actions: Shortcut handling changes for #1005
This commit is contained in:
parent
638684642c
commit
d76f372c29
6 changed files with 286 additions and 477 deletions
|
|
@ -5,6 +5,25 @@
|
|||
(modifiers: [Super], key: "Escape"): System(LockScreen),
|
||||
(modifiers: [Super], key: "q"): Close,
|
||||
|
||||
(modifiers: [Super], key: "Left"): Focus(Left),
|
||||
(modifiers: [Super], key: "Right"): Focus(Right),
|
||||
(modifiers: [Super], key: "Up"): Focus(Up),
|
||||
(modifiers: [Super], key: "Down"): Focus(Down),
|
||||
(modifiers: [Super], key: "h"): Focus(Left),
|
||||
(modifiers: [Super], key: "j"): Focus(Down),
|
||||
(modifiers: [Super], key: "k"): Focus(Up),
|
||||
(modifiers: [Super], key: "l"): Focus(Right),
|
||||
(modifiers: [Super], key: "u"): Focus(Out),
|
||||
(modifiers: [Super], key: "i"): Focus(In),
|
||||
(modifiers: [Super, Shift], key: "Left"): Move(Left),
|
||||
(modifiers: [Super, Shift], key: "Right"): Move(Right),
|
||||
(modifiers: [Super, Shift], key: "Up"): Move(Up),
|
||||
(modifiers: [Super, Shift], key: "Down"): Move(Down),
|
||||
(modifiers: [Super, Shift], key: "h"): Move(Left),
|
||||
(modifiers: [Super, Shift], key: "j"): Move(Down),
|
||||
(modifiers: [Super, Shift], key: "k"): Move(Up),
|
||||
(modifiers: [Super, Shift], key: "l"): Move(Right),
|
||||
|
||||
(modifiers: [Super], key: "1"): Workspace(1),
|
||||
(modifiers: [Super], key: "2"): Workspace(2),
|
||||
(modifiers: [Super], key: "3"): Workspace(3),
|
||||
|
|
@ -26,39 +45,39 @@
|
|||
(modifiers: [Super, Shift], key: "9"): MoveToWorkspace(9),
|
||||
(modifiers: [Super, Shift], key: "0"): MoveToLastWorkspace,
|
||||
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Left"): MoveToOutput(Left),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Down"): MoveToOutput(Down),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Up"): MoveToOutput(Up),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Right"): MoveToOutput(Right),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "h"): MoveToOutput(Left),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "k"): MoveToOutput(Down),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "j"): MoveToOutput(Up),
|
||||
(modifiers: [Super, Ctrl, Alt], key: "l"): MoveToOutput(Right),
|
||||
(modifiers: [Super, Ctrl], key: "Left"): PreviousWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "Down"): NextWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "Up"): PreviousWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "Right"): NextWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "h"): PreviousWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "k"): NextWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "j"): PreviousWorkspace,
|
||||
(modifiers: [Super, Ctrl], key: "l"): NextWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "Left"): MoveToPreviousWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "Down"): MoveToNextWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "Up"): MoveToPreviousWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "Right"): MoveToNextWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "h"): MoveToPreviousWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "k"): MoveToNextWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "j"): MoveToPreviousWorkspace,
|
||||
(modifiers: [Super, Shift, Ctrl], key: "l"): MoveToNextWorkspace,
|
||||
|
||||
(modifiers: [Super], key: "Period"): NextOutput,
|
||||
(modifiers: [Super], key: "Comma"): PreviousOutput,
|
||||
(modifiers: [Super, Shift], key: "Period"): MoveToNextOutput,
|
||||
(modifiers: [Super, Shift], key: "Comma"): MoveToPreviousOutput,
|
||||
|
||||
(modifiers: [Super], key: "Left"): Focus(Left),
|
||||
(modifiers: [Super], key: "Right"): Focus(Right),
|
||||
(modifiers: [Super], key: "Up"): Focus(Up),
|
||||
(modifiers: [Super], key: "Down"): Focus(Down),
|
||||
(modifiers: [Super], key: "h"): Focus(Left),
|
||||
(modifiers: [Super], key: "j"): Focus(Down),
|
||||
(modifiers: [Super], key: "k"): Focus(Up),
|
||||
(modifiers: [Super], key: "l"): Focus(Right),
|
||||
(modifiers: [Super], key: "u"): Focus(Out),
|
||||
(modifiers: [Super], key: "i"): Focus(In),
|
||||
|
||||
(modifiers: [Super, Shift], key: "Left"): Move(Left),
|
||||
(modifiers: [Super, Shift], key: "Right"): Move(Right),
|
||||
(modifiers: [Super, Shift], key: "Up"): Move(Up),
|
||||
(modifiers: [Super, Shift], key: "Down"): Move(Down),
|
||||
(modifiers: [Super, Shift], key: "h"): Move(Left),
|
||||
(modifiers: [Super, Shift], key: "j"): Move(Down),
|
||||
(modifiers: [Super, Shift], key: "k"): Move(Up),
|
||||
(modifiers: [Super, Shift], key: "l"): Move(Right),
|
||||
(modifiers: [Super, Alt], key: "Left"): SwitchOutput(Left),
|
||||
(modifiers: [Super, Alt], key: "Down"): SwitchOutput(Down),
|
||||
(modifiers: [Super, Alt], key: "Up"): SwitchOutput(Up),
|
||||
(modifiers: [Super, Alt], key: "Right"): SwitchOutput(Right),
|
||||
(modifiers: [Super, Alt], key: "h"): SwitchOutput(Left),
|
||||
(modifiers: [Super, Alt], key: "k"): SwitchOutput(Down),
|
||||
(modifiers: [Super, Alt], key: "j"): SwitchOutput(Up),
|
||||
(modifiers: [Super, Alt], key: "l"): SwitchOutput(Right),
|
||||
(modifiers: [Super, Shift, Alt], key: "Left"): MoveToOutput(Left),
|
||||
(modifiers: [Super, Shift, Alt], key: "Down"): MoveToOutput(Down),
|
||||
(modifiers: [Super, Shift, Alt], key: "Up"): MoveToOutput(Up),
|
||||
(modifiers: [Super, Shift, Alt], key: "Right"): MoveToOutput(Right),
|
||||
(modifiers: [Super, Shift, Alt], key: "h"): MoveToOutput(Left),
|
||||
(modifiers: [Super, Shift, Alt], key: "k"): MoveToOutput(Down),
|
||||
(modifiers: [Super, Shift, Alt], key: "j"): MoveToOutput(Up),
|
||||
(modifiers: [Super, Shift, Alt], key: "l"): MoveToOutput(Right),
|
||||
|
||||
(modifiers: [Super], key: "o"): ToggleOrientation,
|
||||
(modifiers: [Super], key: "s"): ToggleStacking,
|
||||
|
|
@ -72,6 +91,8 @@
|
|||
|
||||
(modifiers: [Super], key: "equal"): ZoomIn,
|
||||
(modifiers: [Super], key: "minus"): ZoomOut,
|
||||
(modifiers: [Super], key: "Period"): ZoomIn,
|
||||
(modifiers: [Super], key: "Comma"): ZoomOut,
|
||||
|
||||
(modifiers: [Super], key: "b"): System(WebBrowser),
|
||||
(modifiers: [Super], key: "f"): System(HomeFolder),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use cosmic_comp_config::workspace::WorkspaceLayout;
|
||||
use cosmic_settings_config::shortcuts::State as KeyState;
|
||||
use cosmic_settings_config::shortcuts::{self, Modifiers, Shortcuts};
|
||||
use cosmic_settings_config::shortcuts::{self, Modifiers};
|
||||
use smithay::input::keyboard::ModifiersState;
|
||||
use xkbcommon::xkb;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Action {
|
||||
|
|
@ -23,88 +21,6 @@ pub enum PrivateAction {
|
|||
),
|
||||
}
|
||||
|
||||
pub fn add_default_bindings(shortcuts: &mut Shortcuts, workspace_layout: WorkspaceLayout) {
|
||||
let (
|
||||
workspace_previous,
|
||||
workspace_next,
|
||||
(output_previous, output_previous_dir),
|
||||
(output_next, output_next_dir),
|
||||
) = match workspace_layout {
|
||||
WorkspaceLayout::Horizontal => (
|
||||
[xkb::Keysym::Left, xkb::Keysym::h],
|
||||
[xkb::Keysym::Right, xkb::Keysym::l],
|
||||
(
|
||||
[xkb::Keysym::Up, xkb::Keysym::k],
|
||||
shortcuts::action::Direction::Up,
|
||||
),
|
||||
(
|
||||
[xkb::Keysym::Down, xkb::Keysym::j],
|
||||
shortcuts::action::Direction::Down,
|
||||
),
|
||||
),
|
||||
WorkspaceLayout::Vertical => (
|
||||
[xkb::Keysym::Up, xkb::Keysym::k],
|
||||
[xkb::Keysym::Down, xkb::Keysym::j],
|
||||
(
|
||||
[xkb::Keysym::Left, xkb::Keysym::h],
|
||||
shortcuts::action::Direction::Left,
|
||||
),
|
||||
(
|
||||
[xkb::Keysym::Right, xkb::Keysym::l],
|
||||
shortcuts::action::Direction::Right,
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl(),
|
||||
workspace_previous.iter().copied(),
|
||||
shortcuts::Action::PreviousWorkspace,
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl(),
|
||||
workspace_next.iter().copied(),
|
||||
shortcuts::Action::NextWorkspace,
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl().shift(),
|
||||
workspace_previous.iter().copied(),
|
||||
shortcuts::Action::MoveToPreviousWorkspace,
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl().shift(),
|
||||
workspace_next.iter().copied(),
|
||||
shortcuts::Action::MoveToNextWorkspace,
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl(),
|
||||
output_previous.iter().copied(),
|
||||
shortcuts::Action::SwitchOutput(output_previous_dir),
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl(),
|
||||
output_next.iter().copied(),
|
||||
shortcuts::Action::SwitchOutput(output_next_dir),
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl().shift(),
|
||||
output_previous.iter().copied(),
|
||||
shortcuts::Action::MoveToOutput(output_previous_dir),
|
||||
);
|
||||
|
||||
shortcuts.insert_default_binding(
|
||||
Modifiers::new().logo().ctrl().shift(),
|
||||
output_next.iter().copied(),
|
||||
shortcuts::Action::MoveToOutput(output_next_dir),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert `cosmic_settings_config::shortcuts::State` to `smithay::backend::input::KeyState`.
|
||||
pub fn cosmic_keystate_to_smithay(value: KeyState) -> smithay::backend::input::KeyState {
|
||||
match value {
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ impl Config {
|
|||
})
|
||||
.expect("Failed to add cosmic-config to the event loop");
|
||||
let xdg = xdg::BaseDirectories::new().ok();
|
||||
let workspace = get_config::<WorkspaceConfig>(&config, "workspaces");
|
||||
|
||||
let cosmic_comp_config =
|
||||
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
|
||||
|
|
@ -241,10 +240,7 @@ impl Config {
|
|||
// Source key bindings from com.system76.CosmicSettings.Shortcuts
|
||||
let settings_context = shortcuts::context().expect("Failed to load shortcuts config");
|
||||
let system_actions = shortcuts::system_actions(&settings_context);
|
||||
let mut shortcuts = shortcuts::shortcuts(&settings_context);
|
||||
|
||||
// Add any missing default shortcuts recommended by the compositor.
|
||||
key_bindings::add_default_bindings(&mut shortcuts, workspace.workspace_layout);
|
||||
let shortcuts = shortcuts::shortcuts(&settings_context);
|
||||
|
||||
// Listen for updates to the keybindings config.
|
||||
match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) {
|
||||
|
|
@ -254,11 +250,7 @@ impl Config {
|
|||
match key.as_str() {
|
||||
// Reload the keyboard shortcuts config.
|
||||
"custom" | "defaults" => {
|
||||
let mut shortcuts = shortcuts::shortcuts(&config);
|
||||
let layout = get_config::<WorkspaceConfig>(&config, "workspaces")
|
||||
.workspace_layout;
|
||||
key_bindings::add_default_bindings(&mut shortcuts, layout);
|
||||
state.common.config.shortcuts = shortcuts;
|
||||
state.common.config.shortcuts = shortcuts::shortcuts(&config);
|
||||
}
|
||||
|
||||
"system_actions" => {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ use std::{os::unix::process::CommandExt, thread, time::Duration};
|
|||
|
||||
use super::gestures;
|
||||
|
||||
fn propagate_by_default(action: &shortcuts::Action) -> bool {
|
||||
match action {
|
||||
shortcuts::Action::Focus(_) | shortcuts::Action::Move(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn handle_action(
|
||||
&mut self,
|
||||
|
|
@ -37,7 +44,6 @@ impl State {
|
|||
time: u32,
|
||||
pattern: shortcuts::Binding,
|
||||
direction: Option<Direction>,
|
||||
propagate: bool,
|
||||
) {
|
||||
// TODO: Detect if started from login manager or tty, and only allow
|
||||
// `Terminate` if it will return to login manager.
|
||||
|
|
@ -52,9 +58,12 @@ impl State {
|
|||
}
|
||||
|
||||
match action {
|
||||
Action::Shortcut(action) => self
|
||||
.handle_shortcut_action(action, seat, serial, time, pattern, direction, propagate),
|
||||
|
||||
Action::Shortcut(action) => {
|
||||
let propagate = propagate_by_default(&action);
|
||||
self.handle_shortcut_action(
|
||||
action, seat, serial, time, pattern, direction, propagate,
|
||||
)
|
||||
}
|
||||
Action::Private(PrivateAction::Escape) => {
|
||||
{
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
|
@ -184,16 +193,40 @@ impl State {
|
|||
}
|
||||
|
||||
Action::NextWorkspace => {
|
||||
if let Some(direction) = pattern.inferred_direction() {
|
||||
if ((direction == Direction::Left || direction == Direction::Right)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Vertical)
|
||||
|| ((direction == Direction::Up || direction == Direction::Down)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Horizontal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let next = to_next_workspace(
|
||||
&mut *self.common.shell.write().unwrap(),
|
||||
seat,
|
||||
false,
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if next.is_err() && propagate {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
if next.is_err() {
|
||||
if propagate {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_shortcut_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
false,
|
||||
)
|
||||
};
|
||||
} else {
|
||||
self.handle_shortcut_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
Action::Workspace(1),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
|
|
@ -201,21 +234,45 @@ impl State {
|
|||
direction,
|
||||
false,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Action::PreviousWorkspace => {
|
||||
if let Some(direction) = pattern.inferred_direction() {
|
||||
if ((direction == Direction::Left || direction == Direction::Right)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Vertical)
|
||||
|| ((direction == Direction::Up || direction == Direction::Down)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Horizontal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let previous = to_previous_workspace(
|
||||
&mut *self.common.shell.write().unwrap(),
|
||||
seat,
|
||||
false,
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if previous.is_err() && propagate {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
if previous.is_err() {
|
||||
if propagate {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_shortcut_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
false,
|
||||
)
|
||||
};
|
||||
} else {
|
||||
self.handle_shortcut_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
Action::LastWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
|
|
@ -223,7 +280,7 @@ impl State {
|
|||
direction,
|
||||
false,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,24 +341,39 @@ impl State {
|
|||
}
|
||||
|
||||
x @ Action::MoveToNextWorkspace | x @ Action::SendToNextWorkspace => {
|
||||
if let Some(direction) = pattern.inferred_direction() {
|
||||
if ((direction == Direction::Left || direction == Direction::Right)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Vertical)
|
||||
|| ((direction == Direction::Up || direction == Direction::Down)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Horizontal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
let Some(focused_output) = seat.focused_output() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let res = {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let workspace = shell
|
||||
shell
|
||||
.workspaces
|
||||
.active_num(&focused_output)
|
||||
.1
|
||||
.saturating_add(1);
|
||||
shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&focused_output, Some(workspace)),
|
||||
matches!(x, Action::MoveToNextWorkspace),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
)
|
||||
.checked_add(1)
|
||||
.ok_or(InvalidWorkspaceIndex)
|
||||
.and_then(|workspace| {
|
||||
shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&focused_output, Some(workspace)),
|
||||
matches!(x, Action::MoveToNextWorkspace),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
)
|
||||
})
|
||||
};
|
||||
|
||||
match res {
|
||||
|
|
@ -315,6 +387,7 @@ impl State {
|
|||
matches!(x, Action::MoveToNextWorkspace),
|
||||
);
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(_) if propagate => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_shortcut_action(
|
||||
|
|
@ -332,30 +405,59 @@ impl State {
|
|||
)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
Err(_) => {
|
||||
// cycle through
|
||||
self.handle_shortcut_action(
|
||||
if matches!(x, Action::MoveToNextWorkspace) {
|
||||
Action::MoveToWorkspace(1)
|
||||
} else {
|
||||
Action::SendToWorkspace(1)
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x @ Action::MoveToPreviousWorkspace | x @ Action::SendToPreviousWorkspace => {
|
||||
if let Some(direction) = pattern.inferred_direction() {
|
||||
if ((direction == Direction::Left || direction == Direction::Right)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Vertical)
|
||||
|| ((direction == Direction::Up || direction == Direction::Down)
|
||||
&& self.common.config.cosmic_conf.workspaces.workspace_layout
|
||||
== WorkspaceLayout::Horizontal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
let Some(focused_output) = seat.focused_output() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let res = {
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
let workspace = shell
|
||||
shell
|
||||
.workspaces
|
||||
.active_num(&focused_output)
|
||||
.1
|
||||
.saturating_sub(1);
|
||||
// TODO: Possibly move to prev output, if idx < 0
|
||||
shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&focused_output, Some(workspace)),
|
||||
matches!(x, Action::MoveToPreviousWorkspace),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
)
|
||||
.checked_sub(1)
|
||||
.ok_or(InvalidWorkspaceIndex)
|
||||
.and_then(|workspace| {
|
||||
shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&focused_output, Some(workspace)),
|
||||
matches!(x, Action::MoveToPreviousWorkspace),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
)
|
||||
})
|
||||
};
|
||||
|
||||
match res {
|
||||
|
|
@ -368,6 +470,7 @@ impl State {
|
|||
matches!(x, Action::MoveToPreviousWorkspace),
|
||||
);
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(_) if propagate => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_shortcut_action(
|
||||
|
|
@ -385,7 +488,22 @@ impl State {
|
|||
)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
Err(_) => {
|
||||
// cycle through
|
||||
self.handle_shortcut_action(
|
||||
if matches!(x, Action::MoveToPreviousWorkspace) {
|
||||
Action::MoveToLastWorkspace
|
||||
} else {
|
||||
Action::SendToLastWorkspace
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,155 +559,15 @@ impl State {
|
|||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
} else if propagate {
|
||||
std::mem::drop(shell);
|
||||
|
||||
let action = match (
|
||||
direction,
|
||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||
) {
|
||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Up, WorkspaceLayout::Vertical) => {
|
||||
Some(Action::PreviousWorkspace)
|
||||
}
|
||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Down, WorkspaceLayout::Vertical) => {
|
||||
Some(Action::NextWorkspace)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(action) = action {
|
||||
self.handle_shortcut_action(
|
||||
action,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Action::NextOutput => {
|
||||
let current_output = seat.active_output();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
let next_output = shell
|
||||
.outputs()
|
||||
.skip_while(|o| *o != ¤t_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
if let Some(next_output) = next_output {
|
||||
let idx = shell.workspaces.active_num(&next_output).1;
|
||||
let res = shell.activate(
|
||||
&next_output,
|
||||
idx,
|
||||
WorkspaceDelta::new_shortcut(),
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
seat.set_active_output(&next_output);
|
||||
|
||||
if let Ok(Some(new_pos)) = res {
|
||||
let new_target = shell
|
||||
.workspaces
|
||||
.active(&next_output)
|
||||
.unwrap()
|
||||
.1
|
||||
.focus_stack
|
||||
.get(&seat)
|
||||
.last()
|
||||
.cloned()
|
||||
.map(KeyboardFocusTarget::from);
|
||||
std::mem::drop(shell);
|
||||
|
||||
let move_cursor = if let Some(under) = new_target {
|
||||
let update_cursor = self.common.config.cosmic_conf.focus_follows_cursor;
|
||||
Shell::set_focus(self, Some(&under), seat, None, update_cursor);
|
||||
!update_cursor
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
if move_cursor {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
}
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
warn!("Skipping deprecated shortcut NextOutput");
|
||||
}
|
||||
|
||||
Action::PreviousOutput => {
|
||||
let current_output = seat.active_output();
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
let prev_output = shell
|
||||
.outputs()
|
||||
.rev()
|
||||
.skip_while(|o| *o != ¤t_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
if let Some(prev_output) = prev_output {
|
||||
let idx = shell.workspaces.active_num(&prev_output).1;
|
||||
let res = shell.activate(
|
||||
&prev_output,
|
||||
idx,
|
||||
WorkspaceDelta::new_shortcut(),
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
seat.set_active_output(&prev_output);
|
||||
|
||||
if let Ok(Some(new_pos)) = res {
|
||||
let new_target = shell
|
||||
.workspaces
|
||||
.active(&prev_output)
|
||||
.unwrap()
|
||||
.1
|
||||
.focus_stack
|
||||
.get(&seat)
|
||||
.last()
|
||||
.cloned()
|
||||
.map(KeyboardFocusTarget::from);
|
||||
std::mem::drop(shell);
|
||||
|
||||
let move_cursor = if let Some(under) = new_target {
|
||||
let update_cursor = self.common.config.cosmic_conf.focus_follows_cursor;
|
||||
Shell::set_focus(self, Some(&under), seat, None, update_cursor);
|
||||
!update_cursor
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
if move_cursor {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
}
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
warn!("Skipping deprecated shortcut PreviousOutput");
|
||||
}
|
||||
|
||||
action @ Action::MoveToOutput(_) | action @ Action::SendToOutput(_) => {
|
||||
|
|
@ -631,170 +609,15 @@ impl State {
|
|||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
} else if propagate {
|
||||
std::mem::drop(shell);
|
||||
match (
|
||||
direction,
|
||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||
) {
|
||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Up, WorkspaceLayout::Vertical) => self
|
||||
.handle_shortcut_action(
|
||||
Action::MoveToPreviousWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
false,
|
||||
),
|
||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Down, WorkspaceLayout::Vertical) => self
|
||||
.handle_shortcut_action(
|
||||
Action::MoveToNextWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
false,
|
||||
),
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x @ Action::MoveToNextOutput | x @ Action::SendToNextOutput => {
|
||||
let Some(focused_output) = seat.focused_output() else {
|
||||
return;
|
||||
};
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
let next_output = shell
|
||||
.outputs()
|
||||
.skip_while(|o| *o != &focused_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
if let Some(next_output) = next_output {
|
||||
let res = shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&next_output, None),
|
||||
matches!(x, Action::MoveToNextOutput),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if let Ok(Some((target, new_pos))) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(
|
||||
self,
|
||||
Some(&target),
|
||||
seat,
|
||||
None,
|
||||
matches!(x, Action::MoveToNextOutput),
|
||||
);
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::MoveToNextOutput | Action::SendToNextOutput => {
|
||||
warn!("Ignoring deprecated action Move/SendToNextOutput");
|
||||
}
|
||||
|
||||
x @ Action::MoveToPreviousOutput | x @ Action::SendToPreviousOutput => {
|
||||
let Some(focused_output) = seat.focused_output() else {
|
||||
return;
|
||||
};
|
||||
let mut shell = self.common.shell.write().unwrap();
|
||||
|
||||
let prev_output = shell
|
||||
.outputs()
|
||||
.rev()
|
||||
.skip_while(|o| *o != &focused_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
if let Some(prev_output) = prev_output {
|
||||
let res = shell.move_current_window(
|
||||
seat,
|
||||
&focused_output,
|
||||
(&prev_output, None),
|
||||
matches!(x, Action::MoveToPreviousOutput),
|
||||
direction,
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if let Ok(Some((target, new_pos))) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(
|
||||
self,
|
||||
Some(&target),
|
||||
seat,
|
||||
None,
|
||||
matches!(x, Action::MoveToPreviousOutput),
|
||||
);
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Action::MigrateWorkspaceToNextOutput => {
|
||||
let active_output = seat.active_output();
|
||||
let (active, next_output) = {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
let output = shell
|
||||
.outputs()
|
||||
.skip_while(|o| *o != &active_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
|
||||
(shell.active_space(&active_output).unwrap().handle, output)
|
||||
};
|
||||
if let Some(next_output) = next_output {
|
||||
self.common
|
||||
.migrate_workspace(&active_output, &next_output, &active);
|
||||
}
|
||||
}
|
||||
|
||||
Action::MigrateWorkspaceToPreviousOutput => {
|
||||
let active_output = seat.active_output();
|
||||
let (active, prev_output) = {
|
||||
let shell = self.common.shell.read().unwrap();
|
||||
let output = shell
|
||||
.outputs()
|
||||
.rev()
|
||||
.skip_while(|o| *o != &active_output)
|
||||
.skip(1)
|
||||
.next()
|
||||
.cloned();
|
||||
|
||||
(shell.active_space(&active_output).unwrap().handle, output)
|
||||
};
|
||||
if let Some(prev_output) = prev_output {
|
||||
self.common
|
||||
.migrate_workspace(&active_output, &prev_output, &active);
|
||||
}
|
||||
Action::MoveToPreviousOutput | Action::SendToPreviousOutput => {
|
||||
warn!("Ignoring deprecated action Move/SendToPreviousOutput");
|
||||
}
|
||||
|
||||
Action::MigrateWorkspaceToOutput(direction) => {
|
||||
|
|
@ -814,6 +637,14 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
Action::MigrateWorkspaceToNextOutput => {
|
||||
warn!("Ignoring deprecated action MigrateWorkspaceToNextOutput");
|
||||
}
|
||||
|
||||
Action::MigrateWorkspaceToPreviousOutput => {
|
||||
warn!("Ignoring deprecated action MigrateWorkspaceToPreviousOutput");
|
||||
}
|
||||
|
||||
Action::Focus(focus) => {
|
||||
let result = self.common.shell.read().unwrap().next_focus(focus, seat);
|
||||
|
||||
|
|
@ -828,8 +659,23 @@ impl State {
|
|||
};
|
||||
|
||||
if let Some(direction) = dir {
|
||||
let action = match (
|
||||
direction,
|
||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||
) {
|
||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Up, WorkspaceLayout::Vertical) => {
|
||||
Action::PreviousWorkspace
|
||||
}
|
||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Down, WorkspaceLayout::Vertical) => {
|
||||
Action::NextWorkspace
|
||||
}
|
||||
_ => Action::SwitchOutput(direction),
|
||||
};
|
||||
|
||||
self.handle_shortcut_action(
|
||||
Action::SwitchOutput(direction),
|
||||
action,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
|
|
@ -854,15 +700,32 @@ impl State {
|
|||
.unwrap()
|
||||
.move_current_element(direction, seat);
|
||||
match res {
|
||||
MoveResult::MoveFurther(_move_further) => self.handle_shortcut_action(
|
||||
Action::MoveToOutput(direction),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
true,
|
||||
),
|
||||
MoveResult::MoveFurther(_move_further) => {
|
||||
let action = match (
|
||||
direction,
|
||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||
) {
|
||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Up, WorkspaceLayout::Vertical) => {
|
||||
Action::MoveToPreviousWorkspace
|
||||
}
|
||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||
| (Direction::Down, WorkspaceLayout::Vertical) => {
|
||||
Action::MoveToNextWorkspace
|
||||
}
|
||||
_ => Action::MoveToOutput(direction),
|
||||
};
|
||||
|
||||
self.handle_shortcut_action(
|
||||
action,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
true,
|
||||
)
|
||||
}
|
||||
MoveResult::ShiftFocus(shift) => {
|
||||
Shell::set_focus(self, Some(&shift), seat, None, true);
|
||||
}
|
||||
|
|
@ -1159,7 +1022,8 @@ fn to_next_workspace(
|
|||
.workspaces
|
||||
.active_num(¤t_output)
|
||||
.1
|
||||
.saturating_add(1);
|
||||
.checked_add(1)
|
||||
.ok_or(InvalidWorkspaceIndex)?;
|
||||
|
||||
shell.activate(
|
||||
¤t_output,
|
||||
|
|
@ -1184,7 +1048,8 @@ fn to_previous_workspace(
|
|||
.workspaces
|
||||
.active_num(¤t_output)
|
||||
.1
|
||||
.saturating_sub(1);
|
||||
.checked_sub(1)
|
||||
.ok_or(InvalidWorkspaceIndex)?;
|
||||
|
||||
shell.activate(
|
||||
¤t_output,
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ impl State {
|
|||
FilterResult::<()>::Forward
|
||||
});
|
||||
}
|
||||
self.handle_action(action, &seat, serial, time, pattern, None, true)
|
||||
self.handle_action(action, &seat, serial, time, pattern, None)
|
||||
}
|
||||
|
||||
// If we want to track numlock state so it can be reused on the next boot...
|
||||
|
|
@ -1639,7 +1639,6 @@ impl State {
|
|||
time.overflowing_add(duration as u32).0,
|
||||
key_pattern_clone.clone(),
|
||||
None,
|
||||
true,
|
||||
);
|
||||
calloop::timer::TimeoutAction::ToDuration(Duration::from_millis(25))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2653,11 +2653,27 @@ impl Shell {
|
|||
) -> Result<Option<(KeyboardFocusTarget, Point<i32, Global>)>, InvalidWorkspaceIndex> {
|
||||
let (to_output, to_idx) = to;
|
||||
let to_idx = to_idx.unwrap_or(self.workspaces.active_num(to_output).1);
|
||||
let from_idx = self.workspaces.active_num(from_output).1;
|
||||
|
||||
if from_output == to_output && to_idx == self.workspaces.active_num(from_output).1 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if from_output == to_output
|
||||
&& to_idx.checked_sub(1).is_some_and(|idx| idx == from_idx)
|
||||
&& to_idx == self.workspaces.len(to_output) - 1
|
||||
&& self
|
||||
.workspaces
|
||||
.get(from_idx, from_output)
|
||||
.is_some_and(|w| w.mapped().count() == 1)
|
||||
&& self
|
||||
.workspaces
|
||||
.get(to_idx, to_output)
|
||||
.is_some_and(|w| w.is_empty())
|
||||
{
|
||||
return Err(InvalidWorkspaceIndex);
|
||||
}
|
||||
|
||||
let to = self
|
||||
.workspaces
|
||||
.get(to_idx, to_output)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue