jMonkeyEngine-Contributions / Lemur

Lemur is a jMonkeyEngine-based UI toolkit.
http://jmonkeyengine-contributions.github.io/Lemur/
BSD 3-Clause "New" or "Revised" License
116 stars 32 forks source link

Missing mouse click event when closing a popup. #98

Open eugen-paul opened 4 years ago

eugen-paul commented 4 years ago

I create and show a popup with the property ClickMode=Close. A click outside of the popup on another Lemur-GUI-Element will close the current popup and a MouseButtonEvent=pressed pass through to the real UI (to the JME analog listener) not to the Lemur-GUI-Element. But the MouseButtonEvent=release will be catched by Lemur-GUI-Element and will be not pass through to the JME. Thats why the MouseButtonEvent=pressed will be triggered by each update loop.

Example: Click on "Open Popup" button two times. The message "MouseInput.BUTTON_LEFT" will be continuously logged on the console until you click somewhere.

import com.jme3.app.SimpleApplication;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Command;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.event.PopupState;

public class TestPopup extends SimpleApplication {
  public static void main(String[] args) {
    TestPopup app = new TestPopup();
    app.start();
  }

  @Override
  public void simpleInitApp() {
    GuiGlobals.initialize(this);

    Container myWindow = new Container();
    getGuiNode().attachChild(myWindow);

    myWindow.setLocalTranslation(0, getContext().getSettings().getHeight(), 0);

    Button startButton = myWindow.addChild(new Button("Open Popup"));
    startButton.addClickCommands(new Command<Button>() {
      @Override
      public void execute(Button source) {
        Button popUpButton = new Button("don't click on me");
        popUpButton.setLocalTranslation(300, getContext().getSettings().getHeight(), 0);
        PopupState popupState = GuiGlobals.getInstance().getPopupState();
        popupState.showPopup(popUpButton);
      }
    });

    initKeys();
  }

  private void initKeys() {
    inputManager.addMapping("mouseClick", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
    // Add the names to the action listener.
    inputManager.addListener(analogListener, "mouseClick");
  }

  private final AnalogListener analogListener = new AnalogListener() {
    @Override
    public void onAnalog(String name, float value, float tpf) {
      if (name.equals("mouseClick")) {
        System.out.println("MouseInput.BUTTON_LEFT.");
      }
    }
  };
}
pspeed42 commented 4 years ago

Note: I'm not ignoring this report but every time I read it, I'm not sure what to do about yet and then life gets in the way again.

Curious if it would also happen if the mouse click was handled with Lemur's InputMapper instead of JME's cludgy InputManager. I assume it would, though.

eugen-paul commented 4 years ago

When describing "PopupState.ClickMode=Close" it says that "A click outside of the current popup will close the current popup and the event will otherwise propagate to whatever was below.". But when I click a button (or another GUI element) that is behind the popup, the popup is closed. The event (MouseButtonEvent = pressed) is not caught by the button, but passed on directly to the JME's InputManager. Since a click consists of two events, the second event (MouseButtonEvent = release) is intercepted by the button.

I expected that both events would be handled by the button in this case. In my example, if you click on the "Open Popup" button while a popup is open, then only the current popup is closed but no new popup is opened.

pspeed42 commented 1 year ago

There is some weirdness with event delivery in the case of the popup blockers. It's frustrating because I really do want that first 'down' event to be passed on but it would require a sensitive refactoring of the mouse propagation code.

So to me your issue is kind of a real one but it's just difficult to accomplish a fix. I'm going to leave it open.