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:
Mikayla Maki 2024-04-01 17:22:59 -07:00 committed by GitHub
parent e0cd96db7b
commit 1da2441e7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 220 additions and 154 deletions

View File

@ -219,7 +219,7 @@
"context": "BufferSearchBar && in_replace",
"bindings": {
"enter": "search::ReplaceNext",
"cmd-enter": "search::ReplaceAll"
"ctrl-enter": "search::ReplaceAll"
}
},
{
@ -258,7 +258,7 @@
"bindings": {
"escape": "project_search::ToggleFocus",
"alt-tab": "search::CycleMode",
"cmd-shift-h": "search::ToggleReplace",
"ctrl-shift-h": "search::ToggleReplace",
"alt-ctrl-g": "search::ActivateRegexMode",
"alt-ctrl-x": "search::ActivateTextMode"
}
@ -304,8 +304,10 @@
}
],
"ctrl-alt-shift-down": "editor::DuplicateLine",
"ctrl-shift-right": "editor::SelectLargerSyntaxNode",
"ctrl-shift-left": "editor::SelectSmallerSyntaxNode",
"ctrl-shift-left": "editor::SelectToPreviousWordStart",
"ctrl-shift-right": "editor::SelectToNextWordEnd",
"ctrl-shift-up": "editor::SelectLargerSyntaxNode", //todo(linux) tmp keybinding
"ctrl-shift-down": "editor::SelectSmallerSyntaxNode", //todo(linux) tmp keybinding
"ctrl-d": [
"editor::SelectNext",
{
@ -354,14 +356,14 @@
"ctrl-shift-]": "editor::UnfoldLines",
"ctrl-space": "editor::ShowCompletions",
"ctrl-.": "editor::ToggleCodeActions",
"alt-cmd-r": "editor::RevealInFinder",
"alt-ctrl-r": "editor::RevealInFinder",
"ctrl-alt-shift-c": "editor::DisplayCursorNames"
}
},
{
"context": "Editor && mode == full",
"bindings": {
"cmd-shift-o": "outline::Toggle",
"ctrl-shift-o": "outline::Toggle",
"ctrl-g": "go_to_line::Toggle"
}
},
@ -419,7 +421,7 @@
"ctrl-shift-f": "pane::DeploySearch",
"ctrl-k ctrl-s": "zed::OpenKeymap",
"ctrl-k ctrl-t": "theme_selector::Toggle",
"ctrl-t": "project_symbols::Toggle",
"ctrl-shift-t": "project_symbols::Toggle",
"ctrl-p": "file_finder::Toggle",
"ctrl-tab": "tab_switcher::Toggle",
"ctrl-shift-tab": ["tab_switcher::Toggle", { "select_last": true }],
@ -549,7 +551,7 @@
"delete": "project_panel::Delete",
"ctrl-backspace": ["project_panel::Delete", { "skip_prompt": true }],
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": true }],
"alt-cmd-r": "project_panel::RevealInFinder",
"alt-ctrl-r": "project_panel::RevealInFinder",
"alt-shift-f": "project_panel::NewSearchInDirectory"
}
},
@ -610,7 +612,12 @@
"pagedown": ["terminal::SendKeystroke", "pagedown"],
"escape": ["terminal::SendKeystroke", "escape"],
"enter": ["terminal::SendKeystroke", "enter"],
"ctrl-c": ["terminal::SendKeystroke", "ctrl-c"]
"ctrl-c": ["terminal::SendKeystroke", "ctrl-c"],
// Some nice conveniences
"ctrl-backspace": ["terminal::SendText", "\u0015"],
"ctrl-right": ["terminal::SendText", "\u0005"],
"ctrl-left": ["terminal::SendText", "\u0001"]
}
}
]

View File

@ -48,7 +48,8 @@
// which gives the same size as all other panes.
"active_pane_magnification": 1.0,
// The key to use for adding multiple cursors
// Currently "alt" or "cmd" are supported.
// Currently "alt" or "cmd_or_ctrl" (also aliased as
// "cmd" and "ctrl") are supported.
"multi_cursor_modifier": "alt",
// Whether to enable vim modes and key bindings
"vim_mode": false,

View File

@ -92,7 +92,8 @@ pub enum ShowScrollbar {
#[serde(rename_all = "snake_case")]
pub enum MultiCursorModifier {
Alt,
Cmd,
#[serde(alias = "cmd", alias = "ctrl")]
CmdOrCtrl,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]

View File

@ -449,7 +449,8 @@ impl EditorElement {
},
cx,
);
} else if modifiers.shift && !modifiers.control && !modifiers.alt && !modifiers.command {
} else if modifiers.shift && !modifiers.control && !modifiers.alt && !modifiers.secondary()
{
editor.select(
SelectPhase::Extend {
position,
@ -461,7 +462,7 @@ impl EditorElement {
let multi_cursor_setting = EditorSettings::get_global(cx).multi_cursor_modifier;
let multi_cursor_modifier = match multi_cursor_setting {
MultiCursorModifier::Alt => modifiers.alt,
MultiCursorModifier::Cmd => modifiers.command,
MultiCursorModifier::CmdOrCtrl => modifiers.secondary(),
};
editor.select(
SelectPhase::Begin {
@ -513,8 +514,8 @@ impl EditorElement {
let multi_cursor_setting = EditorSettings::get_global(cx).multi_cursor_modifier;
let multi_cursor_modifier = match multi_cursor_setting {
MultiCursorModifier::Alt => event.modifiers.command,
MultiCursorModifier::Cmd => event.modifiers.alt,
MultiCursorModifier::Alt => event.modifiers.secondary(),
MultiCursorModifier::CmdOrCtrl => event.modifiers.alt,
};
if !pending_nonempty_selections && multi_cursor_modifier && text_hitbox.is_hovered(cx) {

View File

@ -93,7 +93,7 @@ impl Editor {
modifiers: Modifiers,
cx: &mut ViewContext<Self>,
) {
if !modifiers.command || self.has_pending_selection() {
if !modifiers.secondary() || self.has_pending_selection() {
self.hide_hovered_link(cx);
return;
}
@ -113,7 +113,7 @@ impl Editor {
&snapshot,
point_for_position,
self,
modifiers.command,
modifiers.secondary(),
modifiers.shift,
cx,
);
@ -256,7 +256,7 @@ pub fn update_inlay_link_and_hover_points(
snapshot: &EditorSnapshot,
point_for_position: PointForPosition,
editor: &mut Editor,
cmd_held: bool,
secondary_held: bool,
shift_held: bool,
cx: &mut ViewContext<'_, Editor>,
) {
@ -394,7 +394,9 @@ pub fn update_inlay_link_and_hover_points(
if let Some((language_server_id, location)) =
hovered_hint_part.location
{
if cmd_held && !editor.has_pending_nonempty_selection() {
if secondary_held
&& !editor.has_pending_nonempty_selection()
{
go_to_definition_updated = true;
show_link_definition(
shift_held,
@ -762,7 +764,7 @@ mod tests {
let «variable» = A;
"});
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
cx.run_until_parked();
// Assert no link highlights
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
@ -823,7 +825,7 @@ mod tests {
])))
});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
@ -849,7 +851,7 @@ mod tests {
])))
});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
@ -868,7 +870,7 @@ mod tests {
// No definitions returned
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![])))
});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
@ -912,7 +914,7 @@ mod tests {
])))
});
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
@ -928,7 +930,7 @@ mod tests {
fn do_work() { test(); }
"});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
fn test() { do_work(); }
@ -940,7 +942,7 @@ mod tests {
fn test() { do_work(); }
fn do_work() { tesˇt(); }
"});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
fn test() { do_work(); }
@ -948,7 +950,7 @@ mod tests {
"});
// Cmd click with existing definition doesn't re-request and dismisses highlight
cx.simulate_click(hover_point, Modifiers::command());
cx.simulate_click(hover_point, Modifiers::secondary_key());
cx.lsp
.handle_request::<GotoDefinition, _, _>(move |_, _| async move {
// Empty definition response to make sure we aren't hitting the lsp and using
@ -987,7 +989,7 @@ mod tests {
},
])))
});
cx.simulate_click(hover_point, Modifiers::command());
cx.simulate_click(hover_point, Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
cx.assert_editor_state(indoc! {"
@ -1030,7 +1032,7 @@ mod tests {
s.set_pending_anchor_range(anchor_range, crate::SelectMode::Character)
});
});
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
assert!(requests.try_next().is_err());
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
@ -1144,7 +1146,7 @@ mod tests {
});
// Press cmd to trigger highlight
let hover_point = cx.pixel_position_for(midpoint);
cx.simulate_mouse_move(hover_point, Modifiers::command());
cx.simulate_mouse_move(hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.update_editor(|editor, cx| {
let snapshot = editor.snapshot(cx);
@ -1175,9 +1177,9 @@ mod tests {
assert!(actual_ranges.is_empty(), "When no cmd is pressed, should have no hint label selected, but got: {actual_ranges:?}");
});
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.simulate_click(hover_point, Modifiers::command());
cx.simulate_click(hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.assert_editor_state(indoc! {"
struct «TestStructˇ»;
@ -1207,12 +1209,12 @@ mod tests {
Let's test a [complex](https://zed.dev/channel/had-(ˇoops)) case.
"});
cx.simulate_mouse_move(screen_coord, Modifiers::command());
cx.simulate_mouse_move(screen_coord, Modifiers::secondary_key());
cx.assert_editor_text_highlights::<HoveredLinkState>(indoc! {"
Let's test a [complex](«https://zed.dev/channel/had-(oops)ˇ») case.
"});
cx.simulate_click(screen_coord, Modifiers::command());
cx.simulate_click(screen_coord, Modifiers::secondary_key());
assert_eq!(
cx.opened_url(),
Some("https://zed.dev/channel/had-(oops)".into())
@ -1235,12 +1237,12 @@ mod tests {
let screen_coord =
cx.pixel_position(indoc! {"https://zed.dev/relˇeases is a cool webpage."});
cx.simulate_mouse_move(screen_coord, Modifiers::command());
cx.simulate_mouse_move(screen_coord, Modifiers::secondary_key());
cx.assert_editor_text_highlights::<HoveredLinkState>(
indoc! {"«https://zed.dev/releasesˇ» is a cool webpage."},
);
cx.simulate_click(screen_coord, Modifiers::command());
cx.simulate_click(screen_coord, Modifiers::secondary_key());
assert_eq!(cx.opened_url(), Some("https://zed.dev/releases".into()));
}
@ -1260,12 +1262,12 @@ mod tests {
let screen_coord =
cx.pixel_position(indoc! {"A cool webpage is https://zed.dev/releˇases"});
cx.simulate_mouse_move(screen_coord, Modifiers::command());
cx.simulate_mouse_move(screen_coord, Modifiers::secondary_key());
cx.assert_editor_text_highlights::<HoveredLinkState>(
indoc! {"A cool webpage is «https://zed.dev/releasesˇ»"},
);
cx.simulate_click(screen_coord, Modifiers::command());
cx.simulate_click(screen_coord, Modifiers::secondary_key());
assert_eq!(cx.opened_url(), Some("https://zed.dev/releases".into()));
}
@ -1386,7 +1388,7 @@ mod tests {
});
for _ in 0..5 {
cx.simulate_click(definition_hover_point, Modifiers::command());
cx.simulate_click(definition_hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.assert_editor_state(indoc! {"
fn test() {
@ -1398,7 +1400,7 @@ mod tests {
}
"});
cx.simulate_click(reference_hover_point, Modifiers::command());
cx.simulate_click(reference_hover_point, Modifiers::secondary_key());
cx.background_executor.run_until_parked();
cx.assert_editor_state(indoc! {"
fn «testˇ»() {

View File

@ -1490,7 +1490,7 @@ async fn test_keeps_file_finder_open_after_modifier_keys_release(cx: &mut gpui::
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
open_file_picker(&workspace, cx);
cx.simulate_modifiers_change(Modifiers::none());
@ -1519,7 +1519,7 @@ async fn test_opens_file_on_modifier_keys_release(cx: &mut gpui::TestAppContext)
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
let picker = open_file_picker(&workspace, cx);
picker.update(cx, |finder, _| {
assert_eq!(finder.delegate.matches.len(), 2);
@ -1560,7 +1560,7 @@ async fn test_switches_between_release_norelease_modes_on_forward_nav(
open_queried_buffer("2", 1, "2.txt", &workspace, cx).await;
// Open with a shortcut
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
let picker = open_file_picker(&workspace, cx);
picker.update(cx, |finder, _| {
assert_eq!(finder.delegate.matches.len(), 2);
@ -1581,7 +1581,7 @@ async fn test_switches_between_release_norelease_modes_on_forward_nav(
// Back to navigation with initial shortcut
// Open file on modifiers release
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
cx.dispatch_action(Toggle);
cx.simulate_modifiers_change(Modifiers::none());
cx.read(|cx| {
@ -1617,7 +1617,7 @@ async fn test_switches_between_release_norelease_modes_on_backward_nav(
open_queried_buffer("3", 1, "3.txt", &workspace, cx).await;
// Open with a shortcut
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
let picker = open_file_picker(&workspace, cx);
picker.update(cx, |finder, _| {
assert_eq!(finder.delegate.matches.len(), 3);
@ -1640,7 +1640,7 @@ async fn test_switches_between_release_norelease_modes_on_backward_nav(
// Back to navigation with initial shortcut
// Open file on modifiers release
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
cx.dispatch_action(SelectPrev); // <-- File Finder's SelectPrev, not menu's
cx.simulate_modifiers_change(Modifiers::none());
cx.read(|cx| {
@ -1669,7 +1669,7 @@ async fn test_extending_modifiers_does_not_confirm_selection(cx: &mut gpui::Test
open_queried_buffer("1", 1, "1.txt", &workspace, cx).await;
cx.simulate_modifiers_change(Modifiers::command());
cx.simulate_modifiers_change(Modifiers::secondary_key());
open_file_picker(&workspace, cx);
cx.simulate_modifiers_change(Modifiers::command_shift());

View File

@ -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();

View File

@ -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)
}
}

View File

@ -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);

View File

@ -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,
}
}

View File

@ -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,

View File

@ -279,7 +279,7 @@ impl MacPlatform {
let mut mask = NSEventModifierFlags::empty();
for (modifier, flag) in &[
(
keystroke.modifiers.command,
keystroke.modifiers.platform,
NSEventModifierFlags::NSCommandKeyMask,
),
(

View File

@ -853,7 +853,7 @@ impl PlatformWindow for MacWindow {
control,
alt,
shift,
command,
platform: command,
function,
}
}

View File

@ -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,
}
}

View File

@ -418,7 +418,7 @@ impl<D: PickerDelegate> Picker<D> {
.id(("item", ix))
.cursor_pointer()
.on_click(cx.listener(move |this, event: &ClickEvent, cx| {
this.handle_click(ix, event.down.modifiers.command, cx)
this.handle_click(ix, event.down.modifiers.secondary(), cx)
}))
// As of this writing, GPUI intercepts `ctrl-[mouse-event]`s on macOS
// and produces right mouse button events. This matches platforms norms
@ -427,7 +427,9 @@ impl<D: PickerDelegate> Picker<D> {
.on_mouse_up(
MouseButton::Right,
cx.listener(move |this, event: &MouseUpEvent, cx| {
this.handle_click(ix, event.modifiers.command, cx)
// We specficially want to use the platform key here, as
// ctrl will already be held down for the tab switcher.
this.handle_click(ix, event.modifiers.platform, cx)
}),
)
.children(

View File

@ -1456,7 +1456,7 @@ impl ProjectPanel {
if kind.is_dir() {
this.toggle_expanded(entry_id, cx);
} else {
if event.down.modifiers.command {
if event.down.modifiers.secondary() {
this.split_entry(entry_id, cx);
} else {
this.open_entry(entry_id, event.up.click_count > 1, cx);

View File

@ -18,7 +18,7 @@ impl AlacModifiers {
ks.modifiers.alt,
ks.modifiers.control,
ks.modifiers.shift,
ks.modifiers.command,
ks.modifiers.platform,
) {
(false, false, false, false) => AlacModifiers::None,
(true, false, false, false) => AlacModifiers::Alt,
@ -336,7 +336,7 @@ mod test {
control: false,
alt: false,
shift: false,
command: false,
platform: false,
function: false,
},
key: "🖖🏻".to_string(), //2 char string

View File

@ -432,7 +432,7 @@ impl TerminalBuilder {
last_mouse_position: None,
next_link_id: 0,
selection_phase: SelectionPhase::Ended,
cmd_pressed: false,
secondary_pressed: false,
hovered_word: false,
url_regex,
word_regex,
@ -585,7 +585,7 @@ pub struct Terminal {
scroll_px: Pixels,
next_link_id: usize,
selection_phase: SelectionPhase,
cmd_pressed: bool,
secondary_pressed: bool,
hovered_word: bool,
url_regex: RegexSearch,
word_regex: RegexSearch,
@ -1029,11 +1029,11 @@ impl Terminal {
}
pub fn try_modifiers_change(&mut self, modifiers: &Modifiers) -> bool {
let changed = self.cmd_pressed != modifiers.command;
if !self.cmd_pressed && modifiers.command {
let changed = self.secondary_pressed != modifiers.secondary();
if !self.secondary_pressed && modifiers.secondary() {
self.refresh_hovered_word();
}
self.cmd_pressed = modifiers.command;
self.secondary_pressed = modifiers.secondary();
changed
}
@ -1136,7 +1136,7 @@ impl Terminal {
self.pty_tx.notify(bytes);
}
}
} else if self.cmd_pressed {
} else if self.secondary_pressed {
self.word_from_position(Some(position));
}
}
@ -1266,7 +1266,7 @@ impl Terminal {
let mouse_cell_index = content_index_for_mouse(position, &self.last_content.size);
if let Some(link) = self.last_content.cells[mouse_cell_index].hyperlink() {
cx.open_url(link.uri());
} else if self.cmd_pressed {
} else if self.secondary_pressed {
self.events
.push_back(InternalEvent::FindHyperlink(position, true));
}
@ -1402,7 +1402,7 @@ impl Terminal {
}
pub fn can_navigate_to_selected_word(&self) -> bool {
self.cmd_pressed && self.hovered_word
self.secondary_pressed && self.hovered_word
}
pub fn task(&self) -> Option<&TaskState> {

View File

@ -113,7 +113,7 @@ impl RenderOnce for KeyBinding {
el.child(Key::new("Alt")).child(Key::new("+"))
}
})
.when(keystroke.modifiers.command, |el| {
.when(keystroke.modifiers.platform, |el| {
match self.platform_style {
PlatformStyle::Mac => el.child(KeyIcon::new(IconName::Command)),
PlatformStyle::Linux => {

View File

@ -120,7 +120,7 @@ impl NeovimConnection {
let special = keystroke.modifiers.shift
|| keystroke.modifiers.control
|| keystroke.modifiers.alt
|| keystroke.modifiers.command
|| keystroke.modifiers.platform
|| keystroke.key.len() > 1;
let start = if special { "<" } else { "" };
let shift = if keystroke.modifiers.shift { "S-" } else { "" };
@ -130,7 +130,7 @@ impl NeovimConnection {
""
};
let alt = if keystroke.modifiers.alt { "M-" } else { "" };
let cmd = if keystroke.modifiers.command {
let cmd = if keystroke.modifiers.platform {
"D-"
} else {
""