History

Add Caps Lock support (#30470)

Closes #21700 Release Notes: - Added caps lock support and show a warning if the user is entering an SSH password with Caps Lock enabled ---------

Maxim Zaks committed 1 year ago

Commit 90aa99b1 parent e47c48f16 files · +146 −31Browse files

Unified · Split

16 files
  1. crates/gpui/src/app/test_context.rs +14 −3
  2. crates/gpui/src/interactive.rs +4 −2
  3. crates/gpui/src/platform.rs +1 −0
  4. crates/gpui/src/platform/keystroke.rs +8 −0
  5. crates/gpui/src/platform/linux/platform.rs +8 −0
  6. crates/gpui/src/platform/linux/wayland/client.rs +6 −1
  7. crates/gpui/src/platform/linux/wayland/window.rs +12 −5
  8. crates/gpui/src/platform/linux/x11/client.rs +16 −2
  9. crates/gpui/src/platform/linux/x11/window.rs +11 −0
  10. crates/gpui/src/platform/mac/events.rs +6 −1
  11. crates/gpui/src/platform/mac/window.rs +22 −8
  12. crates/gpui/src/platform/test/window.rs +4 −0
  13. crates/gpui/src/platform/windows/events.rs +8 −0
  14. crates/gpui/src/platform/windows/window.rs +4 −0
  15. crates/gpui/src/window.rs +19 −9
  16. crates/recent_projects/src/ssh_connections.rs +3 −0
crates/gpui/src/app/test_context.rs+14−3
@@ -1,7 +1,7 @@
1use crate::{1use crate::{
2 Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,2 Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,
3 BackgroundExecutor, BorrowAppContext, Bounds, ClipboardItem, DrawPhase, Drawable, Element,3 BackgroundExecutor, BorrowAppContext, Bounds, Capslock, ClipboardItem, DrawPhase, Drawable,
4 Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,4 Element, Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
5 ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,5 ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
6 Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,6 Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
7 TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,7 TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
@@ -771,7 +771,18 @@ impl VisualTestContext { · 763 unmodified lines
771 771
772 /// Simulate a modifiers changed event772 /// Simulate a modifiers changed event
773 pub fn simulate_modifiers_change(&mut self, modifiers: Modifiers) {773 pub fn simulate_modifiers_change(&mut self, modifiers: Modifiers) {
774 self.simulate_event(ModifiersChangedEvent { modifiers })774 self.simulate_event(ModifiersChangedEvent {
775 modifiers,
776 capslock: Capslock { on: false },
777 })
778 }
779
780 /// Simulate a capslock changed event
781 pub fn simulate_capslock_change(&mut self, on: bool) {
782 self.simulate_event(ModifiersChangedEvent {
783 modifiers: Modifiers::none(),
784 capslock: Capslock { on },
785 })
775 }786 }
776 787
777 /// Simulates the user resizing the window to the new size.788 /// Simulates the user resizing the window to the new size.
crates/gpui/src/interactive.rs+4−2
@@ -1,6 +1,6 @@
1use crate::{1use crate::{
2 Context, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, Window, point,2 Capslock, Context, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, Window,
3 seal::Sealed,3 point, seal::Sealed,
4};4};
5use smallvec::SmallVec;5use smallvec::SmallVec;
6use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};6use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
@@ -55,6 +55,8 @@ impl KeyEvent for KeyUpEvent {} · 48 unmodified lines
55pub struct ModifiersChangedEvent {55pub struct ModifiersChangedEvent {
56 /// The new state of the modifier keys56 /// The new state of the modifier keys
57 pub modifiers: Modifiers,57 pub modifiers: Modifiers,
58 /// The new state of the capslock key
59 pub capslock: Capslock,
58}60}
59 61
60impl Sealed for ModifiersChangedEvent {}62impl Sealed for ModifiersChangedEvent {}
crates/gpui/src/platform.rs+1−0
@@ -415,6 +415,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { · 414 unmodified lines
415 fn display(&self) -> Option<Rc<dyn PlatformDisplay>>;415 fn display(&self) -> Option<Rc<dyn PlatformDisplay>>;
416 fn mouse_position(&self) -> Point<Pixels>;416 fn mouse_position(&self) -> Point<Pixels>;
417 fn modifiers(&self) -> Modifiers;417 fn modifiers(&self) -> Modifiers;
418 fn capslock(&self) -> Capslock;
418 fn set_input_handler(&mut self, input_handler: PlatformInputHandler);419 fn set_input_handler(&mut self, input_handler: PlatformInputHandler);
419 fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;420 fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;
420 fn prompt(421 fn prompt(
crates/gpui/src/platform/keystroke.rs+8−0
@@ -538,3 +538,11 @@ impl Modifiers { · 537 unmodified lines
538 && (other.function || !self.function)538 && (other.function || !self.function)
539 }539 }
540}540}
541
542/// The state of the capslock key at some point in time
543#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize, Hash, JsonSchema)]
544pub struct Capslock {
545 /// The capslock key is on
546 #[serde(default)]
547 pub on: bool,
548}
crates/gpui/src/platform/linux/platform.rs+8−0
@@ -873,6 +873,14 @@ impl crate::Modifiers { · 872 unmodified lines
873 }873 }
874}874}
875 875
876#[cfg(any(feature = "wayland", feature = "x11"))]
877impl crate::Capslock {
878 pub(super) fn from_xkb(keymap_state: &State) -> Self {
879 let on = keymap_state.mod_name_is_active(xkb::MOD_NAME_CAPS, xkb::STATE_MODS_EFFECTIVE);
880 Self { on }
881 }
882}
883
876#[cfg(test)]884#[cfg(test)]
877mod tests {885mod tests {
878 use super::*;886 use super::*;
crates/gpui/src/platform/linux/wayland/client.rs+6−1
@@ -73,7 +73,7 @@ use super::{ · 72 unmodified lines
73 73
74use crate::platform::{PlatformWindow, blade::BladeContext};74use crate::platform::{PlatformWindow, blade::BladeContext};
75use crate::{75use crate::{
76 AnyWindowHandle, Bounds, CursorStyle, DOUBLE_CLICK_INTERVAL, DevicePixels, DisplayId,76 AnyWindowHandle, Bounds, Capslock, CursorStyle, DOUBLE_CLICK_INTERVAL, DevicePixels, DisplayId,
77 FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon,77 FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon,
78 LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,78 LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
79 MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,79 MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
@@ -217,6 +217,7 @@ pub(crate) struct WaylandClientState { · 137 unmodified lines
217 click: ClickState,217 click: ClickState,
218 repeat: KeyRepeat,218 repeat: KeyRepeat,
219 pub modifiers: Modifiers,219 pub modifiers: Modifiers,
220 pub capslock: Capslock,
220 axis_source: AxisSource,221 axis_source: AxisSource,
221 pub mouse_location: Option<Point<Pixels>>,222 pub mouse_location: Option<Point<Pixels>>,
222 continuous_scroll_delta: Option<Point<Pixels>>,223 continuous_scroll_delta: Option<Point<Pixels>>,
@@ -595,6 +596,7 @@ impl WaylandClient { · 372 unmodified lines
595 function: false,596 function: false,
596 platform: false,597 platform: false,
597 },598 },
599 capslock: Capslock { on: false },
598 scroll_event_received: false,600 scroll_event_received: false,
599 axis_source: AxisSource::Wheel,601 axis_source: AxisSource::Wheel,
600 mouse_location: None,602 mouse_location: None,
@@ -1251,9 +1253,12 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientStatePtr { · 650 unmodified lines
1251 keymap_state.serialize_layout(xkbcommon::xkb::STATE_LAYOUT_EFFECTIVE);1253 keymap_state.serialize_layout(xkbcommon::xkb::STATE_LAYOUT_EFFECTIVE);
1252 keymap_state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);1254 keymap_state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
1253 state.modifiers = Modifiers::from_xkb(keymap_state);1255 state.modifiers = Modifiers::from_xkb(keymap_state);
1256 let keymap_state = state.keymap_state.as_mut().unwrap();
1257 state.capslock = Capslock::from_xkb(keymap_state);
1254 1258
1255 let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent {1259 let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent {
1256 modifiers: state.modifiers,1260 modifiers: state.modifiers,
1261 capslock: state.capslock,
1257 });1262 });
1258 drop(state);1263 drop(state);
1259 1264
crates/gpui/src/platform/linux/wayland/window.rs+12−5
@@ -21,11 +21,6 @@ use wayland_protocols::xdg::shell::client::xdg_surface; · 20 unmodified lines
21use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};21use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};
22use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;22use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;
23 23
24use crate::platform::{
25 PlatformAtlas, PlatformInputHandler, PlatformWindow,
26 blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
27 linux::wayland::{display::WaylandDisplay, serial::SerialKind},
28};
29use crate::scene::Scene;24use crate::scene::Scene;
30use crate::{25use crate::{
31 AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,26 AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,
@@ -34,6 +29,14 @@ use crate::{ · 2 unmodified lines
34 WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls, WindowDecorations,29 WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls, WindowDecorations,
35 WindowParams, px, size,30 WindowParams, px, size,
36};31};
32use crate::{
33 Capslock,
34 platform::{
35 PlatformAtlas, PlatformInputHandler, PlatformWindow,
36 blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
37 linux::wayland::{display::WaylandDisplay, serial::SerialKind},
38 },
39};
37 40
38#[derive(Default)]41#[derive(Default)]
39pub(crate) struct Callbacks {42pub(crate) struct Callbacks {
@@ -861,6 +864,10 @@ impl PlatformWindow for WaylandWindow { · 821 unmodified lines
861 self.borrow().client.get_client().borrow().modifiers864 self.borrow().client.get_client().borrow().modifiers
862 }865 }
863 866
867 fn capslock(&self) -> Capslock {
868 self.borrow().client.get_client().borrow().capslock
869 }
870
864 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {871 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
865 self.borrow_mut().input_handler = Some(input_handler);872 self.borrow_mut().input_handler = Some(input_handler);
866 }873 }
crates/gpui/src/platform/linux/x11/client.rs+16−2
@@ -1,3 +1,4 @@
1use crate::Capslock;
1use core::str;2use core::str;
2use std::{3use std::{
3 cell::RefCell,4 cell::RefCell,
@@ -203,8 +204,11 @@ pub struct X11ClientState { · 199 unmodified lines
203 pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,204 pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
204 pub(crate) xim_handler: Option<XimHandler>,205 pub(crate) xim_handler: Option<XimHandler>,
205 pub modifiers: Modifiers,206 pub modifiers: Modifiers,
207 pub capslock: Capslock,
206 // TODO: Can the other updates to `modifiers` be removed so that this is unnecessary?208 // TODO: Can the other updates to `modifiers` be removed so that this is unnecessary?
209 // capslock logic was done analog to modifiers
207 pub last_modifiers_changed_event: Modifiers,210 pub last_modifiers_changed_event: Modifiers,
211 pub last_capslock_changed_event: Capslock,
208 212
209 pub(crate) compose_state: Option<xkbc::compose::State>,213 pub(crate) compose_state: Option<xkbc::compose::State>,
210 pub(crate) pre_edit_text: Option<String>,214 pub(crate) pre_edit_text: Option<String>,
@@ -473,7 +477,9 @@ impl X11Client { · 262 unmodified lines
473 477
474 X11Client(Rc::new(RefCell::new(X11ClientState {478 X11Client(Rc::new(RefCell::new(X11ClientState {
475 modifiers: Modifiers::default(),479 modifiers: Modifiers::default(),
480 capslock: Capslock::default(),
476 last_modifiers_changed_event: Modifiers::default(),481 last_modifiers_changed_event: Modifiers::default(),
482 last_capslock_changed_event: Capslock::default(),
477 event_loop: Some(event_loop),483 event_loop: Some(event_loop),
478 loop_handle: handle,484 loop_handle: handle,
479 common,485 common,
@@ -961,17 +967,25 @@ impl X11Client { · 481 unmodified lines
961 };967 };
962 968
963 let modifiers = Modifiers::from_xkb(&state.xkb);969 let modifiers = Modifiers::from_xkb(&state.xkb);
964 if state.last_modifiers_changed_event == modifiers {970 let capslock = Capslock::from_xkb(&state.xkb);
971 if state.last_modifiers_changed_event == modifiers
972 && state.last_capslock_changed_event == capslock
973 {
965 drop(state);974 drop(state);
966 } else {975 } else {
967 let focused_window_id = state.keyboard_focused_window?;976 let focused_window_id = state.keyboard_focused_window?;
968 state.modifiers = modifiers;977 state.modifiers = modifiers;
969 state.last_modifiers_changed_event = modifiers;978 state.last_modifiers_changed_event = modifiers;
979 state.capslock = capslock;
980 state.last_capslock_changed_event = capslock;
970 drop(state);981 drop(state);
971 982
972 let focused_window = self.get_window(focused_window_id)?;983 let focused_window = self.get_window(focused_window_id)?;
973 focused_window.handle_input(PlatformInput::ModifiersChanged(984 focused_window.handle_input(PlatformInput::ModifiersChanged(
974 ModifiersChangedEvent { modifiers },985 ModifiersChangedEvent {
986 modifiers,
987 capslock,
988 },
975 ));989 ));
976 }990 }
977 991
crates/gpui/src/platform/linux/x11/window.rs+11−0
@@ -1215,6 +1215,17 @@ impl PlatformWindow for X11Window { · 1214 unmodified lines
1215 .unwrap_or_default()1215 .unwrap_or_default()
1216 }1216 }
1217 1217
1218 fn capslock(&self) -> crate::Capslock {
1219 self.0
1220 .state
1221 .borrow()
1222 .client
1223 .0
1224 .upgrade()
1225 .map(|ref_cell| ref_cell.borrow().capslock)
1226 .unwrap_or_default()
1227 }
1228
1218 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {1229 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
1219 self.0.state.borrow_mut().input_handler = Some(input_handler);1230 self.0.state.borrow_mut().input_handler = Some(input_handler);
1220 }1231 }
crates/gpui/src/platform/mac/events.rs+6−1
@@ -1,5 +1,5 @@
1use crate::{1use crate::{
2 KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,2 Capslock, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
3 MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,3 MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,
4 PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,4 PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
5 platform::mac::{5 platform::mac::{
@@ -121,6 +121,11 @@ impl PlatformInput { · 115 unmodified lines
121 NSEventType::NSFlagsChanged => {121 NSEventType::NSFlagsChanged => {
122 Some(Self::ModifiersChanged(ModifiersChangedEvent {122 Some(Self::ModifiersChanged(ModifiersChangedEvent {
123 modifiers: read_modifiers(native_event),123 modifiers: read_modifiers(native_event),
124 capslock: Capslock {
125 on: native_event
126 .modifierFlags()
127 .contains(NSEventModifierFlags::NSAlphaShiftKeyMask),
128 },
124 }))129 }))
125 }130 }
126 NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {131 NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
crates/gpui/src/platform/mac/window.rs+22−8
@@ -1,11 +1,11 @@
1use super::{BoolExt, MacDisplay, NSRange, NSStringExt, ns_string, renderer};1use super::{BoolExt, MacDisplay, NSRange, NSStringExt, ns_string, renderer};
2use crate::{2use crate::{
3 AnyWindowHandle, Bounds, DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor,3 AnyWindowHandle, Bounds, Capslock, DisplayLink, ExternalPaths, FileDropEvent,
4 KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,4 ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
5 MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,5 MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay,
6 PlatformWindow, Point, PromptButton, PromptLevel, RequestFrameOptions, ScaledPixels, Size,6 PlatformInput, PlatformWindow, Point, PromptButton, PromptLevel, RequestFrameOptions,
7 Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControlArea,7 ScaledPixels, Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds,
8 WindowKind, WindowParams, platform::PlatformInputHandler, point, px, size,8 WindowControlArea, WindowKind, WindowParams, platform::PlatformInputHandler, point, px, size,
9};9};
10use block::ConcreteBlock;10use block::ConcreteBlock;
11use cocoa::{11use cocoa::{
@@ -890,6 +890,16 @@ impl PlatformWindow for MacWindow { · 878 unmodified lines
890 }890 }
891 }891 }
892 892
893 fn capslock(&self) -> Capslock {
894 unsafe {
895 let modifiers: NSEventModifierFlags = msg_send![class!(NSEvent), modifierFlags];
896
897 Capslock {
898 on: modifiers.contains(NSEventModifierFlags::NSAlphaShiftKeyMask),
899 }
900 }
901 }
902
893 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {903 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
894 self.0.as_ref().lock().input_handler = Some(input_handler);904 self.0.as_ref().lock().input_handler = Some(input_handler);
895 }905 }
@@ -1556,13 +1566,17 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) { · 660 unmodified lines
1556 lock.synthetic_drag_counter += 1;1566 lock.synthetic_drag_counter += 1;
1557 }1567 }
1558 1568
1559 PlatformInput::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {1569 PlatformInput::ModifiersChanged(ModifiersChangedEvent {
1570 modifiers,
1571 capslock,
1572 }) => {
1560 // Only raise modifiers changed event when they have actually changed1573 // Only raise modifiers changed event when they have actually changed
1561 if let Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {1574 if let Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
1562 modifiers: prev_modifiers,1575 modifiers: prev_modifiers,
1576 capslock: prev_capslock,
1563 })) = &lock.previous_modifiers_changed_event1577 })) = &lock.previous_modifiers_changed_event
1564 {1578 {
1565 if prev_modifiers == modifiers {1579 if prev_modifiers == modifiers && prev_capslock == capslock {
1566 return;1580 return;
1567 }1581 }
1568 }1582 }
crates/gpui/src/platform/test/window.rs+4−0
@@ -153,6 +153,10 @@ impl PlatformWindow for TestWindow { · 152 unmodified lines
153 crate::Modifiers::default()153 crate::Modifiers::default()
154 }154 }
155 155
156 fn capslock(&self) -> crate::Capslock {
157 crate::Capslock::default()
158 }
159
156 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {160 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
157 self.0.lock().input_handler = Some(input_handler);161 self.0.lock().input_handler = Some(input_handler);
158 }162 }
crates/gpui/src/platform/windows/events.rs+8−0
@@ -1227,6 +1227,7 @@ where · 1226 unmodified lines
1227{1227{
1228 let virtual_key = VIRTUAL_KEY(wparam.loword());1228 let virtual_key = VIRTUAL_KEY(wparam.loword());
1229 let mut modifiers = current_modifiers();1229 let mut modifiers = current_modifiers();
1230 let capslock = current_capslock();
1230 1231
1231 match virtual_key {1232 match virtual_key {
1232 VK_SHIFT | VK_CONTROL | VK_MENU | VK_LWIN | VK_RWIN => {1233 VK_SHIFT | VK_CONTROL | VK_MENU | VK_LWIN | VK_RWIN => {
@@ -1239,6 +1240,7 @@ where · 6 unmodified lines
1239 state.last_reported_modifiers = Some(modifiers);1240 state.last_reported_modifiers = Some(modifiers);
1240 Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {1241 Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
1241 modifiers,1242 modifiers,
1243 capslock,
1242 }))1244 }))
1243 }1245 }
1244 vkey => {1246 vkey => {
@@ -1371,6 +1373,12 @@ pub(crate) fn current_modifiers() -> Modifiers { · 126 unmodified lines
1371 }1373 }
1372}1374}
1373 1375
1376#[inline]
1377pub(crate) fn current_capslock() -> Capslock {
1378 let on = unsafe { GetKeyState(VK_CAPITAL.0 as i32) & 1 } > 0;
1379 Capslock { on: on }
1380}
1381
1374fn get_client_area_insets(1382fn get_client_area_insets(
1375 handle: HWND,1383 handle: HWND,
1376 is_maximized: bool,1384 is_maximized: bool,
crates/gpui/src/platform/windows/window.rs+4−0
@@ -559,6 +559,10 @@ impl PlatformWindow for WindowsWindow { · 558 unmodified lines
559 current_modifiers()559 current_modifiers()
560 }560 }
561 561
562 fn capslock(&self) -> Capslock {
563 current_capslock()
564 }
565
562 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {566 fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
563 self.0.state.borrow_mut().input_handler = Some(input_handler);567 self.0.state.borrow_mut().input_handler = Some(input_handler);
564 }568 }
crates/gpui/src/window.rs+19−9
@@ -2,15 +2,15 @@ · 1 unmodified line
2use crate::Inspector;2use crate::Inspector;
3use crate::{3use crate::{
4 Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,4 Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,
5 AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,5 AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Capslock,
6 Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,6 Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener,
7 DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,7 DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter,
8 Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,8 FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero,
9 KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,9 KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId,
10 ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,10 LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent,
11 Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,11 MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
12 PlatformWindow, Point, PolychromeSprite, PromptButton, PromptLevel, Quad, Render,12 PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptButton, PromptLevel, Quad,
13 RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,13 Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,
14 SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size,14 SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size,
15 StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle,15 StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle,
16 TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, WindowAppearance,16 TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, WindowAppearance,
@@ -796,6 +796,7 @@ pub struct Window { · 779 unmodified lines
796 mouse_position: Point<Pixels>,796 mouse_position: Point<Pixels>,
797 mouse_hit_test: HitTest,797 mouse_hit_test: HitTest,
798 modifiers: Modifiers,798 modifiers: Modifiers,
799 capslock: Capslock,
799 scale_factor: f32,800 scale_factor: f32,
800 pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,801 pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
801 appearance: WindowAppearance,802 appearance: WindowAppearance,
@@ -907,6 +908,7 @@ impl Window { · 105 unmodified lines
907 let sprite_atlas = platform_window.sprite_atlas();908 let sprite_atlas = platform_window.sprite_atlas();
908 let mouse_position = platform_window.mouse_position();909 let mouse_position = platform_window.mouse_position();
909 let modifiers = platform_window.modifiers();910 let modifiers = platform_window.modifiers();
911 let capslock = platform_window.capslock();
910 let content_size = platform_window.content_size();912 let content_size = platform_window.content_size();
911 let scale_factor = platform_window.scale_factor();913 let scale_factor = platform_window.scale_factor();
912 let appearance = platform_window.appearance();914 let appearance = platform_window.appearance();
@@ -1015,6 +1017,7 @@ impl Window { · 102 unmodified lines
1015 .update(&mut cx, |_, window, cx| {1017 .update(&mut cx, |_, window, cx| {
1016 window.active.set(active);1018 window.active.set(active);
1017 window.modifiers = window.platform_window.modifiers();1019 window.modifiers = window.platform_window.modifiers();
1020 window.capslock = window.platform_window.capslock();
1018 window1021 window
1019 .activation_observers1022 .activation_observers
1020 .clone()1023 .clone()
@@ -1100,6 +1103,7 @@ impl Window { · 79 unmodified lines
1100 mouse_position,1103 mouse_position,
1101 mouse_hit_test: HitTest::default(),1104 mouse_hit_test: HitTest::default(),
1102 modifiers,1105 modifiers,
1106 capslock,
1103 scale_factor,1107 scale_factor,
1104 bounds_observers: SubscriberSet::new(),1108 bounds_observers: SubscriberSet::new(),
1105 appearance,1109 appearance,
@@ -1728,6 +1732,11 @@ impl Window { · 622 unmodified lines
1728 self.modifiers1732 self.modifiers
1729 }1733 }
1730 1734
1735 /// The current state of the keyboard's capslock
1736 pub fn capslock(&self) -> Capslock {
1737 self.capslock
1738 }
1739
1731 fn complete_frame(&self) {1740 fn complete_frame(&self) {
1732 self.platform_window.completed_frame();1741 self.platform_window.completed_frame();
1733 }1742 }
@@ -3352,6 +3361,7 @@ impl Window { · 1618 unmodified lines
3352 }3361 }
3353 PlatformInput::ModifiersChanged(modifiers_changed) => {3362 PlatformInput::ModifiersChanged(modifiers_changed) => {
3354 self.modifiers = modifiers_changed.modifiers;3363 self.modifiers = modifiers_changed.modifiers;
3364 self.capslock = modifiers_changed.capslock;
3355 PlatformInput::ModifiersChanged(modifiers_changed)3365 PlatformInput::ModifiersChanged(modifiers_changed)
3356 }3366 }
3357 PlatformInput::ScrollWheel(scroll_wheel) => {3367 PlatformInput::ScrollWheel(scroll_wheel) => {
crates/recent_projects/src/ssh_connections.rs+3−0
@@ -289,6 +289,9 @@ impl Render for SshPrompt { · 288 unmodified lines
289 .child(MarkdownElement::new(prompt.0.clone(), markdown_style))289 .child(MarkdownElement::new(prompt.0.clone(), markdown_style))
290 .child(self.editor.clone()),290 .child(self.editor.clone()),
291 )291 )
292 .when(window.capslock().on, |el| {
293 el.child(Label::new("⚠️ ⇪ is on"))
294 })
292 })295 })
293 }296 }
294}297}