【问题标题】:LWJGL grabbed mouse - debug if application hangs or when breakpoint hits with grabbed mouseLWJGL 抓取鼠标 - 如果应用程序挂起或使用抓取的鼠标命中断点时进行调试
【发布时间】:2023-03-20 18:51:01
【问题描述】:

我有一个有时会随机挂起的 LWJGL 程序 (LWJGL 2.9.0)。调试的问题是鼠标总是被抓住。在 Windows 上,可以毫无问题地恢复鼠标,但在 linux(我使用 linux Kubuntu)上,我知道恢复鼠标的唯一方法是停止应用程序。当鼠标被抓住时断点命中时也会发生同样的问题。

使用 netbeans 调试模式,我可以随时暂停应用程序并获取一些信息,但是当应用程序挂起时,鼠标不再起作用(没有光标)。是否可以在不停止应用程序或仅使用键盘进行调试的情况下恢复鼠标?

【问题讨论】:

标签: java linux debugging lwjgl freeze


【解决方案1】:

到目前为止,我已经找到了 5 个解决这个问题的方法:

  1. 根据您的 IDE 和操作系统,这可能会或可能不会起作用 - 如果您能够切换到 IDE 窗口,您可以尝试使用键盘快捷键暂停执行,然后评估表达式 松开鼠标。在这种情况下,您需要评估的表达式是 Mouse.setGrabbed(false)。当断点命中并且您的鼠标卡在 LWJGL 窗口中时,这也很有用。因为我第一次问这个问题,所以我切换到 IntelliJ IDEA,所以这里是如何在那个 IDE 中执行此操作:alt+u 打开“运行”菜单,然后选择“暂停”,然后使用 F7 或 F8 进一步单步执行代码,然后再次按 alt+u 并选择“评估表达式”。

  2. 配置断点以评估Mouse.setGrabbed(false)

    或者,您可以设置断点并使用取消鼠标抓取的代码应用条件,例如: 包 com.acne;

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

    然后将断点条件设置为com.acne.DebugHelper.restoreMouse()

  3. 远程调试 - 如果您可以访问第二台机器并且知道在启动程序之前需要远程调试,那么这是一个很好的解决方案。

    在第一台计算机上以调试模式启动它并在第二台计算机上附加调试器。

  4. [仅限 Linux] 通过启动第二个 X 会话

    使用 ctrl+alt+Fn 切换到 tty1/2/...(例如 ctr+alt+F1 用于 tty1),登录并运行命令 startx。这应该在您所在的 tty 或 tty8 中启动新的 X 会话。您可以使用 ctrl+alt+Fn(通常是 F7 和 F8)在图形环境之间切换。

    很遗憾,如果您的应用程序占用太多内存以至于您无法运行第二个 X 会话,这不是一个好的解决方案。

  5. [仅限 Linux] 您可以添加第二个鼠标指针。您的 LWJGL(或 OpenGL)应用程序将只抓取一个鼠标指针,而您将拥有第二个鼠标指针。

    不幸的是,大多数窗口管理器并没有正式支持多鼠标指针,但这并不意味着它不起作用。它确实有效,但有一些令人讨厌的故障。

    您可以使用 xinput 添加第二个鼠标指针:

    • 运行xinput create-master pointer-name。第二个鼠标指针应出现在屏幕上。这将创建键盘/指针对,您无需对添加的第二个键盘执行任何操作。它不会连接到任何物理设备。
    • 运行xinput list 列出您的所有设备

      在我的笔记本电脑上是这样的:

      ⎡ 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)]
      

      新添加的鼠标指针(主设备)的 id=15。我有一个触摸板和一个外接鼠标,因此我可以将其中一个连接到新光标,并将另一个连接到旧光标。如果您没有 2 个物理设备 - 您可以留下没有连接物理设备的旧指针。

    • 现在运行xinput reattach slave-device-id master-device-id。例如,如果我想将触摸板附加到新指针:xinput reattach 14 15

      在这之后你应该可以控制新添加的指针了。

    • 当您不再希望第二个鼠标指针使用 xinput remove-master master-device-id 时,在我的情况下是 xinput remove-master 15

    • 有时您可能需要将设备重新连接到之前的主设备。

      注意:最好在开始调试之前添加新指针。 我还注意到一些窗口管理器在多个光标方面存在一些问题,这些问题会导致各种意外错误——例如“打字停止工作”,或者打字工作但在错误的窗口中。因此,正常启用多个游标可能不是一个好的选择。

【讨论】:

  • 这可以让我独立控制我的两只鼠标(是的,我每边都有一只,有时我用左手(主要在游戏中)其他右手),显示 2 个鼠标指针?如果你愿意,我可以把它变成一个完整的问题,谢谢! :),顺便说一句,这迫使 unix.stackexchange.com/a/40472/30352
  • 它实际上确实是这样工作的,但我知道没有正式支持 2 个光标的窗口管理器/桌面环境,使用其中 2 个光标的体验可能不是很好。它主要是“工作”,但有时会导致奇怪的故障,并且只有一个活动窗口。另外我已经 triec 那个 ungrab 键,我没有运行它之前的命令,但只是使用 xdotool 没有做任何事情。
  • 这就是重点,setxkbmap 将允许它工作,在这里它也没有它!
【解决方案2】:

为了完整起见: 如果您发现自己陷入困境并且非常不想停止调试,您可以在代码中的某处添加此 sn-p:

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

然后通过调试命令执行它。
例如在 Eclipse 中:
使用Run>Execute(默认快捷方式:Ctrl+U)或Run>Display(默认快捷方式:Ctrl+Shift+D

它可能并不总是有效,但它可能会为您节省一个调试会话。
[不要忘记再次从您的代码中删除它;)]

【讨论】:

  • 问题是通常当它发生时我的代码已经到达断点并且我没有鼠标光标并且不知道/没有为“评估表达式”配置键盘快捷键。但是使用工作键盘我仍然可以启动终端并运行一些命令来启用第二个光标。另一种方法是配置断点以评估 Mouse.setGrabbed(false)。
  • @Barteks2x 你试过my answer 吗?在始终被评估的监视表达式上使用它(只要它可见且未最小化)
  • @founderio 这很好,因为完整的包名很重要,可以在任何断点发生的地方找到它
猜你喜欢
  • 2018-12-05
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多