LWJGL grabbed mouse - debug if application hangs or when breakpoint hits with grabbed mouse

冷暖自知 提交于 2019-12-05 14:43:09

So far I have found 5 solutions to this problem:

  1. This may or may not work depending on your IDE and operating system - if you are able to switch into the IDE window you can try to use keyboard shortcuts to pause execution and then evaluate expression to ungrab the mouse. The expression you need to evaluate in that case is Mouse.setGrabbed(false). This is also useful when breakpoint hits and your mouse is stuck within LWJGL window. Since I first asked this question I switched to IntelliJ IDEA so here is how to do it in that IDE: alt+u to open "run" menu, then select "pause", then step through the code one line further using F7 or F8, and then press alt+u again and select "evaluate expression".

  2. Configure breakpoint to evaluate Mouse.setGrabbed(false).

    Alternatively you can set a breakpoint and apply a condition with code that ungrabs the mouse, for example: package com.acne;

    import org.lwjgl.input.Mouse;
    
    public class DebugHelper {
        public static boolean restoreMouse() {
            Mouse.setGrabbed(false);
            return true;
        }
    }
    

    Then set your breakpoint condition to com.acne.DebugHelper.restoreMouse()

  3. Remote debugging - good solution if you have access to a second machine and know that you will need remote debugging before starting your program.

    On the first computer start it in debug mode and attach the debugger on the second computer.

  4. [linux only] By starting second X session

    Switch to tty1/2/... using ctrl+alt+Fn (for example ctr+alt+F1 for tty1), login and run command startx. This should start new X session, eighter in the tty you are in or in tty8. The you can switch between graphical environments using ctrl+alt+Fn (usially F7 and F8).

    Unfortunately this is not a good solution if your application takes so much memory that you can't run second X session.

  5. [linux only] You can add a second mouse pointer. Your LWJGL (or OpenGL) application will grab only one mouse pointer and you will have the second one for you.

    Unfortunately most window managers don't officially support multiple mouse pointers, but it doesn't mean that it doesn't work. It does work, but there are some annoying glitches.

    You can add a second mouse pointer using xinput:

    • Run xinput create-master pointer-name. A second mouse pointer should appear on the screen. This creates keyboard/pointer pair, you don't need to do anything with the second added keyboard. It won't be attached to any physical device.
    • Run xinput list to list all your devices

      On my laptop it looks like this:

      ⎡ Virtual core pointer                      id=2    [master pointer  (3)]
      ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
      ⎜   ↳ ETPS/2 Elantech Touchpad                  id=14   [slave  pointer  (2)]
      ⎜   ↳ A4Tech USB Mouse                          id=11   [slave  pointer  (2)]
      ⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
          ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
          ↳ Power Button                              id=6    [slave  keyboard (3)]
          ↳ Video Bus                                 id=7    [slave  keyboard (3)]
          ↳ Video Bus                                 id=8    [slave  keyboard (3)]
          ↳ Power Button                              id=9    [slave  keyboard (3)]
          ↳ Lenovo EasyCamera                         id=10   [slave  keyboard (3)]
          ↳ Ideapad extra buttons                     id=12   [slave  keyboard (3)]
          ↳ AT Translated Set 2 keyboard              id=13   [slave  keyboard (3)]
      ⎡ new-mouse pointer                         id=15   [master pointer  (16)]
      ⎜   ↳ new-mouse XTEST pointer                   id=17   [slave  pointer  (15)]
      ⎣ new-mouse keyboard                        id=16   [master keyboard (15)]
          ↳ new-mouse XTEST keyboard                  id=18   [slave  keyboard (16)]
      

      The newly added mouse pointer (master device) has id=15. I have a touchpad and an external mouse so I can attach one of them to the new cursor and leave the other attached to the old cursor. If you don't have 2 physical devices - you can leave the old pointer with no physical device attached.

    • Now run xinput reattach slave-device-id master-device-id. For example if I want to attach my touchpad to the new pointer: xinput reattach 14 15

      After this you should be able to control the newly added pointer.

    • When you no longer want the second mouse pointer use xinput remove-master master-device-id, in my case it would be xinput remove-master 15

    • sometimes you may need to reattach the device to the previous master device.

      Note: It's better to add the new pointer before you start debugging. I also noticed that some window managers have some issues with multiple cursors that cause all kinds of unexpected bugs - for example "typing stops working", or typing works but in the wrong window. So leaving multiple cursors enabled normally may not be a good option.

For completeness' sake: If you find yourself stuck and desperately don't want to stop debugging, you can add this snippet somewhere in your code:

org.lwjgl.input.Mouse.setGrabbed(false);

then execute it via Debug commands.
For example in Eclipse:
Use Run>Execute (Default shortcut: Ctrl+U) or Run>Display (Default shortcut: Ctrl+Shift+D)

It might not work always, but it might save you a debug session.
[Don't forget to remove it from your code again ;)]

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!