Lemur: request/release cursor API

Just a heads up on a new feature coming in the next release (whenever that is) that is also a potentially breaking change for some apps. It may affect you now if you build from source.

Note: it tries really hard to be backwards compatible so most people should be unaffected… and if you build from source and ARE affected then I’d surely like to know about it even if the ultimate solution is to tell you the work-around.

Feature: Better cursor enable/disable management

It’s long been a frustration of mine that the only way to turn on and off picking was as a global application true/false. It makes it really hard to manage nested popup windows that may or may not be opened in a particular order.

For example, popping open inventory should enable the cursor and closing it again should disable it.

But popping open your character sheet should also enable the cursor and closing it again should disable it.

…so what if you pop open the inventory and character sheet at the same time?

What if a warning message is opened while all of that is going on?

Solution:
Things that require the cursor can now request it. When they are done, they release it.

If any requests are still active then the cursor (and picking) stays enabled.

GuiGlobals.getInstance().requestCursorEnabled(this);
GuiGlobals.getInstance().releaseCursorEnabled(this);

Where “this” is the owner you want tied to the particular request.

Lemur popups such as the PopupState and the OptionPanelState have been modified to use this… which is super cool because previously popping up in-app messages while in “FPS mode” was a real pain in the neck.

To make this backwards compatible with applications that previously called GuiGlobals.getInstance().setCursorEnabled(true/false), this call has been modified to internally request/release using GuiGlobals.getInstance() as the owner.

So mostly things will continue to work as they always did… except now you also have the ability to use request/release.

There are some exceptions to the above that may break your application in certain cases… though I suspect mostly in the case of trying to work around the lack of this feature.

Probable breaking things:

  • if you manage your InputManager.setCursorVisible() state separately from Lemur’s picking state in some potentially complicated way then it may be possible to somehow get out of sync, this is especially true…
  • if you tend to call setCursorEnabled(true) multiple times before calling setCursorEnabled(false) and/or vice-versa in a way that these calls do not evenly match up. Especially if you expect them to always call through to InputManager.setCursorVisible().

If that’s the case, I’d still like to see if there is some easy way we can fix your app now that there is a better way… but barring that, there is a new GuiGlobals.setCursorEnabled() method that takes an additional “force” flag. Setting that flag to true will cause the old non-request/release behavior. Just note that if you use Lemur popups then they may mess you up now.

If this turns out to be a widespread problem, I’m not against supporting some kind of global property to turn the new feature off… but it would be a real shame.

Anyway, typical usage for the "new way would be something like:

public class MyWindowAppState extends BaseAppState {
    ...blah  blah...

    protected void onEnable() {
        ...code to show the window etc...
        GuiGlobals.getInstance().requestCursorEnabled(this);
    }

    protected void onDisable() {
        ...code to hide the window etc...
        GuiGlobals.getInstance().releaseCursorEnabled(this);
    }
}

And magic happens.

And a ton of really weird gymnastics are avoided in application code.

5 Likes