[macOS, 3.2] Implement confined mouse mode.
This commit is contained in:
parent
44a516986d
commit
b233cb640d
|
@ -65,6 +65,13 @@ public:
|
||||||
uint32_t unicode;
|
uint32_t unicode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WarpEvent {
|
||||||
|
NSTimeInterval timestamp;
|
||||||
|
NSPoint delta;
|
||||||
|
};
|
||||||
|
List<WarpEvent> warp_events;
|
||||||
|
NSTimeInterval last_warp = 0;
|
||||||
|
|
||||||
Vector<KeyEvent> key_event_buffer;
|
Vector<KeyEvent> key_event_buffer;
|
||||||
int key_event_pos;
|
int key_event_pos;
|
||||||
|
|
||||||
|
|
|
@ -716,12 +716,58 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
|
||||||
|
|
||||||
- (void)mouseMoved:(NSEvent *)event {
|
- (void)mouseMoved:(NSEvent *)event {
|
||||||
|
|
||||||
|
NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
|
||||||
|
NSPoint mpos = [event locationInWindow];
|
||||||
|
|
||||||
|
if (OS_OSX::singleton->mouse_mode == OS::MOUSE_MODE_CONFINED) {
|
||||||
|
// Discard late events
|
||||||
|
if (([event timestamp]) < OS_OSX::singleton->last_warp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warp affects next event delta, subtract previous warp deltas
|
||||||
|
List<OS_OSX::WarpEvent>::Element *F = OS_OSX::singleton->warp_events.front();
|
||||||
|
while (F) {
|
||||||
|
if (F->get().timestamp < [event timestamp]) {
|
||||||
|
List<OS_OSX::WarpEvent>::Element *E = F;
|
||||||
|
delta.x -= E->get().delta.x;
|
||||||
|
delta.y -= E->get().delta.y;
|
||||||
|
F = F->next();
|
||||||
|
OS_OSX::singleton->warp_events.erase(E);
|
||||||
|
} else {
|
||||||
|
F = F->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confine mouse position to the window, and update delta
|
||||||
|
NSRect frame = [OS_OSX::singleton->window_object frame];
|
||||||
|
NSPoint conf_pos = mpos;
|
||||||
|
conf_pos.x = CLAMP(conf_pos.x + delta.x, 0.f, frame.size.width);
|
||||||
|
conf_pos.y = CLAMP(conf_pos.y - delta.y, 0.f, frame.size.height);
|
||||||
|
delta.x = conf_pos.x - mpos.x;
|
||||||
|
delta.y = mpos.y - conf_pos.y;
|
||||||
|
mpos = conf_pos;
|
||||||
|
|
||||||
|
// Move mouse cursor
|
||||||
|
NSRect pointInWindowRect = NSMakeRect(conf_pos.x, conf_pos.y, 0, 0);
|
||||||
|
conf_pos = [[OS_OSX::singleton->window_view window] convertRectToScreen:pointInWindowRect].origin;
|
||||||
|
conf_pos.y = CGDisplayBounds(CGMainDisplayID()).size.height - conf_pos.y;
|
||||||
|
CGWarpMouseCursorPosition(conf_pos);
|
||||||
|
|
||||||
|
// Save warp data
|
||||||
|
OS_OSX::singleton->last_warp = [[NSProcessInfo processInfo] systemUptime];
|
||||||
|
OS_OSX::WarpEvent ev;
|
||||||
|
ev.timestamp = OS_OSX::singleton->last_warp;
|
||||||
|
ev.delta = delta;
|
||||||
|
OS_OSX::singleton->warp_events.push_back(ev);
|
||||||
|
}
|
||||||
|
|
||||||
Ref<InputEventMouseMotion> mm;
|
Ref<InputEventMouseMotion> mm;
|
||||||
mm.instance();
|
mm.instance();
|
||||||
|
|
||||||
mm->set_button_mask(button_mask);
|
mm->set_button_mask(button_mask);
|
||||||
const CGFloat backingScaleFactor = [[event window] backingScaleFactor];
|
const CGFloat backingScaleFactor = [[event window] backingScaleFactor];
|
||||||
const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor);
|
const Vector2 pos = get_mouse_pos(mpos, backingScaleFactor);
|
||||||
mm->set_position(pos);
|
mm->set_position(pos);
|
||||||
mm->set_pressure([event pressure]);
|
mm->set_pressure([event pressure]);
|
||||||
if ([event subtype] == NSEventSubtypeTabletPoint) {
|
if ([event subtype] == NSEventSubtypeTabletPoint) {
|
||||||
|
@ -730,9 +776,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
|
||||||
}
|
}
|
||||||
mm->set_global_position(pos);
|
mm->set_global_position(pos);
|
||||||
mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed());
|
mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed());
|
||||||
Vector2 relativeMotion = Vector2();
|
const Vector2 relativeMotion = Vector2(delta.x, delta.y) * OS_OSX::singleton->_mouse_scale(backingScaleFactor);
|
||||||
relativeMotion.x = [event deltaX] * OS_OSX::singleton -> _mouse_scale(backingScaleFactor);
|
|
||||||
relativeMotion.y = [event deltaY] * OS_OSX::singleton -> _mouse_scale(backingScaleFactor);
|
|
||||||
mm->set_relative(relativeMotion);
|
mm->set_relative(relativeMotion);
|
||||||
get_key_modifier_state([event modifierFlags], mm);
|
get_key_modifier_state([event modifierFlags], mm);
|
||||||
|
|
||||||
|
@ -2042,7 +2086,9 @@ void OS_OSX::warp_mouse_position(const Point2 &p_to) {
|
||||||
CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0);
|
CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0);
|
||||||
CGAssociateMouseAndMouseCursorPosition(false);
|
CGAssociateMouseAndMouseCursorPosition(false);
|
||||||
CGWarpMouseCursorPosition(lMouseWarpPos);
|
CGWarpMouseCursorPosition(lMouseWarpPos);
|
||||||
CGAssociateMouseAndMouseCursorPosition(true);
|
if (mouse_mode != MOUSE_MODE_CONFINED) {
|
||||||
|
CGAssociateMouseAndMouseCursorPosition(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3093,11 +3139,15 @@ void OS_OSX::set_mouse_mode(MouseMode p_mode) {
|
||||||
CGDisplayHideCursor(kCGDirectMainDisplay);
|
CGDisplayHideCursor(kCGDirectMainDisplay);
|
||||||
}
|
}
|
||||||
CGAssociateMouseAndMouseCursorPosition(true);
|
CGAssociateMouseAndMouseCursorPosition(true);
|
||||||
|
} else if (p_mode == MOUSE_MODE_CONFINED) {
|
||||||
|
CGDisplayShowCursor(kCGDirectMainDisplay);
|
||||||
|
CGAssociateMouseAndMouseCursorPosition(false);
|
||||||
} else {
|
} else {
|
||||||
CGDisplayShowCursor(kCGDirectMainDisplay);
|
CGDisplayShowCursor(kCGDirectMainDisplay);
|
||||||
CGAssociateMouseAndMouseCursorPosition(true);
|
CGAssociateMouseAndMouseCursorPosition(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
warp_events.clear();
|
||||||
mouse_mode = p_mode;
|
mouse_mode = p_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue