I have a LWJGL program (LWJGL 2.9.0) that sometimes randomly hangs. The problem with debugging it is that mouse is always grabbed. On Windows it's possible to get mouse back without any issues, but on linux (I use linux Kubuntu) the only way I know to get mouse back is to stop the application. The same issue happens when a breakpoint hits when mouse is grabbed.
Using netbeans debug mode I can pause application and get some information at any time, but when the application hangs mouse no longer works (there is no cursor). Is it possible to get the mouse back without stopping the application or debug using only keyboard?
So far I have found 5 solutions to this problem:
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".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()
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.
[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.
[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 devicesOn 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 bexinput 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.
- Run
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 ;)]
来源:https://stackoverflow.com/questions/23795010/lwjgl-grabbed-mouse-debug-if-application-hangs-or-when-breakpoint-hits-with-gr