Fix assorted linux issues (#10061)
- Fix a bug where modifiers would be dispatched before they changed - Add a secondary modifier - Improve keybindings Release Notes: - N/A
This commit is contained in:
parent
e0cd96db7b
commit
1da2441e7b
20 changed files with 220 additions and 154 deletions
|
@ -1510,12 +1510,12 @@ impl Interactivity {
|
|||
};
|
||||
if self.location.is_some()
|
||||
&& text_bounds.contains(&cx.mouse_position())
|
||||
&& cx.modifiers().command
|
||||
&& cx.modifiers().secondary()
|
||||
{
|
||||
let command_held = cx.modifiers().command;
|
||||
let secondary_held = cx.modifiers().secondary();
|
||||
cx.on_key_event({
|
||||
move |e: &crate::ModifiersChangedEvent, _phase, cx| {
|
||||
if e.modifiers.command != command_held
|
||||
if e.modifiers.secondary() != secondary_held
|
||||
&& text_bounds.contains(&cx.mouse_position())
|
||||
{
|
||||
cx.refresh();
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Keystroke {
|
|||
control: self.modifiers.control,
|
||||
alt: false,
|
||||
shift: false,
|
||||
command: false,
|
||||
platform: false,
|
||||
function: false,
|
||||
},
|
||||
key: ime_key.to_string(),
|
||||
|
@ -62,7 +62,7 @@ impl Keystroke {
|
|||
let mut control = false;
|
||||
let mut alt = false;
|
||||
let mut shift = false;
|
||||
let mut command = false;
|
||||
let mut platform = false;
|
||||
let mut function = false;
|
||||
let mut key = None;
|
||||
let mut ime_key = None;
|
||||
|
@ -73,8 +73,13 @@ impl Keystroke {
|
|||
"ctrl" => control = true,
|
||||
"alt" => alt = true,
|
||||
"shift" => shift = true,
|
||||
"cmd" => command = true,
|
||||
"fn" => function = true,
|
||||
#[cfg(target_os = "macos")]
|
||||
"cmd" => platform = true,
|
||||
#[cfg(target_os = "linux")]
|
||||
"super" => platform = true,
|
||||
#[cfg(target_os = "windows")]
|
||||
"win" => platform = true,
|
||||
_ => {
|
||||
if let Some(next) = components.peek() {
|
||||
if next.is_empty() && source.ends_with('-') {
|
||||
|
@ -101,7 +106,7 @@ impl Keystroke {
|
|||
control,
|
||||
alt,
|
||||
shift,
|
||||
command,
|
||||
platform,
|
||||
function,
|
||||
},
|
||||
key,
|
||||
|
@ -114,7 +119,7 @@ impl Keystroke {
|
|||
/// be able to simulate typing "space", etc.
|
||||
pub fn with_simulated_ime(mut self) -> Self {
|
||||
if self.ime_key.is_none()
|
||||
&& !self.modifiers.command
|
||||
&& !self.modifiers.platform
|
||||
&& !self.modifiers.control
|
||||
&& !self.modifiers.function
|
||||
&& !self.modifiers.alt
|
||||
|
@ -147,8 +152,15 @@ impl std::fmt::Display for Keystroke {
|
|||
if self.modifiers.alt {
|
||||
f.write_char('⌥')?;
|
||||
}
|
||||
if self.modifiers.command {
|
||||
if self.modifiers.platform {
|
||||
#[cfg(target_os = "macos")]
|
||||
f.write_char('⌘')?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
f.write_char('❖')?;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
f.write_char('⊞')?;
|
||||
}
|
||||
if self.modifiers.shift {
|
||||
f.write_char('⇧')?;
|
||||
|
@ -188,7 +200,8 @@ pub struct Modifiers {
|
|||
|
||||
/// The command key, on macos
|
||||
/// the windows key, on windows
|
||||
pub command: bool,
|
||||
/// the super key, on linux
|
||||
pub platform: bool,
|
||||
|
||||
/// The function key
|
||||
pub function: bool,
|
||||
|
@ -197,7 +210,22 @@ pub struct Modifiers {
|
|||
impl Modifiers {
|
||||
/// Returns true if any modifier key is pressed
|
||||
pub fn modified(&self) -> bool {
|
||||
self.control || self.alt || self.shift || self.command || self.function
|
||||
self.control || self.alt || self.shift || self.platform || self.function
|
||||
}
|
||||
|
||||
/// Whether the semantically 'secondary' modifier key is pressed
|
||||
/// On macos, this is the command key
|
||||
/// On windows and linux, this is the control key
|
||||
pub fn secondary(&self) -> bool {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
return self.platform;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
return self.control;
|
||||
}
|
||||
}
|
||||
|
||||
/// helper method for Modifiers with no modifiers
|
||||
|
@ -205,10 +233,45 @@ impl Modifiers {
|
|||
Default::default()
|
||||
}
|
||||
|
||||
/// helper method for Modifiers with just command
|
||||
/// helper method for Modifiers with just the command key
|
||||
pub fn command() -> Modifiers {
|
||||
Modifiers {
|
||||
command: true,
|
||||
platform: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper method for Modifiers with just the secondary key pressed
|
||||
pub fn secondary_key() -> Modifiers {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
Modifiers {
|
||||
platform: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
Modifiers {
|
||||
control: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// helper method for Modifiers with just the windows key
|
||||
pub fn windows() -> Modifiers {
|
||||
Modifiers {
|
||||
platform: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// helper method for Modifiers with just the super key
|
||||
pub fn super_key() -> Modifiers {
|
||||
Modifiers {
|
||||
platform: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +296,7 @@ impl Modifiers {
|
|||
pub fn command_shift() -> Modifiers {
|
||||
Modifiers {
|
||||
shift: true,
|
||||
command: true,
|
||||
platform: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +306,7 @@ impl Modifiers {
|
|||
(other.control || !self.control)
|
||||
&& (other.alt || !self.alt)
|
||||
&& (other.shift || !self.shift)
|
||||
&& (other.command || !self.command)
|
||||
&& (other.platform || !self.platform)
|
||||
&& (other.function || !self.function)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ impl WaylandClient {
|
|||
control: false,
|
||||
alt: false,
|
||||
function: false,
|
||||
command: false,
|
||||
platform: false,
|
||||
},
|
||||
scroll_direction: -1.0,
|
||||
axis_source: AxisSource::Wheel,
|
||||
|
@ -692,6 +692,11 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
|
|||
group,
|
||||
..
|
||||
} => {
|
||||
let focused_window = state.keyboard_focused_window.clone();
|
||||
let Some(focused_window) = focused_window else {
|
||||
return;
|
||||
};
|
||||
|
||||
let keymap_state = state.keymap_state.as_mut().unwrap();
|
||||
keymap_state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
|
||||
|
@ -707,14 +712,22 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
|
|||
state.modifiers.shift = shift;
|
||||
state.modifiers.alt = alt;
|
||||
state.modifiers.control = control;
|
||||
state.modifiers.command = command;
|
||||
state.modifiers.platform = command;
|
||||
|
||||
let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||
modifiers: state.modifiers,
|
||||
});
|
||||
|
||||
drop(state);
|
||||
|
||||
focused_window.handle_input(input);
|
||||
}
|
||||
wl_keyboard::Event::Key {
|
||||
key,
|
||||
state: WEnum::Value(key_state),
|
||||
..
|
||||
} => {
|
||||
let focused_window = &state.keyboard_focused_window;
|
||||
let focused_window = state.keyboard_focused_window.clone();
|
||||
let Some(focused_window) = focused_window else {
|
||||
return;
|
||||
};
|
||||
|
@ -725,80 +738,56 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
|
|||
let keysym = keymap_state.key_get_one_sym(keycode);
|
||||
|
||||
match key_state {
|
||||
wl_keyboard::KeyState::Pressed => {
|
||||
let input = if keysym.is_modifier_key() {
|
||||
PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||
modifiers: state.modifiers,
|
||||
wl_keyboard::KeyState::Pressed if !keysym.is_modifier_key() => {
|
||||
let input = PlatformInput::KeyDown(KeyDownEvent {
|
||||
keystroke: Keystroke::from_xkb(keymap_state, state.modifiers, keycode),
|
||||
is_held: false, // todo(linux)
|
||||
});
|
||||
|
||||
state.repeat.current_id += 1;
|
||||
state.repeat.current_keysym = Some(keysym);
|
||||
|
||||
let rate = state.repeat.characters_per_second;
|
||||
let delay = state.repeat.delay;
|
||||
let id = state.repeat.current_id;
|
||||
let this = this.clone();
|
||||
|
||||
let timer = Timer::from_duration(delay);
|
||||
let state_ = Rc::clone(&this.client_state_inner);
|
||||
let input_ = input.clone();
|
||||
state
|
||||
.loop_handle
|
||||
.insert_source(timer, move |event, _metadata, shared_data| {
|
||||
let state_ = state_.borrow_mut();
|
||||
let is_repeating = id == state_.repeat.current_id
|
||||
&& state_.repeat.current_keysym.is_some()
|
||||
&& state_.keyboard_focused_window.is_some();
|
||||
|
||||
if !is_repeating {
|
||||
return TimeoutAction::Drop;
|
||||
}
|
||||
|
||||
let focused_window =
|
||||
state_.keyboard_focused_window.as_ref().unwrap().clone();
|
||||
|
||||
drop(state_);
|
||||
|
||||
focused_window.handle_input(input_.clone());
|
||||
|
||||
TimeoutAction::ToDuration(Duration::from_secs(1) / rate)
|
||||
})
|
||||
} else {
|
||||
PlatformInput::KeyDown(KeyDownEvent {
|
||||
keystroke: Keystroke::from_xkb(
|
||||
keymap_state,
|
||||
state.modifiers,
|
||||
keycode,
|
||||
),
|
||||
is_held: false, // todo(linux)
|
||||
})
|
||||
};
|
||||
|
||||
if !keysym.is_modifier_key() {
|
||||
state.repeat.current_id += 1;
|
||||
state.repeat.current_keysym = Some(keysym);
|
||||
|
||||
let rate = state.repeat.characters_per_second;
|
||||
let delay = state.repeat.delay;
|
||||
let id = state.repeat.current_id;
|
||||
let this = this.clone();
|
||||
|
||||
let timer = Timer::from_duration(delay);
|
||||
let state_ = Rc::clone(&this.client_state_inner);
|
||||
let input_ = input.clone();
|
||||
state
|
||||
.loop_handle
|
||||
.insert_source(timer, move |event, _metadata, shared_data| {
|
||||
let state_ = state_.borrow_mut();
|
||||
let is_repeating = id == state_.repeat.current_id
|
||||
&& state_.repeat.current_keysym.is_some()
|
||||
&& state_.keyboard_focused_window.is_some();
|
||||
|
||||
if !is_repeating {
|
||||
return TimeoutAction::Drop;
|
||||
}
|
||||
|
||||
let focused_window =
|
||||
state_.keyboard_focused_window.as_ref().unwrap().clone();
|
||||
|
||||
drop(state_);
|
||||
|
||||
focused_window.handle_input(input_.clone());
|
||||
|
||||
TimeoutAction::ToDuration(Duration::from_secs(1) / rate)
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
drop(state);
|
||||
|
||||
focused_window.handle_input(input);
|
||||
}
|
||||
wl_keyboard::KeyState::Released => {
|
||||
let input = if keysym.is_modifier_key() {
|
||||
PlatformInput::ModifiersChanged(ModifiersChangedEvent {
|
||||
modifiers: state.modifiers,
|
||||
})
|
||||
} else {
|
||||
PlatformInput::KeyUp(KeyUpEvent {
|
||||
keystroke: Keystroke::from_xkb(
|
||||
keymap_state,
|
||||
state.modifiers,
|
||||
keycode,
|
||||
),
|
||||
})
|
||||
};
|
||||
wl_keyboard::KeyState::Released if !keysym.is_modifier_key() => {
|
||||
let input = PlatformInput::KeyUp(KeyUpEvent {
|
||||
keystroke: Keystroke::from_xkb(keymap_state, state.modifiers, keycode),
|
||||
});
|
||||
|
||||
if !keysym.is_modifier_key() {
|
||||
state.repeat.current_keysym = None;
|
||||
}
|
||||
state.repeat.current_keysym = None;
|
||||
|
||||
drop(state);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ pub(crate) fn modifiers_from_state(state: xproto::KeyButMask) -> Modifiers {
|
|||
control: state.contains(xproto::KeyButMask::CONTROL),
|
||||
alt: state.contains(xproto::KeyButMask::MOD1),
|
||||
shift: state.contains(xproto::KeyButMask::SHIFT),
|
||||
command: state.contains(xproto::KeyButMask::MOD4),
|
||||
platform: state.contains(xproto::KeyButMask::MOD4),
|
||||
function: false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ unsafe fn read_modifiers(native_event: id) -> Modifiers {
|
|||
control,
|
||||
alt,
|
||||
shift,
|
||||
command,
|
||||
platform: command,
|
||||
function,
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ unsafe fn parse_keystroke(native_event: id) -> Keystroke {
|
|||
control,
|
||||
alt,
|
||||
shift,
|
||||
command,
|
||||
platform: command,
|
||||
function,
|
||||
},
|
||||
key,
|
||||
|
|
|
@ -279,7 +279,7 @@ impl MacPlatform {
|
|||
let mut mask = NSEventModifierFlags::empty();
|
||||
for (modifier, flag) in &[
|
||||
(
|
||||
keystroke.modifiers.command,
|
||||
keystroke.modifiers.platform,
|
||||
NSEventModifierFlags::NSCommandKeyMask,
|
||||
),
|
||||
(
|
||||
|
|
|
@ -853,7 +853,7 @@ impl PlatformWindow for MacWindow {
|
|||
control,
|
||||
alt,
|
||||
shift,
|
||||
command,
|
||||
platform: command,
|
||||
function,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ impl WindowsWindowInner {
|
|||
control: self.is_virtual_key_pressed(VK_CONTROL),
|
||||
alt: self.is_virtual_key_pressed(VK_MENU),
|
||||
shift: self.is_virtual_key_pressed(VK_SHIFT),
|
||||
command: self.is_virtual_key_pressed(VK_LWIN) || self.is_virtual_key_pressed(VK_RWIN),
|
||||
platform: self.is_virtual_key_pressed(VK_LWIN) || self.is_virtual_key_pressed(VK_RWIN),
|
||||
function: false,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue