Adding mouse locking to Lime

I wanted to add mouse locking support to Lime, and I have successfully done so in my fork, but it isn’t quite useful yet. The onMouseMove function in Module reports only the current position of the mouse, and not the relative motion. The mouse properly gets trapped within the window and is hidden, but once it reaches the edge it simply gets stuck there and there’s no way (that I’m aware of) to get the movements of the mouse past that.

The SDL Wiki claims that setting the relative mouse mode still allows the mouse to report relative movements when the mouse has reached the edges of the window, so it should be relatively (ha) simple to set up.

However, I’m stuck. I got as far as finding this in ExternalInterface.cpp, but I don’t know where to look next.

value lime_mouse_event_manager_register (value callback, value eventObject) {
    MouseEvent::callback = new AutoGCRoot (callback);
    MouseEvent::eventObject = new AutoGCRoot (eventObject);
    return alloc_null ();

Where/how does Lime handle SDL events/how should I go about exposing relative mouse movement in Lime?


The first part is whether we want to use different events (such as onMouseMoveRelative) or re-use our existing events, but change the meaning of the x and y values to be relative (and not absolute).

I’m leaning toward re-using the same events. I’d like the native code to match with whatever we use on the higher-level API, so if we re-use the x and y we should do it in C++ as well.

You can see where it is set here for SDL:

Above this code is where the mouseEvent.type is set, and here the button and position. We would need a flag to track whether we are in relative mouse mode, and if so, we should use the xrel and yrel values instead of x and y from the SDL event object.

Great! I’ll get to work.

A couple questions about implementation though: currently the function for ‘locking’ the mouse is lime.Mouse.setRelative(value:Bool) since the corresponding SDL function is SDL_SetRelativeMouseMode. My first instinct was to add the flag as lime.Mouse.relative but that makes the difference between the two very unclear.

Maybe a lime.Mouse.relativeMode attribute and a lime.Mouse.relativeEvents attribute?

edit: Oh, I just remembered why relative is a function and not an attribute: the SDL function returns 0 on success and -1 on error. Would it make more sense to make it an attribute and have Lime put something into the console when it isn’t supported? And similarly, should Lime do anything if the mouse bits that I’ve added in my fork (lime.ui.Mouse.warpGlobal(200,40), window.warpMouse(20,40)) are used outside of native?

Perhaps it could be lime.ui.Mouse.lock

A getter/setter can then use lime_mouse_set_lock or lime_mouse_get_lock

It’s tough to decide sometimes, I like “lock” as a convention, but I still don’t know if we should re-use the same mouse events, or dispatch relative ones

I thought about it, and I think it might make more sense to dispatch relative ones. At some point someone is going to want both at the same time, and having both doesn’t change anything for people that just want either.

Is there any update on this?
I’m currently using stage.mouseLock and e.movementX to get relative mouse co-ordinates when in full screen mode.
Only works when targeting flash though, would be nice to get this feature on html and windows.

It was merged years ago, not sure if it still works/works the same way.

Sorry for being a noob, but how do you use it?
I can’t find documentation and there’s no comments in the classes themselves.

lime.Mouse.lock, a boolean that hides the cursor and prevents it from leaving the window. AFAIK there isn’t a way to keep the cursor from being hidden using SDL_SetRelativeMouseMode
lime.Mouse.globalWarp, a function that warps the cursor anywhere in screen space
window.warpMouse, a function that warps the cursor anywhere in window space

Basic is to just Set Mouse lock by
lime.ui.Mouse.lock = true;

Ok I figured out how to capture relative mouse co-ordinates but Mouse.lock = true; doesn’t seem to do anything.

And how is Mouse.warp() supposed to work?
Do you give it the co-ordinates you want the mouse to be at or the amount you want it to move by?

I believe Mouse.lock () (in Lime) is correct, Mouse.warp () is different than you want – it moves the system mouse cursor to an absolute screen position.

I think we need to add support in OpenFL for dispatching relative mouse move events, and for stage.mouseLock to enable it.

stage.window.onMouseMoveRelative.add (function (dx, dy) { });

I think the above might work for now, without better support

I created an issue:

Yeah, turns out I had it right, it just wasn’t working until I compiled to windows.
herp derp
thanks anyway

So it works on Windows, but not HTML5? Thanks :slight_smile: