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:
co-authored by
Mikayla Maki
Mikayla Maki
张小白
parent
e47c48fd3b
commit
90aa99bb14
@@ -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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -73,7 +73,7 @@ use super::{
|
||||
|
||||
use crate::platform::{PlatformWindow, blade::BladeContext};
|
||||
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,
|
||||
LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
||||
MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
|
||||
@@ -217,6 +217,7 @@ pub(crate) struct WaylandClientState {
|
||||
click: ClickState,
|
||||
repeat: KeyRepeat,
|
||||
pub modifiers: Modifiers,
|
||||
pub capslock: Capslock,
|
||||
axis_source: AxisSource,
|
||||
pub mouse_location: Option<Point<Pixels>>,
|
||||
continuous_scroll_delta: Option<Point<Pixels>>,
|
||||
@@ -595,6 +596,7 @@ impl WaylandClient {
|
||||
function: false,
|
||||
platform: false,
|
||||
},
|
||||
capslock: Capslock { on: false },
|
||||
scroll_event_received: false,
|
||||
axis_source: AxisSource::Wheel,
|
||||
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.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
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 {
|
||||
modifiers: state.modifiers,
|
||||
capslock: state.capslock,
|
||||
});
|
||||
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_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::{
|
||||
AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,
|
||||
@@ -34,6 +29,14 @@ use crate::{
|
||||
WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls, WindowDecorations,
|
||||
WindowParams, px, size,
|
||||
};
|
||||
use crate::{
|
||||
Capslock,
|
||||
platform::{
|
||||
PlatformAtlas, PlatformInputHandler, PlatformWindow,
|
||||
blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
|
||||
linux::wayland::{display::WaylandDisplay, serial::SerialKind},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Callbacks {
|
||||
@@ -861,6 +864,10 @@ impl PlatformWindow for WaylandWindow {
|
||||
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) {
|
||||
self.borrow_mut().input_handler = Some(input_handler);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::Capslock;
|
||||
use core::str;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@@ -203,8 +204,11 @@ pub struct X11ClientState {
|
||||
pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
|
||||
pub(crate) xim_handler: Option<XimHandler>,
|
||||
pub modifiers: Modifiers,
|
||||
pub capslock: Capslock,
|
||||
// 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_capslock_changed_event: Capslock,
|
||||
|
||||
pub(crate) compose_state: Option<xkbc::compose::State>,
|
||||
pub(crate) pre_edit_text: Option<String>,
|
||||
@@ -473,7 +477,9 @@ impl X11Client {
|
||||
|
||||
X11Client(Rc::new(RefCell::new(X11ClientState {
|
||||
modifiers: Modifiers::default(),
|
||||
capslock: Capslock::default(),
|
||||
last_modifiers_changed_event: Modifiers::default(),
|
||||
last_capslock_changed_event: Capslock::default(),
|
||||
event_loop: Some(event_loop),
|
||||
loop_handle: handle,
|
||||
common,
|
||||
@@ -961,17 +967,25 @@ impl X11Client {
|
||||
};
|
||||
|
||||
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);
|
||||
} else {
|
||||
let focused_window_id = state.keyboard_focused_window?;
|
||||
state.modifiers = modifiers;
|
||||
state.last_modifiers_changed_event = modifiers;
|
||||
state.capslock = capslock;
|
||||
state.last_capslock_changed_event = capslock;
|
||||
drop(state);
|
||||
|
||||
let focused_window = self.get_window(focused_window_id)?;
|
||||
focused_window.handle_input(PlatformInput::ModifiersChanged(
|
||||
ModifiersChangedEvent { modifiers },
|
||||
ModifiersChangedEvent {
|
||||
modifiers,
|
||||
capslock,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1215,6 +1215,17 @@ impl PlatformWindow for X11Window {
|
||||
.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) {
|
||||
self.0.state.borrow_mut().input_handler = Some(input_handler);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user