使用 Core Graphics 在 macOS 上生成相对鼠标事件
Generating relative mouse events on macOS using Core Graphics
我正在使用 Core Graphics 框架来生成鼠标事件。我希望能够正常移动鼠标并在 FPS 游戏中移动鼠标。我遇到的问题是这两种情况似乎需要不同的事件。
我可以使用以下命令将鼠标移出游戏。
// Event source was created with this:
// CGEventSourceCreate(kCGEventSourceStateCombinedSessionState)
CGPoint mouse_location(CGEventSourceRef source) {
CGEventRef event = CGEventCreate(source);
CGPoint loc = CGEventGetLocation(event);
CFRelease(event);
}
void mouse_move_relative(CGEventSourceRef source, int x, int y) {
CGPoint pos = mouse_location(source);
pos.x += x;
pos.y += y;
CGEventRef event = CGEventCreateMouseEvent(source, kCGEventMouseMoved, loc, kCGMouseButtonLeft);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, x);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, y);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
这在游戏外有效,但在游戏内,鼠标似乎碰到屏幕边缘并停止。所以我尝试在不设置位置的情况下使用增量。
void mouse_move_relative(CGEventSourceRef source, int x, int y) {
CGEventRef event = CGEventCreate(source);
CGEventSetType(event, kCGEventMouseMoved);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber, kCGMouseButtonLeft);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, x);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, y);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
这在游戏内有效,鼠标不会碰到屏幕边缘,但在游戏外鼠标不会移动。如果我在游戏中打开菜单屏幕,我就不能再移动鼠标了。对于这两种情况,我需要两个单独的代码路径或两个单独的模式。我试图避免在模式之间切换并想知道这是否可能。
我能否生成适用于两种情况的鼠标事件?
也许有一些方法可以告诉我系统何时进入相对鼠标模式并相应地更改发出的事件?我不确定 Core Graphics 是否可以做到这一点(或者这是否有意义)。另外,我不完全明白 kCGHIDEventTap
和 kCGEventSourceStateCombinedSessionState
是什么意思。文档在谈论水龙头和桌子,但我不太明白。也许我需要做的就是改变其中一个......?
请注意,上面的代码片段可能不太正确,因为我在 Rust 中使用了一个包装器库,但这不是重点。
原来很简单。我需要做的就是将鼠标坐标限制在显示范围内。
CGDirectDisplayID display = CGMainDisplayID();
size_t width = CGDisplayPixelsWide(display);
size_t height = CGDisplayPixelsHigh(display);
pos.x = min(max(pos.x, 0), width - 1);
pos.y = min(max(pos.y, 0), height - 1);
我正在使用 Core Graphics 框架来生成鼠标事件。我希望能够正常移动鼠标并在 FPS 游戏中移动鼠标。我遇到的问题是这两种情况似乎需要不同的事件。
我可以使用以下命令将鼠标移出游戏。
// Event source was created with this:
// CGEventSourceCreate(kCGEventSourceStateCombinedSessionState)
CGPoint mouse_location(CGEventSourceRef source) {
CGEventRef event = CGEventCreate(source);
CGPoint loc = CGEventGetLocation(event);
CFRelease(event);
}
void mouse_move_relative(CGEventSourceRef source, int x, int y) {
CGPoint pos = mouse_location(source);
pos.x += x;
pos.y += y;
CGEventRef event = CGEventCreateMouseEvent(source, kCGEventMouseMoved, loc, kCGMouseButtonLeft);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, x);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, y);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
这在游戏外有效,但在游戏内,鼠标似乎碰到屏幕边缘并停止。所以我尝试在不设置位置的情况下使用增量。
void mouse_move_relative(CGEventSourceRef source, int x, int y) {
CGEventRef event = CGEventCreate(source);
CGEventSetType(event, kCGEventMouseMoved);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber, kCGMouseButtonLeft);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, x);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, y);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
这在游戏内有效,鼠标不会碰到屏幕边缘,但在游戏外鼠标不会移动。如果我在游戏中打开菜单屏幕,我就不能再移动鼠标了。对于这两种情况,我需要两个单独的代码路径或两个单独的模式。我试图避免在模式之间切换并想知道这是否可能。
我能否生成适用于两种情况的鼠标事件?
也许有一些方法可以告诉我系统何时进入相对鼠标模式并相应地更改发出的事件?我不确定 Core Graphics 是否可以做到这一点(或者这是否有意义)。另外,我不完全明白 kCGHIDEventTap
和 kCGEventSourceStateCombinedSessionState
是什么意思。文档在谈论水龙头和桌子,但我不太明白。也许我需要做的就是改变其中一个......?
请注意,上面的代码片段可能不太正确,因为我在 Rust 中使用了一个包装器库,但这不是重点。
原来很简单。我需要做的就是将鼠标坐标限制在显示范围内。
CGDirectDisplayID display = CGMainDisplayID();
size_t width = CGDisplayPixelsWide(display);
size_t height = CGDisplayPixelsHigh(display);
pos.x = min(max(pos.x, 0), width - 1);
pos.y = min(max(pos.y, 0), height - 1);