actions: Fix focus on Output-actions

This commit is contained in:
Victoria Brekenfeld 2024-09-09 17:50:19 +02:00
parent 932c204de4
commit 5006eae60b
3 changed files with 186 additions and 154 deletions

View file

@ -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);
}
_ => {}
} }
} }
} }

View file

@ -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,
);
},
);
}
_ => {}
} }
} }
} }

View file

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