diff --git a/crates/eframe/src/web/input.rs b/crates/eframe/src/web/input.rs index eecf7c1f5c54..71586e8f90c4 100644 --- a/crates/eframe/src/web/input.rs +++ b/crates/eframe/src/web/input.rs @@ -151,6 +151,7 @@ pub fn translate_key(key: &str) -> Option { pub fn modifiers_from_kb_event(event: &web_sys::KeyboardEvent) -> egui::Modifiers { egui::Modifiers { + function: event.key() == "Fn", alt: event.alt_key(), ctrl: event.ctrl_key(), shift: event.shift_key(), @@ -167,6 +168,7 @@ pub fn modifiers_from_kb_event(event: &web_sys::KeyboardEvent) -> egui::Modifier pub fn modifiers_from_mouse_event(event: &web_sys::MouseEvent) -> egui::Modifiers { egui::Modifiers { + function: event.get_modifier_state("Fn"), alt: event.alt_key(), ctrl: event.ctrl_key(), shift: event.shift_key(), @@ -183,6 +185,7 @@ pub fn modifiers_from_mouse_event(event: &web_sys::MouseEvent) -> egui::Modifier pub fn modifiers_from_wheel_event(event: &web_sys::WheelEvent) -> egui::Modifiers { egui::Modifiers { + function: event.get_modifier_state("Fn"), alt: event.alt_key(), ctrl: event.ctrl_key(), shift: event.shift_key(), diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index a78339d01fe0..3e35d62da8b7 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -394,15 +394,27 @@ impl State { consumed: false, } } else { - self.on_keyboard_input(event); + let function = event.logical_key + == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Fn); - // When pressing the Tab key, egui focuses the first focusable element, hence Tab always consumes. - let consumed = self.egui_ctx.wants_keyboard_input() - || event.logical_key - == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab); - EventResponse { - repaint: true, - consumed, + self.egui_input.modifiers.function = function; + + if function { + EventResponse { + repaint: true, + consumed: false, + } + } else { + self.on_keyboard_input(event); + + // When pressing the Tab key, egui focuses the first focusable element, hence Tab always consumes. + let consumed = self.egui_ctx.wants_keyboard_input() + || event.logical_key + == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab); + EventResponse { + repaint: true, + consumed, + } } } } diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 3601fcae46ee..40373bbc579f 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -586,6 +586,9 @@ pub const NUM_POINTER_BUTTONS: usize = 5; #[derive(Clone, Copy, Default, Hash, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Modifiers { + /// The fn key (or the 🌐︎ Globe key on Mac). + pub function: bool, + /// Either of the alt keys are down (option ⌥ on Mac). pub alt: bool, @@ -613,6 +616,7 @@ impl std::fmt::Debug for Modifiers { } let Self { + function, alt, ctrl, shift, @@ -621,6 +625,9 @@ impl std::fmt::Debug for Modifiers { } = *self; let mut debug = f.debug_struct("Modifiers"); + if function { + debug.field("function", &true); + } if alt { debug.field("alt", &true); } @@ -642,6 +649,7 @@ impl std::fmt::Debug for Modifiers { impl Modifiers { pub const NONE: Self = Self { + function: false, alt: false, ctrl: false, shift: false, @@ -649,7 +657,16 @@ impl Modifiers { command: false, }; + pub const FN: Self = Self { + function: true, + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }; pub const ALT: Self = Self { + function: false, alt: true, ctrl: false, shift: false, @@ -657,6 +674,7 @@ impl Modifiers { command: false, }; pub const CTRL: Self = Self { + function: false, alt: false, ctrl: true, shift: false, @@ -664,6 +682,7 @@ impl Modifiers { command: false, }; pub const SHIFT: Self = Self { + function: false, alt: false, ctrl: false, shift: true, @@ -673,6 +692,7 @@ impl Modifiers { /// The Mac ⌘ Command key pub const MAC_CMD: Self = Self { + function: false, alt: false, ctrl: false, shift: false, @@ -682,6 +702,7 @@ impl Modifiers { /// On Mac: ⌘ Command key, elsewhere: Ctrl key pub const COMMAND: Self = Self { + function: false, alt: false, ctrl: false, shift: false, @@ -707,6 +728,7 @@ impl Modifiers { #[inline] pub const fn plus(self, rhs: Self) -> Self { Self { + function: self.function | rhs.function, alt: self.alt | rhs.alt, ctrl: self.ctrl | rhs.ctrl, shift: self.shift | rhs.shift, @@ -727,19 +749,19 @@ impl Modifiers { #[inline] pub fn all(&self) -> bool { - self.alt && self.ctrl && self.shift && self.command + self.function && self.alt && self.ctrl && self.shift && self.command } /// Is shift the only pressed button? #[inline] pub fn shift_only(&self) -> bool { - self.shift && !(self.alt || self.command) + self.shift && !(self.function || self.alt || self.command) } /// true if only [`Self::ctrl`] or only [`Self::mac_cmd`] is pressed. #[inline] pub fn command_only(&self) -> bool { - !self.alt && !self.shift && self.command + !self.function && !self.alt && !self.shift && self.command } /// Checks that the `ctrl/cmd` matches, and that the `shift/alt` of the argument is a subset @@ -778,6 +800,9 @@ impl Modifiers { /// assert!(!Modifiers::COMMAND.matches_logically(Modifiers::MAC_CMD)); /// ``` pub fn matches_logically(&self, pattern: Self) -> bool { + if pattern.function && !self.function { + return false; + } if pattern.alt && !self.alt { return false; } @@ -821,7 +846,10 @@ impl Modifiers { /// ``` pub fn matches_exact(&self, pattern: Self) -> bool { // alt and shift must always match the pattern: - if pattern.alt != self.alt || pattern.shift != self.shift { + if pattern.function != self.function + || pattern.alt != self.alt + || pattern.shift != self.shift + { return false; } @@ -891,6 +919,7 @@ impl Modifiers { } let Self { + function, alt, ctrl, shift, @@ -898,6 +927,12 @@ impl Modifiers { command, } = *self; + if function && query.function { + return self.contains(Self { + function: false, + ..query + }); + } if alt && query.alt { return self.contains(Self { alt: false, @@ -948,6 +983,7 @@ impl std::ops::BitOr for Modifiers { pub struct ModifierNames<'a> { pub is_short: bool, + pub function: &'a str, pub alt: &'a str, pub ctrl: &'a str, pub shift: &'a str, @@ -959,9 +995,10 @@ pub struct ModifierNames<'a> { } impl ModifierNames<'static> { - /// ⌥ ⌃ ⇧ ⌘ - NOTE: not supported by the default egui font. + /// 🌐︎ ⌥ ⌃ ⇧ ⌘ - NOTE: not supported by the default egui font. pub const SYMBOLS: Self = Self { is_short: true, + function: "🌐︎", alt: "⌥", ctrl: "⌃", shift: "⇧", @@ -970,9 +1007,10 @@ impl ModifierNames<'static> { concat: "", }; - /// Alt, Ctrl, Shift, Cmd + /// Fn, Alt, Ctrl, Shift, Cmd pub const NAMES: Self = Self { is_short: false, + function: "Fn", alt: "Alt", ctrl: "Ctrl", shift: "Shift", @@ -998,11 +1036,13 @@ impl<'a> ModifierNames<'a> { if is_mac { append_if(modifiers.ctrl, self.ctrl); append_if(modifiers.shift, self.shift); + append_if(modifiers.function, self.function); append_if(modifiers.alt, self.mac_alt); append_if(modifiers.mac_cmd || modifiers.command, self.mac_cmd); } else { append_if(modifiers.ctrl || modifiers.command, self.ctrl); append_if(modifiers.alt, self.alt); + append_if(modifiers.function, self.function); append_if(modifiers.shift, self.shift); }