Add fn modifier to modifier keys in gpui and refactor platform events to use a single modifiers struct

K Simmons created

Change summary

Cargo.lock                                 | 39 +++++++++++++
crates/editor/src/element.rs               | 22 ++++---
crates/editor/src/link_go_to_definition.rs | 13 +++-
crates/gpui/Cargo.toml                     |  1 
crates/gpui/src/app.rs                     |  5 -
crates/gpui/src/platform/event.rs          | 42 +++++++-------
crates/gpui/src/platform/mac/event.rs      | 68 +++++++++--------------
crates/gpui/src/platform/mac/window.rs     | 18 +-----
8 files changed, 110 insertions(+), 98 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1160,6 +1160,12 @@ dependencies = [
  "theme",
 ]
 
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
 [[package]]
 name = "core-foundation"
 version = "0.9.3"
@@ -1572,6 +1578,19 @@ dependencies = [
  "byteorder",
 ]
 
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version 0.4.0",
+ "syn",
+]
+
 [[package]]
 name = "dhat"
 version = "0.3.1"
@@ -2388,6 +2407,7 @@ dependencies = [
  "core-graphics",
  "core-text",
  "ctor",
+ "derive_more",
  "dhat",
  "env_logger",
  "etagere",
@@ -3945,7 +3965,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff"
 dependencies = [
- "rustc_version",
+ "rustc_version 0.3.3",
 ]
 
 [[package]]
@@ -4897,7 +4917,16 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
 dependencies = [
- "semver",
+ "semver 0.11.0",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver 1.0.14",
 ]
 
 [[package]]
@@ -5152,6 +5181,12 @@ dependencies = [
  "semver-parser",
 ]
 
+[[package]]
+name = "semver"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+
 [[package]]
 name = "semver-parser"
 version = "0.10.2"

crates/editor/src/element.rs 🔗

@@ -30,8 +30,8 @@ use gpui::{
     platform::CursorStyle,
     text_layout::{self, Line, RunStyle, TextLayoutCache},
     AppContext, Axis, Border, CursorRegion, Element, ElementBox, EventContext, LayoutContext,
-    MouseButton, MouseButtonEvent, MouseMovedEvent, MouseRegion, MutableAppContext, PaintContext,
-    Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
+    Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent, MouseRegion, MutableAppContext,
+    PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
 };
 use json::json;
 use language::{Bias, CursorShape, DiagnosticSeverity, OffsetUtf16, Point, Selection};
@@ -209,10 +209,14 @@ impl EditorElement {
     fn mouse_down(
         MouseButtonEvent {
             position,
-            ctrl,
-            alt,
-            shift,
-            cmd,
+            modifiers:
+                Modifiers {
+                    shift,
+                    ctrl,
+                    alt,
+                    cmd,
+                    ..
+                },
             mut click_count,
             ..
         }: MouseButtonEvent,
@@ -303,8 +307,7 @@ impl EditorElement {
     fn mouse_dragged(
         view: WeakViewHandle<Editor>,
         MouseMovedEvent {
-            cmd,
-            shift,
+            modifiers: Modifiers { cmd, shift, .. },
             position,
             ..
         }: MouseMovedEvent,
@@ -379,8 +382,7 @@ impl EditorElement {
 
     fn mouse_moved(
         MouseMovedEvent {
-            cmd,
-            shift,
+            modifiers: Modifiers { shift, cmd, .. },
             position,
             ..
         }: MouseMovedEvent,
@@ -358,7 +358,7 @@ fn go_to_fetched_definition_of_kind(
 #[cfg(test)]
 mod tests {
     use futures::StreamExt;
-    use gpui::{ModifiersChangedEvent, View};
+    use gpui::{Modifiers, ModifiersChangedEvent, View};
     use indoc::indoc;
     use lsp::request::{GotoDefinition, GotoTypeDefinition};
 
@@ -431,7 +431,10 @@ mod tests {
         cx.update_editor(|editor, cx| {
             editor.modifiers_changed(
                 &gpui::ModifiersChangedEvent {
-                    cmd: true,
+                    modifiers: Modifiers {
+                        cmd: true,
+                        ..Default::default()
+                    },
                     ..Default::default()
                 },
                 cx,
@@ -660,8 +663,10 @@ mod tests {
         cx.update_editor(|editor, cx| {
             editor.modifiers_changed(
                 &ModifiersChangedEvent {
-                    cmd: true,
-                    ..Default::default()
+                    modifiers: Modifiers {
+                        cmd: true,
+                        ..Default::default()
+                    },
                 },
                 cx,
             );

crates/gpui/Cargo.toml 🔗

@@ -20,6 +20,7 @@ sum_tree = { path = "../sum_tree" }
 async-task = "4.0.3"
 backtrace = { version = "0.3", optional = true }
 ctor = "0.1"
+derive_more = "0.99.17"
 dhat = { version = "0.3", optional = true }
 env_logger = { version = "0.9", optional = true }
 etagere = "0.2"

crates/gpui/src/app.rs 🔗

@@ -5777,10 +5777,7 @@ mod tests {
             Event::MouseDown(MouseButtonEvent {
                 position: Default::default(),
                 button: MouseButton::Left,
-                ctrl: false,
-                alt: false,
-                shift: false,
-                cmd: false,
+                modifiers: Default::default(),
                 click_count: 1,
             }),
             false,

crates/gpui/src/platform/event.rs 🔗

@@ -1,3 +1,5 @@
+use derive_more::Deref;
+
 use crate::{geometry::vector::Vector2F, keymap::Keystroke};
 
 #[derive(Clone, Debug)]
@@ -11,12 +13,19 @@ pub struct KeyUpEvent {
     pub keystroke: Keystroke,
 }
 
-#[derive(Clone, Copy, Debug, Default)]
-pub struct ModifiersChangedEvent {
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct Modifiers {
     pub ctrl: bool,
     pub alt: bool,
     pub shift: bool,
     pub cmd: bool,
+    pub fun: bool,
+}
+
+#[derive(Clone, Copy, Debug, Default, Deref)]
+pub struct ModifiersChangedEvent {
+    #[deref]
+    pub modifiers: Modifiers,
 }
 
 /// The phase of a touch motion event.
@@ -28,15 +37,13 @@ pub enum TouchPhase {
     Ended,
 }
 
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default, Deref)]
 pub struct ScrollWheelEvent {
     pub position: Vector2F,
     pub delta: Vector2F,
     pub precise: bool,
-    pub ctrl: bool,
-    pub alt: bool,
-    pub shift: bool,
-    pub cmd: bool,
+    #[deref]
+    pub modifiers: Modifiers,
     /// If the platform supports returning the phase of a scroll wheel event, it will be stored here
     pub phase: Option<TouchPhase>,
 }
@@ -79,25 +86,21 @@ impl Default for MouseButton {
     }
 }
 
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default, Deref)]
 pub struct MouseButtonEvent {
     pub button: MouseButton,
     pub position: Vector2F,
-    pub ctrl: bool,
-    pub alt: bool,
-    pub shift: bool,
-    pub cmd: bool,
+    #[deref]
+    pub modifiers: Modifiers,
     pub click_count: usize,
 }
 
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default, Deref)]
 pub struct MouseMovedEvent {
     pub position: Vector2F,
     pub pressed_button: Option<MouseButton>,
-    pub ctrl: bool,
-    pub cmd: bool,
-    pub alt: bool,
-    pub shift: bool,
+    #[deref]
+    pub modifiers: Modifiers,
 }
 
 impl MouseMovedEvent {
@@ -105,10 +108,7 @@ impl MouseMovedEvent {
         MouseButtonEvent {
             position: self.position,
             button: self.pressed_button.unwrap_or(button),
-            ctrl: self.ctrl,
-            alt: self.alt,
-            shift: self.shift,
-            cmd: self.cmd,
+            modifiers: self.modifiers,
             click_count: 0,
         }
     }

crates/gpui/src/platform/mac/event.rs 🔗

@@ -2,7 +2,7 @@ use crate::{
     geometry::vector::vec2f,
     keymap::Keystroke,
     platform::{Event, NavigationDirection},
-    KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
+    KeyDownEvent, KeyUpEvent, Modifiers, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
     MouseMovedEvent, ScrollWheelEvent, TouchPhase,
 };
 use cocoa::{
@@ -65,6 +65,23 @@ pub fn key_to_native(key: &str) -> Cow<str> {
     Cow::Owned(String::from_utf16(&[code]).unwrap())
 }
 
+unsafe fn read_modifiers(native_event: id) -> Modifiers {
+    let modifiers = native_event.modifierFlags();
+    let ctrl = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
+    let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
+    let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
+    let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
+    let fun = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask);
+
+    Modifiers {
+        ctrl,
+        alt,
+        shift,
+        cmd,
+        fun,
+    }
+}
+
 impl Event {
     pub unsafe fn from_native(native_event: id, window_height: Option<f32>) -> Option<Self> {
         let event_type = native_event.eventType();
@@ -79,20 +96,9 @@ impl Event {
         }
 
         match event_type {
-            NSEventType::NSFlagsChanged => {
-                let modifiers = native_event.modifierFlags();
-                let ctrl = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
-                let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
-                let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
-                let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
-
-                Some(Self::ModifiersChanged(ModifiersChangedEvent {
-                    ctrl,
-                    alt,
-                    shift,
-                    cmd,
-                }))
-            }
+            NSEventType::NSFlagsChanged => Some(Self::ModifiersChanged(ModifiersChangedEvent {
+                modifiers: read_modifiers(native_event),
+            })),
             NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
                 keystroke: parse_keystroke(native_event),
                 is_held: native_event.isARepeat() == YES,
@@ -112,8 +118,6 @@ impl Event {
                     // Other mouse buttons aren't tracked currently
                     _ => return None,
                 };
-                let modifiers = native_event.modifierFlags();
-
                 window_height.map(|window_height| {
                     Self::MouseDown(MouseButtonEvent {
                         button,
@@ -121,10 +125,7 @@ impl Event {
                             native_event.locationInWindow().x as f32,
                             window_height - native_event.locationInWindow().y as f32,
                         ),
-                        ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
-                        alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
-                        shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
-                        cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
+                        modifiers: read_modifiers(native_event),
                         click_count: native_event.clickCount() as usize,
                     })
                 })
@@ -143,24 +144,18 @@ impl Event {
                 };
 
                 window_height.map(|window_height| {
-                    let modifiers = native_event.modifierFlags();
                     Self::MouseUp(MouseButtonEvent {
                         button,
                         position: vec2f(
                             native_event.locationInWindow().x as f32,
                             window_height - native_event.locationInWindow().y as f32,
                         ),
-                        ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
-                        alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
-                        shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
-                        cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
+                        modifiers: read_modifiers(native_event),
                         click_count: native_event.clickCount() as usize,
                     })
                 })
             }
             NSEventType::NSScrollWheel => window_height.map(|window_height| {
-                let modifiers = native_event.modifierFlags();
-
                 let phase = match native_event.phase() {
                     NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
                         Some(TouchPhase::Started)
@@ -180,10 +175,7 @@ impl Event {
                     ),
                     phase,
                     precise: native_event.hasPreciseScrollingDeltas() == YES,
-                    ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
-                    alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
-                    shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
-                    cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
+                    modifiers: read_modifiers(native_event),
                 })
             }),
             NSEventType::NSLeftMouseDragged
@@ -200,32 +192,24 @@ impl Event {
                 };
 
                 window_height.map(|window_height| {
-                    let modifiers = native_event.modifierFlags();
                     Self::MouseMoved(MouseMovedEvent {
                         pressed_button: Some(pressed_button),
                         position: vec2f(
                             native_event.locationInWindow().x as f32,
                             window_height - native_event.locationInWindow().y as f32,
                         ),
-                        ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
-                        alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
-                        shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
-                        cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
+                        modifiers: read_modifiers(native_event),
                     })
                 })
             }
             NSEventType::NSMouseMoved => window_height.map(|window_height| {
-                let modifiers = native_event.modifierFlags();
                 Self::MouseMoved(MouseMovedEvent {
                     position: vec2f(
                         native_event.locationInWindow().x as f32,
                         window_height - native_event.locationInWindow().y as f32,
                     ),
                     pressed_button: None,
-                    ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
-                    alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
-                    shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
-                    cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
+                    modifiers: read_modifiers(native_event),
                 })
             }),
             _ => None,

crates/gpui/src/platform/mac/window.rs 🔗

@@ -981,25 +981,13 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
             }) => {
                 window_state_borrow.synthetic_drag_counter += 1;
             }
-            Event::ModifiersChanged(ModifiersChangedEvent {
-                ctrl,
-                alt,
-                shift,
-                cmd,
-            }) => {
+            Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
                 // Only raise modifiers changed event when they have actually changed
                 if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
-                    ctrl: prev_ctrl,
-                    alt: prev_alt,
-                    shift: prev_shift,
-                    cmd: prev_cmd,
+                    modifiers: prev_modifiers,
                 })) = &window_state_borrow.previous_modifiers_changed_event
                 {
-                    if prev_ctrl == ctrl
-                        && prev_alt == alt
-                        && prev_shift == shift
-                        && prev_cmd == cmd
-                    {
+                    if prev_modifiers == modifiers {
                         return;
                     }
                 }