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 --------- Co-authored-by: Mikayla Maki <mikayla@zed.dev> Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com> Co-authored-by: 张小白 <364772080@qq.com>
This commit is contained in:
parent
e47c48fd3b
commit
90aa99bb14
16 changed files with 146 additions and 31 deletions
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,
|
Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,
|
||||||
BackgroundExecutor, BorrowAppContext, Bounds, ClipboardItem, DrawPhase, Drawable, Element,
|
BackgroundExecutor, BorrowAppContext, Bounds, Capslock, ClipboardItem, DrawPhase, Drawable,
|
||||||
Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
|
Element, Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
|
||||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
|
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
|
||||||
Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
|
Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
|
||||||
TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
|
TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
|
||||||
|
@ -771,7 +771,18 @@ impl VisualTestContext {
|
||||||
|
|
||||||
/// Simulate a modifiers changed event
|
/// Simulate a modifiers changed event
|
||||||
pub fn simulate_modifiers_change(&mut self, modifiers: Modifiers) {
|
pub fn simulate_modifiers_change(&mut self, modifiers: Modifiers) {
|
||||||
self.simulate_event(ModifiersChangedEvent { modifiers })
|
self.simulate_event(ModifiersChangedEvent {
|
||||||
|
modifiers,
|
||||||
|
capslock: Capslock { on: false },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simulate a capslock changed event
|
||||||
|
pub fn simulate_capslock_change(&mut self, on: bool) {
|
||||||
|
self.simulate_event(ModifiersChangedEvent {
|
||||||
|
modifiers: Modifiers::none(),
|
||||||
|
capslock: Capslock { on },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simulates the user resizing the window to the new size.
|
/// Simulates the user resizing the window to the new size.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Context, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, Window, point,
|
Capslock, Context, Empty, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, Window,
|
||||||
seal::Sealed,
|
point, seal::Sealed,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
|
use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
|
||||||
|
@ -55,6 +55,8 @@ impl KeyEvent for KeyUpEvent {}
|
||||||
pub struct ModifiersChangedEvent {
|
pub struct ModifiersChangedEvent {
|
||||||
/// The new state of the modifier keys
|
/// The new state of the modifier keys
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
|
/// The new state of the capslock key
|
||||||
|
pub capslock: Capslock,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sealed for ModifiersChangedEvent {}
|
impl Sealed for ModifiersChangedEvent {}
|
||||||
|
|
|
@ -415,6 +415,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
|
||||||
fn display(&self) -> Option<Rc<dyn PlatformDisplay>>;
|
fn display(&self) -> Option<Rc<dyn PlatformDisplay>>;
|
||||||
fn mouse_position(&self) -> Point<Pixels>;
|
fn mouse_position(&self) -> Point<Pixels>;
|
||||||
fn modifiers(&self) -> Modifiers;
|
fn modifiers(&self) -> Modifiers;
|
||||||
|
fn capslock(&self) -> Capslock;
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler);
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler);
|
||||||
fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;
|
fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;
|
||||||
fn prompt(
|
fn prompt(
|
||||||
|
|
|
@ -538,3 +538,11 @@ impl Modifiers {
|
||||||
&& (other.function || !self.function)
|
&& (other.function || !self.function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The state of the capslock key at some point in time
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize, Hash, JsonSchema)]
|
||||||
|
pub struct Capslock {
|
||||||
|
/// The capslock key is on
|
||||||
|
#[serde(default)]
|
||||||
|
pub on: bool,
|
||||||
|
}
|
||||||
|
|
|
@ -873,6 +873,14 @@ impl crate::Modifiers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
|
impl crate::Capslock {
|
||||||
|
pub(super) fn from_xkb(keymap_state: &State) -> Self {
|
||||||
|
let on = keymap_state.mod_name_is_active(xkb::MOD_NAME_CAPS, xkb::STATE_MODS_EFFECTIVE);
|
||||||
|
Self { on }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -73,7 +73,7 @@ use super::{
|
||||||
|
|
||||||
use crate::platform::{PlatformWindow, blade::BladeContext};
|
use crate::platform::{PlatformWindow, blade::BladeContext};
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, CursorStyle, DOUBLE_CLICK_INTERVAL, DevicePixels, DisplayId,
|
AnyWindowHandle, Bounds, Capslock, CursorStyle, DOUBLE_CLICK_INTERVAL, DevicePixels, DisplayId,
|
||||||
FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon,
|
FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon,
|
||||||
LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
||||||
MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
|
MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
|
||||||
|
@ -217,6 +217,7 @@ pub(crate) struct WaylandClientState {
|
||||||
click: ClickState,
|
click: ClickState,
|
||||||
repeat: KeyRepeat,
|
repeat: KeyRepeat,
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
|
pub capslock: Capslock,
|
||||||
axis_source: AxisSource,
|
axis_source: AxisSource,
|
||||||
pub mouse_location: Option<Point<Pixels>>,
|
pub mouse_location: Option<Point<Pixels>>,
|
||||||
continuous_scroll_delta: Option<Point<Pixels>>,
|
continuous_scroll_delta: Option<Point<Pixels>>,
|
||||||
|
@ -595,6 +596,7 @@ impl WaylandClient {
|
||||||
function: false,
|
function: false,
|
||||||
platform: false,
|
platform: false,
|
||||||
},
|
},
|
||||||
|
capslock: Capslock { on: false },
|
||||||
scroll_event_received: false,
|
scroll_event_received: false,
|
||||||
axis_source: AxisSource::Wheel,
|
axis_source: AxisSource::Wheel,
|
||||||
mouse_location: None,
|
mouse_location: None,
|
||||||
|
@ -1251,9 +1253,12 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientStatePtr {
|
||||||
keymap_state.serialize_layout(xkbcommon::xkb::STATE_LAYOUT_EFFECTIVE);
|
keymap_state.serialize_layout(xkbcommon::xkb::STATE_LAYOUT_EFFECTIVE);
|
||||||
keymap_state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
keymap_state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||||
state.modifiers = Modifiers::from_xkb(keymap_state);
|
state.modifiers = Modifiers::from_xkb(keymap_state);
|
||||||
|
let keymap_state = state.keymap_state.as_mut().unwrap();
|
||||||
|
state.capslock = Capslock::from_xkb(keymap_state);
|
||||||
|
|
||||||
let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers: state.modifiers,
|
modifiers: state.modifiers,
|
||||||
|
capslock: state.capslock,
|
||||||
});
|
});
|
||||||
drop(state);
|
drop(state);
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,6 @@ use wayland_protocols::xdg::shell::client::xdg_surface;
|
||||||
use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};
|
use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};
|
||||||
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;
|
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;
|
||||||
|
|
||||||
use crate::platform::{
|
|
||||||
PlatformAtlas, PlatformInputHandler, PlatformWindow,
|
|
||||||
blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
|
|
||||||
linux::wayland::{display::WaylandDisplay, serial::SerialKind},
|
|
||||||
};
|
|
||||||
use crate::scene::Scene;
|
use crate::scene::Scene;
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,
|
AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,
|
||||||
|
@ -34,6 +29,14 @@ use crate::{
|
||||||
WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls, WindowDecorations,
|
WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls, WindowDecorations,
|
||||||
WindowParams, px, size,
|
WindowParams, px, size,
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
Capslock,
|
||||||
|
platform::{
|
||||||
|
PlatformAtlas, PlatformInputHandler, PlatformWindow,
|
||||||
|
blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
|
||||||
|
linux::wayland::{display::WaylandDisplay, serial::SerialKind},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct Callbacks {
|
pub(crate) struct Callbacks {
|
||||||
|
@ -861,6 +864,10 @@ impl PlatformWindow for WaylandWindow {
|
||||||
self.borrow().client.get_client().borrow().modifiers
|
self.borrow().client.get_client().borrow().modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capslock(&self) -> Capslock {
|
||||||
|
self.borrow().client.get_client().borrow().capslock
|
||||||
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||||
self.borrow_mut().input_handler = Some(input_handler);
|
self.borrow_mut().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::Capslock;
|
||||||
use core::str;
|
use core::str;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
@ -203,8 +204,11 @@ pub struct X11ClientState {
|
||||||
pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
|
pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
|
||||||
pub(crate) xim_handler: Option<XimHandler>,
|
pub(crate) xim_handler: Option<XimHandler>,
|
||||||
pub modifiers: Modifiers,
|
pub modifiers: Modifiers,
|
||||||
|
pub capslock: Capslock,
|
||||||
// TODO: Can the other updates to `modifiers` be removed so that this is unnecessary?
|
// TODO: Can the other updates to `modifiers` be removed so that this is unnecessary?
|
||||||
|
// capslock logic was done analog to modifiers
|
||||||
pub last_modifiers_changed_event: Modifiers,
|
pub last_modifiers_changed_event: Modifiers,
|
||||||
|
pub last_capslock_changed_event: Capslock,
|
||||||
|
|
||||||
pub(crate) compose_state: Option<xkbc::compose::State>,
|
pub(crate) compose_state: Option<xkbc::compose::State>,
|
||||||
pub(crate) pre_edit_text: Option<String>,
|
pub(crate) pre_edit_text: Option<String>,
|
||||||
|
@ -473,7 +477,9 @@ impl X11Client {
|
||||||
|
|
||||||
X11Client(Rc::new(RefCell::new(X11ClientState {
|
X11Client(Rc::new(RefCell::new(X11ClientState {
|
||||||
modifiers: Modifiers::default(),
|
modifiers: Modifiers::default(),
|
||||||
|
capslock: Capslock::default(),
|
||||||
last_modifiers_changed_event: Modifiers::default(),
|
last_modifiers_changed_event: Modifiers::default(),
|
||||||
|
last_capslock_changed_event: Capslock::default(),
|
||||||
event_loop: Some(event_loop),
|
event_loop: Some(event_loop),
|
||||||
loop_handle: handle,
|
loop_handle: handle,
|
||||||
common,
|
common,
|
||||||
|
@ -961,17 +967,25 @@ impl X11Client {
|
||||||
};
|
};
|
||||||
|
|
||||||
let modifiers = Modifiers::from_xkb(&state.xkb);
|
let modifiers = Modifiers::from_xkb(&state.xkb);
|
||||||
if state.last_modifiers_changed_event == modifiers {
|
let capslock = Capslock::from_xkb(&state.xkb);
|
||||||
|
if state.last_modifiers_changed_event == modifiers
|
||||||
|
&& state.last_capslock_changed_event == capslock
|
||||||
|
{
|
||||||
drop(state);
|
drop(state);
|
||||||
} else {
|
} else {
|
||||||
let focused_window_id = state.keyboard_focused_window?;
|
let focused_window_id = state.keyboard_focused_window?;
|
||||||
state.modifiers = modifiers;
|
state.modifiers = modifiers;
|
||||||
state.last_modifiers_changed_event = modifiers;
|
state.last_modifiers_changed_event = modifiers;
|
||||||
|
state.capslock = capslock;
|
||||||
|
state.last_capslock_changed_event = capslock;
|
||||||
drop(state);
|
drop(state);
|
||||||
|
|
||||||
let focused_window = self.get_window(focused_window_id)?;
|
let focused_window = self.get_window(focused_window_id)?;
|
||||||
focused_window.handle_input(PlatformInput::ModifiersChanged(
|
focused_window.handle_input(PlatformInput::ModifiersChanged(
|
||||||
ModifiersChangedEvent { modifiers },
|
ModifiersChangedEvent {
|
||||||
|
modifiers,
|
||||||
|
capslock,
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1215,6 +1215,17 @@ impl PlatformWindow for X11Window {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capslock(&self) -> crate::Capslock {
|
||||||
|
self.0
|
||||||
|
.state
|
||||||
|
.borrow()
|
||||||
|
.client
|
||||||
|
.0
|
||||||
|
.upgrade()
|
||||||
|
.map(|ref_cell| ref_cell.borrow().capslock)
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||||
self.0.state.borrow_mut().input_handler = Some(input_handler);
|
self.0.state.borrow_mut().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
Capslock, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||||
MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,
|
MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,
|
||||||
PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
||||||
platform::mac::{
|
platform::mac::{
|
||||||
|
@ -121,6 +121,11 @@ impl PlatformInput {
|
||||||
NSEventType::NSFlagsChanged => {
|
NSEventType::NSFlagsChanged => {
|
||||||
Some(Self::ModifiersChanged(ModifiersChangedEvent {
|
Some(Self::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers: read_modifiers(native_event),
|
modifiers: read_modifiers(native_event),
|
||||||
|
capslock: Capslock {
|
||||||
|
on: native_event
|
||||||
|
.modifierFlags()
|
||||||
|
.contains(NSEventModifierFlags::NSAlphaShiftKeyMask),
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
|
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{BoolExt, MacDisplay, NSRange, NSStringExt, ns_string, renderer};
|
use super::{BoolExt, MacDisplay, NSRange, NSStringExt, ns_string, renderer};
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor,
|
AnyWindowHandle, Bounds, Capslock, DisplayLink, ExternalPaths, FileDropEvent,
|
||||||
KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||||
MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay,
|
||||||
PlatformWindow, Point, PromptButton, PromptLevel, RequestFrameOptions, ScaledPixels, Size,
|
PlatformInput, PlatformWindow, Point, PromptButton, PromptLevel, RequestFrameOptions,
|
||||||
Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControlArea,
|
ScaledPixels, Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds,
|
||||||
WindowKind, WindowParams, platform::PlatformInputHandler, point, px, size,
|
WindowControlArea, WindowKind, WindowParams, platform::PlatformInputHandler, point, px, size,
|
||||||
};
|
};
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
|
@ -890,6 +890,16 @@ impl PlatformWindow for MacWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capslock(&self) -> Capslock {
|
||||||
|
unsafe {
|
||||||
|
let modifiers: NSEventModifierFlags = msg_send![class!(NSEvent), modifierFlags];
|
||||||
|
|
||||||
|
Capslock {
|
||||||
|
on: modifiers.contains(NSEventModifierFlags::NSAlphaShiftKeyMask),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||||
self.0.as_ref().lock().input_handler = Some(input_handler);
|
self.0.as_ref().lock().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
@ -1556,13 +1566,17 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
lock.synthetic_drag_counter += 1;
|
lock.synthetic_drag_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformInput::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||||
|
modifiers,
|
||||||
|
capslock,
|
||||||
|
}) => {
|
||||||
// Only raise modifiers changed event when they have actually changed
|
// Only raise modifiers changed event when they have actually changed
|
||||||
if let Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
if let Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers: prev_modifiers,
|
modifiers: prev_modifiers,
|
||||||
|
capslock: prev_capslock,
|
||||||
})) = &lock.previous_modifiers_changed_event
|
})) = &lock.previous_modifiers_changed_event
|
||||||
{
|
{
|
||||||
if prev_modifiers == modifiers {
|
if prev_modifiers == modifiers && prev_capslock == capslock {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,10 @@ impl PlatformWindow for TestWindow {
|
||||||
crate::Modifiers::default()
|
crate::Modifiers::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capslock(&self) -> crate::Capslock {
|
||||||
|
crate::Capslock::default()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||||
self.0.lock().input_handler = Some(input_handler);
|
self.0.lock().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1227,6 +1227,7 @@ where
|
||||||
{
|
{
|
||||||
let virtual_key = VIRTUAL_KEY(wparam.loword());
|
let virtual_key = VIRTUAL_KEY(wparam.loword());
|
||||||
let mut modifiers = current_modifiers();
|
let mut modifiers = current_modifiers();
|
||||||
|
let capslock = current_capslock();
|
||||||
|
|
||||||
match virtual_key {
|
match virtual_key {
|
||||||
VK_SHIFT | VK_CONTROL | VK_MENU | VK_LWIN | VK_RWIN => {
|
VK_SHIFT | VK_CONTROL | VK_MENU | VK_LWIN | VK_RWIN => {
|
||||||
|
@ -1239,6 +1240,7 @@ where
|
||||||
state.last_reported_modifiers = Some(modifiers);
|
state.last_reported_modifiers = Some(modifiers);
|
||||||
Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers,
|
modifiers,
|
||||||
|
capslock,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
vkey => {
|
vkey => {
|
||||||
|
@ -1371,6 +1373,12 @@ pub(crate) fn current_modifiers() -> Modifiers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn current_capslock() -> Capslock {
|
||||||
|
let on = unsafe { GetKeyState(VK_CAPITAL.0 as i32) & 1 } > 0;
|
||||||
|
Capslock { on: on }
|
||||||
|
}
|
||||||
|
|
||||||
fn get_client_area_insets(
|
fn get_client_area_insets(
|
||||||
handle: HWND,
|
handle: HWND,
|
||||||
is_maximized: bool,
|
is_maximized: bool,
|
||||||
|
|
|
@ -559,6 +559,10 @@ impl PlatformWindow for WindowsWindow {
|
||||||
current_modifiers()
|
current_modifiers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn capslock(&self) -> Capslock {
|
||||||
|
current_capslock()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||||
self.0.state.borrow_mut().input_handler = Some(input_handler);
|
self.0.state.borrow_mut().input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
use crate::Inspector;
|
use crate::Inspector;
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,
|
Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,
|
||||||
AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,
|
AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Capslock,
|
||||||
Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,
|
Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener,
|
||||||
DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,
|
DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter,
|
||||||
Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,
|
FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero,
|
||||||
KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,
|
KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId,
|
||||||
ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,
|
LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent,
|
||||||
Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,
|
MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||||
PlatformWindow, Point, PolychromeSprite, PromptButton, PromptLevel, Quad, Render,
|
PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptButton, PromptLevel, Quad,
|
||||||
RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,
|
Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,
|
||||||
SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size,
|
SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size,
|
||||||
StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle,
|
StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle,
|
||||||
TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, WindowAppearance,
|
TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, WindowAppearance,
|
||||||
|
@ -796,6 +796,7 @@ pub struct Window {
|
||||||
mouse_position: Point<Pixels>,
|
mouse_position: Point<Pixels>,
|
||||||
mouse_hit_test: HitTest,
|
mouse_hit_test: HitTest,
|
||||||
modifiers: Modifiers,
|
modifiers: Modifiers,
|
||||||
|
capslock: Capslock,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
|
pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
|
||||||
appearance: WindowAppearance,
|
appearance: WindowAppearance,
|
||||||
|
@ -907,6 +908,7 @@ impl Window {
|
||||||
let sprite_atlas = platform_window.sprite_atlas();
|
let sprite_atlas = platform_window.sprite_atlas();
|
||||||
let mouse_position = platform_window.mouse_position();
|
let mouse_position = platform_window.mouse_position();
|
||||||
let modifiers = platform_window.modifiers();
|
let modifiers = platform_window.modifiers();
|
||||||
|
let capslock = platform_window.capslock();
|
||||||
let content_size = platform_window.content_size();
|
let content_size = platform_window.content_size();
|
||||||
let scale_factor = platform_window.scale_factor();
|
let scale_factor = platform_window.scale_factor();
|
||||||
let appearance = platform_window.appearance();
|
let appearance = platform_window.appearance();
|
||||||
|
@ -1015,6 +1017,7 @@ impl Window {
|
||||||
.update(&mut cx, |_, window, cx| {
|
.update(&mut cx, |_, window, cx| {
|
||||||
window.active.set(active);
|
window.active.set(active);
|
||||||
window.modifiers = window.platform_window.modifiers();
|
window.modifiers = window.platform_window.modifiers();
|
||||||
|
window.capslock = window.platform_window.capslock();
|
||||||
window
|
window
|
||||||
.activation_observers
|
.activation_observers
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -1100,6 +1103,7 @@ impl Window {
|
||||||
mouse_position,
|
mouse_position,
|
||||||
mouse_hit_test: HitTest::default(),
|
mouse_hit_test: HitTest::default(),
|
||||||
modifiers,
|
modifiers,
|
||||||
|
capslock,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
bounds_observers: SubscriberSet::new(),
|
bounds_observers: SubscriberSet::new(),
|
||||||
appearance,
|
appearance,
|
||||||
|
@ -1728,6 +1732,11 @@ impl Window {
|
||||||
self.modifiers
|
self.modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current state of the keyboard's capslock
|
||||||
|
pub fn capslock(&self) -> Capslock {
|
||||||
|
self.capslock
|
||||||
|
}
|
||||||
|
|
||||||
fn complete_frame(&self) {
|
fn complete_frame(&self) {
|
||||||
self.platform_window.completed_frame();
|
self.platform_window.completed_frame();
|
||||||
}
|
}
|
||||||
|
@ -3352,6 +3361,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
PlatformInput::ModifiersChanged(modifiers_changed) => {
|
PlatformInput::ModifiersChanged(modifiers_changed) => {
|
||||||
self.modifiers = modifiers_changed.modifiers;
|
self.modifiers = modifiers_changed.modifiers;
|
||||||
|
self.capslock = modifiers_changed.capslock;
|
||||||
PlatformInput::ModifiersChanged(modifiers_changed)
|
PlatformInput::ModifiersChanged(modifiers_changed)
|
||||||
}
|
}
|
||||||
PlatformInput::ScrollWheel(scroll_wheel) => {
|
PlatformInput::ScrollWheel(scroll_wheel) => {
|
||||||
|
|
|
@ -289,6 +289,9 @@ impl Render for SshPrompt {
|
||||||
.child(MarkdownElement::new(prompt.0.clone(), markdown_style))
|
.child(MarkdownElement::new(prompt.0.clone(), markdown_style))
|
||||||
.child(self.editor.clone()),
|
.child(self.editor.clone()),
|
||||||
)
|
)
|
||||||
|
.when(window.capslock().on, |el| {
|
||||||
|
el.child(Label::new("⚠️ ⇪ is on"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue