From 8c228365322cc531857bc2166731f84e6ee2205d Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:08:24 +0200 Subject: [PATCH] [macOS] Handle Trackpad / Magic Mouse swipe events and simulate XBUTTON1 / XBUTTON2 buttons. --- platform/macos/godot_content_view.h | 2 +- platform/macos/godot_content_view.mm | 49 +++++++++++++++++++--------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/platform/macos/godot_content_view.h b/platform/macos/godot_content_view.h index c6060c96c61..dc8d11be541 100644 --- a/platform/macos/godot_content_view.h +++ b/platform/macos/godot_content_view.h @@ -72,7 +72,7 @@ - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor; - (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy; -- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed; +- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed outofstream:(bool)outofstream; - (void)setWindowID:(DisplayServer::WindowID)wid; - (void)updateLayerDelegate; - (void)cancelComposition; diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm index 139411249c7..9406c987c04 100644 --- a/platform/macos/godot_content_view.mm +++ b/platform/macos/godot_content_view.mm @@ -356,7 +356,7 @@ ds->cursor_update_shape(); } -- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed { +- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed outofstream:(bool)outofstream { DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { return; @@ -377,14 +377,18 @@ Ref mb; mb.instantiate(); mb->set_window_id(window_id); - ds->update_mouse_pos(wd, [event locationInWindow]); + if (outofstream) { + ds->update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); + } else { + ds->update_mouse_pos(wd, [event locationInWindow]); + } ds->get_key_modifier_state([event modifierFlags], mb); mb->set_button_index(index); mb->set_pressed(pressed); mb->set_position(wd.mouse_pos); mb->set_global_position(wd.mouse_pos); mb->set_button_mask(last_button_state); - if (index == MouseButton::LEFT && pressed) { + if (!outofstream && index == MouseButton::LEFT && pressed) { mb->set_double_click([event clickCount] == 2); } @@ -394,10 +398,10 @@ - (void)mouseDown:(NSEvent *)event { if (([event modifierFlags] & NSEventModifierFlagControl)) { mouse_down_control = true; - [self processMouseEvent:event index:MouseButton::RIGHT pressed:true]; + [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false]; } else { mouse_down_control = false; - [self processMouseEvent:event index:MouseButton::LEFT pressed:true]; + [self processMouseEvent:event index:MouseButton::LEFT pressed:true outofstream:false]; } } @@ -407,9 +411,9 @@ - (void)mouseUp:(NSEvent *)event { if (mouse_down_control) { - [self processMouseEvent:event index:MouseButton::RIGHT pressed:false]; + [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false]; } else { - [self processMouseEvent:event index:MouseButton::LEFT pressed:false]; + [self processMouseEvent:event index:MouseButton::LEFT pressed:false outofstream:false]; } } @@ -456,7 +460,7 @@ } - (void)rightMouseDown:(NSEvent *)event { - [self processMouseEvent:event index:MouseButton::RIGHT pressed:true]; + [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false]; } - (void)rightMouseDragged:(NSEvent *)event { @@ -464,16 +468,16 @@ } - (void)rightMouseUp:(NSEvent *)event { - [self processMouseEvent:event index:MouseButton::RIGHT pressed:false]; + [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false]; } - (void)otherMouseDown:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - [self processMouseEvent:event index:MouseButton::MIDDLE pressed:true]; + [self processMouseEvent:event index:MouseButton::MIDDLE pressed:true outofstream:false]; } else if ((int)[event buttonNumber] == 3) { - [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:false]; } else if ((int)[event buttonNumber] == 4) { - [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:false]; } else { return; } @@ -485,16 +489,31 @@ - (void)otherMouseUp:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - [self processMouseEvent:event index:MouseButton::MIDDLE pressed:false]; + [self processMouseEvent:event index:MouseButton::MIDDLE pressed:false outofstream:false]; } else if ((int)[event buttonNumber] == 3) { - [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:false]; } else if ((int)[event buttonNumber] == 4) { - [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:false]; } else { return; } } +- (void)swipeWithEvent:(NSEvent *)event { + // Swipe gesture on Trackpad/Magic Mouse, or physical back/forward mouse buttons. + if ([event phase] == NSEventPhaseEnded || [event phase] == NSEventPhaseChanged) { + if (Math::is_equal_approx([event deltaX], 1.0)) { + // Swipe left (back). + [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:true]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:true]; + } else if (Math::is_equal_approx([event deltaX], -1.0)) { + // Swipe right (forward). + [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:true]; + [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:true]; + } + } +} + - (void)mouseExited:(NSEvent *)event { DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) {