解释如何锁定光标并为 x11、winAPI、cocoa 和 emscrIPten 启用原始鼠标输入的教程。
介绍
rgfw 是一个轻量级单头窗口库,其源代码可以在这里找到。
本教程基于其源代码。
当您创建锁定光标的应用程序时,例如带有第一人称相机的游戏,能够禁用光标非常重要。
这意味着将光标锁定在屏幕中间并获取原始输入。
此方法的唯一替代方法是在鼠标移动时将鼠标拉回到窗口的中心。然而,这是一个 hack,所以它可能有错误
并且不适用于所有操作系统。因此,使用原始输入正确锁定鼠标非常重要。
本教程解释了 rgfw 如何处理原始鼠标输入,以便您可以了解如何自己实现它。
概述
所需步骤的快速概述
- 锁定光标
- 将光标居中
- 启用原始输入
- 处理原始输入
- 禁用原始输入
- 解锁光标
当用户要求 rgfw 保持光标时,rgfw 启用一个表示光标已保持的位标志。
1 |
|
第 1 步(锁定光标)
在 x11 上,可以通过 xgrabpointer 抓取光标来锁定光标
1 |
|
这使窗口可以完全控制指针。
在 windows 上,clipcursor 将光标锁定到屏幕上的特定矩形。
这意味着我们必须在屏幕上找到窗口矩形,然后将鼠标夹到该矩形上。
还使用:geTCLientrect) 和 clienttoscreen
1 2 3 4 5 6 7 8 9 10 |
|
在 macos 和 emscripten 上,启用原始输入的功能也会锁定光标。所以我将在步骤 4 中了解它的功能。
步骤2(将光标置于中心)
光标锁定后,应居中于屏幕中间。
这可确保光标锁定在正确的位置,不会干扰其他任何内容。
rgfw 使用名为 rgfw_window_movemouse 的 rgfw 函数将鼠标移动到窗口中间。
在x11上,xwarppointer可用于将光标移动到窗口中心
1 |
|
在windows上,使用setcursorpos
1 |
|
在 macos 上,使用 cgwarpmousecursorposition
1 |
|
在 emscripten 上,rgfw 不移动鼠标。
步骤 3(启用原始输入)
对于 x11,xi 用于启用原始输入
1 2 3 4 5 6 7 8 9 10 11 12 |
|
在 windows 上,您需要设置 rawinputdevice 结构并使用 registerrawinputdevices 启用它
1 2 |
|
在 macos 上你只需要运行 cgassociatemouseandmousecursorposition
这还通过解除鼠标光标和鼠标移动的关联来锁定光标
1 |
|
在 emscripten 上你只需要请求用户锁定指针
1 |
|
步骤 4(处理原始输入事件)
这些都发生在事件循环期间。
对于x11,您必须处理普通的motionnotify,手动将输入转换为原始输入。
要检查原始鼠标输入事件,您需要使用 genericevent。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
在 windows 上,您只需要处理 wm_input 事件并检查原始运动输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
在 macos 上,您可以正常检查鼠标输入,同时使用 deltax 和 deltay 获取和翻转鼠标点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
在 emscripten 上,可以像平常一样检查鼠标事件,除了我们要使用和翻转 e->movementx/y
1 2 3 4 5 6 7 |
|
步骤 5(禁用原始输入)
最后,rgfw 允许禁用原始输入并解锁光标以恢复正常的鼠标输入。
首先,rgfw 禁用位标志。
1 |
|
在x11中,首先,你必须创建一个带有空白掩码的结构。
这将禁用原始输入。
1 2 3 4 5 6 7 |
|
对于 windows,您可以使用 ridev_remove 传递原始输入设备结构来禁用原始输入。
1 2 |
|
在 macos 和 emscripten 上,解锁光标也会禁用原始输入。
第6步(解锁光标)
在x11上,xungrabpoint用于解锁光标。
1 |
|
在 windows 上,将 null 矩形指针传递给 clipcursor 以指向光标。
1 |
|
在 macos 上,关联鼠标光标和鼠标移动将禁用原始输入并解锁光标
1 |
|
在 emscripten 上,退出指针锁定将解锁光标并禁用原始输入。
1 |
|
完整代码示例
x11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
|
维纳皮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
|