actions: Fix focus on Output-actions
This commit is contained in:
parent
932c204de4
commit
5006eae60b
3 changed files with 186 additions and 154 deletions
|
|
@ -3,8 +3,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Action, PrivateAction},
|
config::{Action, PrivateAction},
|
||||||
shell::{
|
shell::{
|
||||||
layout::tiling::SwapWindowGrab, FocusResult, InvalidWorkspaceIndex, MoveResult, SeatExt,
|
focus::target::KeyboardFocusTarget, layout::tiling::SwapWindowGrab, FocusResult,
|
||||||
Trigger, WorkspaceDelta,
|
InvalidWorkspaceIndex, MoveResult, SeatExt, Trigger, WorkspaceDelta,
|
||||||
},
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -402,11 +402,30 @@ impl State {
|
||||||
WorkspaceDelta::new_shortcut(),
|
WorkspaceDelta::new_shortcut(),
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
);
|
);
|
||||||
match res {
|
seat.set_active_output(&next_output);
|
||||||
Ok(Some(new_pos)) => {
|
|
||||||
std::mem::drop(shell);
|
if let Ok(Some(new_pos)) = res {
|
||||||
seat.set_active_output(&next_output);
|
let new_target = shell
|
||||||
if let Some(ptr) = seat.get_pointer() {
|
.workspaces
|
||||||
|
.active(&next_output)
|
||||||
|
.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(
|
ptr.motion(
|
||||||
self,
|
self,
|
||||||
None,
|
None,
|
||||||
|
|
@ -416,13 +435,9 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ptr.frame(self);
|
|
||||||
}
|
}
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
|
||||||
seat.set_active_output(&next_output);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
} else if propagate {
|
} else if propagate {
|
||||||
std::mem::drop(shell);
|
std::mem::drop(shell);
|
||||||
|
|
@ -474,11 +489,30 @@ impl State {
|
||||||
WorkspaceDelta::new_shortcut(),
|
WorkspaceDelta::new_shortcut(),
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
);
|
);
|
||||||
match res {
|
seat.set_active_output(&next_output);
|
||||||
Ok(Some(new_pos)) => {
|
|
||||||
std::mem::drop(shell);
|
if let Ok(Some(new_pos)) = res {
|
||||||
seat.set_active_output(&next_output);
|
let new_target = shell
|
||||||
if let Some(ptr) = seat.get_pointer() {
|
.workspaces
|
||||||
|
.active(&next_output)
|
||||||
|
.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(
|
ptr.motion(
|
||||||
self,
|
self,
|
||||||
None,
|
None,
|
||||||
|
|
@ -488,13 +522,9 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ptr.frame(self);
|
|
||||||
}
|
}
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
|
||||||
seat.set_active_output(&next_output);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -518,11 +548,30 @@ impl State {
|
||||||
WorkspaceDelta::new_shortcut(),
|
WorkspaceDelta::new_shortcut(),
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
);
|
);
|
||||||
match res {
|
seat.set_active_output(&prev_output);
|
||||||
Ok(Some(new_pos)) => {
|
|
||||||
std::mem::drop(shell);
|
if let Ok(Some(new_pos)) = res {
|
||||||
seat.set_active_output(&prev_output);
|
let new_target = shell
|
||||||
if let Some(ptr) = seat.get_pointer() {
|
.workspaces
|
||||||
|
.active(&prev_output)
|
||||||
|
.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(
|
ptr.motion(
|
||||||
self,
|
self,
|
||||||
None,
|
None,
|
||||||
|
|
@ -532,13 +581,9 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ptr.frame(self);
|
|
||||||
}
|
}
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
|
||||||
seat.set_active_output(&prev_output);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
218
src/input/mod.rs
218
src/input/mod.rs
|
|
@ -603,9 +603,9 @@ impl State {
|
||||||
//If the pointer isn't grabbed, we should check if the focused element should be updated
|
//If the pointer isn't grabbed, we should check if the focused element should be updated
|
||||||
} else if self.common.config.cosmic_conf.focus_follows_cursor {
|
} else if self.common.config.cosmic_conf.focus_follows_cursor {
|
||||||
let shell = self.common.shell.read().unwrap();
|
let shell = self.common.shell.read().unwrap();
|
||||||
let (old_keyboard_target, _) =
|
let old_keyboard_target =
|
||||||
shell.keyboard_target_from_position(original_position, &seat);
|
shell.keyboard_target_from_position(original_position, &seat);
|
||||||
let (new_keyboard_target, _) =
|
let new_keyboard_target =
|
||||||
shell.keyboard_target_from_position(position, &seat);
|
shell.keyboard_target_from_position(position, &seat);
|
||||||
|
|
||||||
if old_keyboard_target != new_keyboard_target
|
if old_keyboard_target != new_keyboard_target
|
||||||
|
|
@ -904,123 +904,115 @@ impl State {
|
||||||
let global_position =
|
let global_position =
|
||||||
seat.get_pointer().unwrap().current_location().as_global();
|
seat.get_pointer().unwrap().current_location().as_global();
|
||||||
let shell = self.common.shell.write().unwrap();
|
let shell = self.common.shell.write().unwrap();
|
||||||
let (under, trigger_move) =
|
let under = shell.keyboard_target_from_position(global_position, &seat);
|
||||||
shell.keyboard_target_from_position(global_position, &seat);
|
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
||||||
if trigger_move {
|
// These cases are handled by the XwaylandKeyboardGrab.
|
||||||
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
if let Some(target) = shell.element_under(global_position, &output) {
|
||||||
// These cases are handled by the XwaylandKeyboardGrab.
|
if seat.get_keyboard().unwrap().modifier_state().logo {
|
||||||
if let Some(target) = shell.element_under(global_position, &output) {
|
if let Some(surface) = target.toplevel().map(Cow::into_owned) {
|
||||||
if seat.get_keyboard().unwrap().modifier_state().logo {
|
let seat_clone = seat.clone();
|
||||||
if let Some(surface) = target.toplevel().map(Cow::into_owned) {
|
let mouse_button = PointerButtonEvent::button(&event);
|
||||||
let seat_clone = seat.clone();
|
|
||||||
let mouse_button = PointerButtonEvent::button(&event);
|
|
||||||
|
|
||||||
let mut supress_button = || {
|
let mut supress_button = || {
|
||||||
// If the logo is held then the pointer event is
|
// If the logo is held then the pointer event is
|
||||||
// aimed at the compositor and shouldn't be passed
|
// aimed at the compositor and shouldn't be passed
|
||||||
// to the application.
|
// to the application.
|
||||||
pass_event = false;
|
pass_event = false;
|
||||||
seat.supressed_buttons().add(button);
|
seat.supressed_buttons().add(button);
|
||||||
};
|
};
|
||||||
|
|
||||||
fn dispatch_grab<G: PointerGrab<State> + 'static>(
|
fn dispatch_grab<G: PointerGrab<State> + 'static>(
|
||||||
grab: Option<(G, smithay::input::pointer::Focus)>,
|
grab: Option<(G, smithay::input::pointer::Focus)>,
|
||||||
seat: Seat<State>,
|
seat: Seat<State>,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
) {
|
) {
|
||||||
if let Some((target, focus)) = grab {
|
if let Some((target, focus)) = grab {
|
||||||
seat.modifiers_shortcut_queue().clear();
|
seat.modifiers_shortcut_queue().clear();
|
||||||
|
|
||||||
seat.get_pointer()
|
seat.get_pointer()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_grab(state, target, serial, focus);
|
.set_grab(state, target, serial, focus);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(mouse_button) = mouse_button {
|
if let Some(mouse_button) = mouse_button {
|
||||||
match mouse_button {
|
match mouse_button {
|
||||||
smithay::backend::input::MouseButton::Left => {
|
smithay::backend::input::MouseButton::Left => {
|
||||||
supress_button();
|
supress_button();
|
||||||
self.common.event_loop_handle.insert_idle(
|
self.common.event_loop_handle.insert_idle(
|
||||||
move |state| {
|
move |state| {
|
||||||
let mut shell =
|
let mut shell =
|
||||||
state.common.shell.write().unwrap();
|
state.common.shell.write().unwrap();
|
||||||
let res = shell.move_request(
|
let res = shell.move_request(
|
||||||
&surface,
|
&surface,
|
||||||
&seat_clone,
|
&seat_clone,
|
||||||
serial,
|
serial,
|
||||||
ReleaseMode::NoMouseButtons,
|
ReleaseMode::NoMouseButtons,
|
||||||
false,
|
false,
|
||||||
&state.common.config,
|
&state.common.config,
|
||||||
&state.common.event_loop_handle,
|
&state.common.event_loop_handle,
|
||||||
&state.common.xdg_activation_state,
|
&state.common.xdg_activation_state,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
drop(shell);
|
drop(shell);
|
||||||
dispatch_grab(
|
dispatch_grab(
|
||||||
res, seat_clone, serial, state,
|
res, seat_clone, serial, state,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
smithay::backend::input::MouseButton::Right => {
|
|
||||||
supress_button();
|
|
||||||
self.common.event_loop_handle.insert_idle(
|
|
||||||
move |state| {
|
|
||||||
let mut shell =
|
|
||||||
state.common.shell.write().unwrap();
|
|
||||||
let Some(target_elem) =
|
|
||||||
shell.element_for_surface(&surface)
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(geom) = shell
|
|
||||||
.space_for(target_elem)
|
|
||||||
.and_then(|f| {
|
|
||||||
f.element_geometry(target_elem)
|
|
||||||
})
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let geom = geom.to_f64();
|
|
||||||
let center =
|
|
||||||
geom.loc + geom.size.downscale(2.0);
|
|
||||||
let offset = center.to_global(&output)
|
|
||||||
- global_position;
|
|
||||||
let edge = match (
|
|
||||||
offset.x > 0.0,
|
|
||||||
offset.y > 0.0,
|
|
||||||
) {
|
|
||||||
(true, true) => {
|
|
||||||
ResizeEdge::TOP_LEFT
|
|
||||||
}
|
|
||||||
(false, true) => {
|
|
||||||
ResizeEdge::TOP_RIGHT
|
|
||||||
}
|
|
||||||
(true, false) => {
|
|
||||||
ResizeEdge::BOTTOM_LEFT
|
|
||||||
}
|
|
||||||
(false, false) => {
|
|
||||||
ResizeEdge::BOTTOM_RIGHT
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let res = shell.resize_request(
|
|
||||||
&surface,
|
|
||||||
&seat_clone,
|
|
||||||
serial,
|
|
||||||
edge,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
drop(shell);
|
|
||||||
dispatch_grab(
|
|
||||||
res, seat_clone, serial, state,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
smithay::backend::input::MouseButton::Right => {
|
||||||
|
supress_button();
|
||||||
|
self.common.event_loop_handle.insert_idle(
|
||||||
|
move |state| {
|
||||||
|
let mut shell =
|
||||||
|
state.common.shell.write().unwrap();
|
||||||
|
let Some(target_elem) =
|
||||||
|
shell.element_for_surface(&surface)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(geom) =
|
||||||
|
shell.space_for(target_elem).and_then(
|
||||||
|
|f| f.element_geometry(target_elem),
|
||||||
|
)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let geom = geom.to_f64();
|
||||||
|
let center =
|
||||||
|
geom.loc + geom.size.downscale(2.0);
|
||||||
|
let offset = center.to_global(&output)
|
||||||
|
- global_position;
|
||||||
|
let edge = match (
|
||||||
|
offset.x > 0.0,
|
||||||
|
offset.y > 0.0,
|
||||||
|
) {
|
||||||
|
(true, true) => ResizeEdge::TOP_LEFT,
|
||||||
|
(false, true) => ResizeEdge::TOP_RIGHT,
|
||||||
|
(true, false) => {
|
||||||
|
ResizeEdge::BOTTOM_LEFT
|
||||||
|
}
|
||||||
|
(false, false) => {
|
||||||
|
ResizeEdge::BOTTOM_RIGHT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let res = shell.resize_request(
|
||||||
|
&surface,
|
||||||
|
&seat_clone,
|
||||||
|
serial,
|
||||||
|
edge,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
drop(shell);
|
||||||
|
dispatch_grab(
|
||||||
|
res, seat_clone, serial, state,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1424,10 +1424,8 @@ impl Shell {
|
||||||
&self,
|
&self,
|
||||||
global_position: Point<f64, Global>,
|
global_position: Point<f64, Global>,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
) -> (Option<KeyboardFocusTarget>, bool) {
|
) -> Option<KeyboardFocusTarget> {
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
// if not done and super key pressed
|
|
||||||
let mut grab_conditions_met = false;
|
|
||||||
let relative_pos = global_position.to_local(&output);
|
let relative_pos = global_position.to_local(&output);
|
||||||
|
|
||||||
let mut under: Option<KeyboardFocusTarget> = None;
|
let mut under: Option<KeyboardFocusTarget> = None;
|
||||||
|
|
@ -1484,11 +1482,7 @@ impl Shell {
|
||||||
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
||||||
// These cases are handled by the XwaylandKeyboardGrab.
|
// These cases are handled by the XwaylandKeyboardGrab.
|
||||||
if let Some(target) = self.element_under(global_position, &output) {
|
if let Some(target) = self.element_under(global_position, &output) {
|
||||||
if !seat.get_keyboard().unwrap().modifier_state().logo {
|
under = Some(target);
|
||||||
under = Some(target);
|
|
||||||
} else {
|
|
||||||
grab_conditions_met = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let layers = layer_map_for_output(&output);
|
let layers = layer_map_for_output(&output);
|
||||||
if let Some(layer) = layers
|
if let Some(layer) = layers
|
||||||
|
|
@ -1512,7 +1506,8 @@ impl Shell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(under, grab_conditions_met)
|
|
||||||
|
under
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Coerce a keyboard focus target into a CosmicMapped element. This is useful when performing window specific
|
/// Coerce a keyboard focus target into a CosmicMapped element. This is useful when performing window specific
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue