input: Take into account output layout
This commit is contained in:
parent
92c16bd4ad
commit
59581f717f
4 changed files with 238 additions and 81 deletions
12
config.ron
12
config.ron
|
|
@ -25,10 +25,14 @@
|
|||
(modifiers: [Super, Shift], key: "9"): MoveToWorkspace(9),
|
||||
(modifiers: [Super, Shift], key: "0"): MoveToLastWorkspace,
|
||||
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Down"): MoveToNextOutput,
|
||||
(modifiers: [Super, Ctrl, Alt], key: "Up"): MoveToPreviousOutput,
|
||||
(modifiers: [Super, Ctrl, Alt], key: "j"): MoveToNextOutput,
|
||||
(modifiers: [Super, Ctrl, Alt], key: "k"): MoveToPreviousOutput,
|
||||
(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], key: "Period"): NextOutput,
|
||||
(modifiers: [Super], key: "Comma"): PreviousOutput,
|
||||
|
|
|
|||
|
|
@ -101,6 +101,16 @@ impl KeyPattern {
|
|||
key,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inferred_direction(&self) -> Option<Direction> {
|
||||
match self.key? {
|
||||
Keysym::Left | Keysym::h | Keysym::H => Some(Direction::Left),
|
||||
Keysym::Down | Keysym::j | Keysym::J => Some(Direction::Down),
|
||||
Keysym::Up | Keysym::k | Keysym::K => Some(Direction::Up),
|
||||
Keysym::Right | Keysym::l | Keysym::L => Some(Direction::Right),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for KeyPattern {
|
||||
|
|
@ -153,6 +163,9 @@ pub enum Action {
|
|||
MoveToPreviousOutput,
|
||||
SendToNextOutput,
|
||||
SendToPreviousOutput,
|
||||
SwitchOutput(Direction),
|
||||
MoveToOutput(Direction),
|
||||
SendToOutput(Direction),
|
||||
|
||||
Focus(FocusDirection),
|
||||
Move(Direction),
|
||||
|
|
@ -195,19 +208,23 @@ pub fn add_default_bindings(
|
|||
key_bindings: &mut HashMap<KeyPattern, Action>,
|
||||
workspace_layout: WorkspaceLayout,
|
||||
) {
|
||||
let (workspace_previous, workspace_next, output_previous, output_next) = match workspace_layout
|
||||
{
|
||||
let (
|
||||
workspace_previous,
|
||||
workspace_next,
|
||||
(output_previous, output_previous_dir),
|
||||
(output_next, output_next_dir),
|
||||
) = match workspace_layout {
|
||||
WorkspaceLayout::Horizontal => (
|
||||
[Keysym::Left, Keysym::h],
|
||||
[Keysym::Right, Keysym::l],
|
||||
[Keysym::Up, Keysym::k],
|
||||
[Keysym::Down, Keysym::j],
|
||||
([Keysym::Up, Keysym::k], Direction::Up),
|
||||
([Keysym::Down, Keysym::j], Direction::Down),
|
||||
),
|
||||
WorkspaceLayout::Vertical => (
|
||||
[Keysym::Up, Keysym::k],
|
||||
[Keysym::Down, Keysym::j],
|
||||
[Keysym::Left, Keysym::h],
|
||||
[Keysym::Right, Keysym::l],
|
||||
([Keysym::Left, Keysym::h], Direction::Left),
|
||||
([Keysym::Right, Keysym::l], Direction::Right),
|
||||
),
|
||||
};
|
||||
|
||||
|
|
@ -262,7 +279,7 @@ pub fn add_default_bindings(
|
|||
..Default::default()
|
||||
},
|
||||
output_previous.iter().copied(),
|
||||
Action::PreviousOutput,
|
||||
Action::SwitchOutput(output_previous_dir),
|
||||
);
|
||||
insert_binding(
|
||||
key_bindings,
|
||||
|
|
@ -272,7 +289,7 @@ pub fn add_default_bindings(
|
|||
..Default::default()
|
||||
},
|
||||
output_next.iter().copied(),
|
||||
Action::NextOutput,
|
||||
Action::SwitchOutput(output_next_dir),
|
||||
);
|
||||
insert_binding(
|
||||
key_bindings,
|
||||
|
|
@ -283,7 +300,7 @@ pub fn add_default_bindings(
|
|||
..Default::default()
|
||||
},
|
||||
output_previous.iter().copied(),
|
||||
Action::MoveToPreviousOutput,
|
||||
Action::MoveToOutput(output_previous_dir),
|
||||
);
|
||||
insert_binding(
|
||||
key_bindings,
|
||||
|
|
@ -294,6 +311,6 @@ pub fn add_default_bindings(
|
|||
..Default::default()
|
||||
},
|
||||
output_next.iter().copied(),
|
||||
Action::MoveToNextOutput,
|
||||
Action::MoveToOutput(output_next_dir),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
235
src/input/mod.rs
235
src/input/mod.rs
|
|
@ -1221,7 +1221,16 @@ impl State {
|
|||
.activate(¤t_output, workspace)
|
||||
.is_err()
|
||||
{
|
||||
self.handle_action(Action::NextOutput, seat, serial, time, pattern, direction);
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
Action::PreviousWorkspace => {
|
||||
|
|
@ -1239,14 +1248,16 @@ impl State {
|
|||
.activate(¤t_output, workspace)
|
||||
.is_err()
|
||||
{
|
||||
self.handle_action(
|
||||
Action::PreviousOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
);
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
Action::LastWorkspace => {
|
||||
|
|
@ -1295,18 +1306,20 @@ impl State {
|
|||
)
|
||||
.is_err()
|
||||
{
|
||||
self.handle_action(
|
||||
if matches!(x, Action::MoveToNextWorkspace) {
|
||||
Action::MoveToNextOutput
|
||||
} else {
|
||||
Action::SendToNextOutput
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
if matches!(x, Action::MoveToNextWorkspace) {
|
||||
Action::MoveToOutput(inferred)
|
||||
} else {
|
||||
Action::SendToOutput(inferred)
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
x @ Action::MoveToPreviousWorkspace | x @ Action::SendToPreviousWorkspace => {
|
||||
|
|
@ -1329,18 +1342,20 @@ impl State {
|
|||
)
|
||||
.is_err()
|
||||
{
|
||||
self.handle_action(
|
||||
if matches!(x, Action::MoveToNextWorkspace) {
|
||||
Action::MoveToPreviousOutput
|
||||
} else {
|
||||
Action::SendToPreviousOutput
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
if matches!(x, Action::MoveToPreviousWorkspace) {
|
||||
Action::MoveToOutput(inferred)
|
||||
} else {
|
||||
Action::SendToOutput(inferred)
|
||||
},
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
x @ Action::MoveToLastWorkspace | x @ Action::SendToLastWorkspace => {
|
||||
|
|
@ -1360,6 +1375,39 @@ impl State {
|
|||
None,
|
||||
);
|
||||
}
|
||||
Action::SwitchOutput(direction) => {
|
||||
let current_output = seat.active_output();
|
||||
let next_output = self
|
||||
.common
|
||||
.shell
|
||||
.next_output(¤t_output, direction)
|
||||
.cloned();
|
||||
|
||||
if let Some(next_output) = next_output {
|
||||
let idx = self.common.shell.workspaces.active_num(&next_output).1;
|
||||
match self.common.shell.activate(&next_output, idx) {
|
||||
Ok(Some(new_pos)) => {
|
||||
seat.set_active_output(&next_output);
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
seat.set_active_output(&next_output);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::NextOutput => {
|
||||
let current_output = seat.active_output();
|
||||
let next_output = self
|
||||
|
|
@ -1431,6 +1479,45 @@ impl State {
|
|||
}
|
||||
}
|
||||
}
|
||||
action @ Action::MoveToOutput(_) | action @ Action::SendToOutput(_) => {
|
||||
let is_move_action = matches!(action, Action::MoveToOutput(_));
|
||||
let direction = match action {
|
||||
Action::MoveToOutput(dir) => dir,
|
||||
Action::SendToOutput(dir) => dir,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let current_output = seat.active_output();
|
||||
let next_output = self
|
||||
.common
|
||||
.shell
|
||||
.next_output(¤t_output, direction)
|
||||
.cloned();
|
||||
|
||||
if let Some(next_output) = next_output {
|
||||
if let Ok(Some(new_pos)) = Shell::move_current_window(
|
||||
self,
|
||||
seat,
|
||||
¤t_output,
|
||||
(&next_output, None),
|
||||
is_move_action,
|
||||
Some(direction),
|
||||
) {
|
||||
if let Some(ptr) = seat.get_pointer() {
|
||||
ptr.motion(
|
||||
self,
|
||||
None,
|
||||
&MotionEvent {
|
||||
location: new_pos.to_f64().as_logical(),
|
||||
serial,
|
||||
time,
|
||||
},
|
||||
);
|
||||
ptr.frame(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
x @ Action::MoveToNextOutput | x @ Action::SendToNextOutput => {
|
||||
let current_output = seat.active_output();
|
||||
let next_output = self
|
||||
|
|
@ -1537,25 +1624,31 @@ impl State {
|
|||
direction,
|
||||
),
|
||||
(FocusDirection::Left, WorkspaceLayout::Vertical)
|
||||
| (FocusDirection::Up, WorkspaceLayout::Horizontal) => self
|
||||
.handle_action(
|
||||
Action::PreviousOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
),
|
||||
| (FocusDirection::Up, WorkspaceLayout::Horizontal) => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
}
|
||||
}
|
||||
(FocusDirection::Right, WorkspaceLayout::Vertical)
|
||||
| (FocusDirection::Down, WorkspaceLayout::Horizontal) => self
|
||||
.handle_action(
|
||||
Action::NextOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
),
|
||||
| (FocusDirection::Down, WorkspaceLayout::Horizontal) => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::SwitchOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
direction,
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1591,23 +1684,31 @@ impl State {
|
|||
Some(direction),
|
||||
),
|
||||
(Direction::Left, WorkspaceLayout::Vertical)
|
||||
| (Direction::Up, WorkspaceLayout::Horizontal) => self.handle_action(
|
||||
Action::MoveToPreviousOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
),
|
||||
| (Direction::Up, WorkspaceLayout::Horizontal) => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::MoveToOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
)
|
||||
}
|
||||
}
|
||||
(Direction::Right, WorkspaceLayout::Vertical)
|
||||
| (Direction::Down, WorkspaceLayout::Horizontal) => self.handle_action(
|
||||
Action::MoveToNextOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
),
|
||||
| (Direction::Down, WorkspaceLayout::Horizontal) => {
|
||||
if let Some(inferred) = pattern.inferred_direction() {
|
||||
self.handle_action(
|
||||
Action::MoveToOutput(inferred),
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
pattern,
|
||||
Some(direction),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MoveResult::ShiftFocus(shift) => {
|
||||
|
|
|
|||
|
|
@ -1146,6 +1146,41 @@ impl Shell {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn next_output(&self, current_output: &Output, direction: Direction) -> Option<&Output> {
|
||||
let current_output_geo = current_output.geometry();
|
||||
self.outputs()
|
||||
.filter(|o| *o != current_output)
|
||||
.filter(|o| {
|
||||
let geo = o.geometry();
|
||||
match direction {
|
||||
Direction::Left | Direction::Right => {
|
||||
!(geo.loc.y + geo.size.h < current_output_geo.loc.y
|
||||
|| geo.loc.y > current_output_geo.loc.y + current_output_geo.size.h)
|
||||
}
|
||||
Direction::Up | Direction::Down => {
|
||||
!(geo.loc.x + geo.size.w < current_output_geo.loc.x
|
||||
|| geo.loc.x > current_output_geo.loc.x + current_output_geo.size.w)
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter_map(|o| {
|
||||
let origin = o.geometry().loc;
|
||||
let res = match direction {
|
||||
Direction::Up => current_output_geo.loc.y - origin.y,
|
||||
Direction::Down => origin.y - current_output_geo.loc.y,
|
||||
Direction::Left => current_output_geo.loc.x - origin.x,
|
||||
Direction::Right => origin.x - current_output_geo.loc.x,
|
||||
};
|
||||
if res > 0 {
|
||||
Some((o, res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.min_by_key(|(_, res)| *res)
|
||||
.map(|(o, _)| o)
|
||||
}
|
||||
|
||||
pub fn global_space(&self) -> Rectangle<i32, Global> {
|
||||
self.outputs()
|
||||
.fold(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue