diff --git a/src/input/actions.rs b/src/input/actions.rs index a9ab6436..a85cf8a0 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -3,8 +3,8 @@ use crate::{ config::{Action, PrivateAction}, shell::{ - layout::tiling::SwapWindowGrab, FocusResult, InvalidWorkspaceIndex, MoveResult, SeatExt, - Trigger, WorkspaceDelta, + focus::target::KeyboardFocusTarget, layout::tiling::SwapWindowGrab, FocusResult, + InvalidWorkspaceIndex, MoveResult, SeatExt, Trigger, WorkspaceDelta, }, utils::prelude::*, wayland::{ @@ -402,11 +402,30 @@ impl State { WorkspaceDelta::new_shortcut(), &mut self.common.workspace_state.update(), ); - match res { - Ok(Some(new_pos)) => { - std::mem::drop(shell); - seat.set_active_output(&next_output); - if let Some(ptr) = seat.get_pointer() { + seat.set_active_output(&next_output); + + if let Ok(Some(new_pos)) = res { + let new_target = shell + .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( self, None, @@ -416,13 +435,9 @@ impl State { time, }, ); - ptr.frame(self); } + ptr.frame(self); } - Ok(None) => { - seat.set_active_output(&next_output); - } - _ => {} } } else if propagate { std::mem::drop(shell); @@ -474,11 +489,30 @@ impl State { WorkspaceDelta::new_shortcut(), &mut self.common.workspace_state.update(), ); - match res { - Ok(Some(new_pos)) => { - std::mem::drop(shell); - seat.set_active_output(&next_output); - if let Some(ptr) = seat.get_pointer() { + seat.set_active_output(&next_output); + + if let Ok(Some(new_pos)) = res { + let new_target = shell + .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( self, None, @@ -488,13 +522,9 @@ impl State { time, }, ); - ptr.frame(self); } + ptr.frame(self); } - Ok(None) => { - seat.set_active_output(&next_output); - } - _ => {} } } } @@ -518,11 +548,30 @@ impl State { WorkspaceDelta::new_shortcut(), &mut self.common.workspace_state.update(), ); - match res { - Ok(Some(new_pos)) => { - std::mem::drop(shell); - seat.set_active_output(&prev_output); - if let Some(ptr) = seat.get_pointer() { + seat.set_active_output(&prev_output); + + if let Ok(Some(new_pos)) = res { + let new_target = shell + .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( self, None, @@ -532,13 +581,9 @@ impl State { time, }, ); - ptr.frame(self); } + ptr.frame(self); } - Ok(None) => { - seat.set_active_output(&prev_output); - } - _ => {} } } } diff --git a/src/input/mod.rs b/src/input/mod.rs index 796297d0..a031688c 100644 --- a/src/input/mod.rs +++ b/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 } else if self.common.config.cosmic_conf.focus_follows_cursor { let shell = self.common.shell.read().unwrap(); - let (old_keyboard_target, _) = + let old_keyboard_target = shell.keyboard_target_from_position(original_position, &seat); - let (new_keyboard_target, _) = + let new_keyboard_target = shell.keyboard_target_from_position(position, &seat); if old_keyboard_target != new_keyboard_target @@ -904,123 +904,115 @@ impl State { let global_position = seat.get_pointer().unwrap().current_location().as_global(); let shell = self.common.shell.write().unwrap(); - let (under, trigger_move) = - shell.keyboard_target_from_position(global_position, &seat); - if trigger_move { - // Don't check override redirect windows, because we don't set keyboard focus to them explicitly. - // These cases are handled by the XwaylandKeyboardGrab. - if let Some(target) = shell.element_under(global_position, &output) { - if seat.get_keyboard().unwrap().modifier_state().logo { - if let Some(surface) = target.toplevel().map(Cow::into_owned) { - let seat_clone = seat.clone(); - let mouse_button = PointerButtonEvent::button(&event); + let under = shell.keyboard_target_from_position(global_position, &seat); + // Don't check override redirect windows, because we don't set keyboard focus to them explicitly. + // These cases are handled by the XwaylandKeyboardGrab. + if let Some(target) = shell.element_under(global_position, &output) { + if seat.get_keyboard().unwrap().modifier_state().logo { + if let Some(surface) = target.toplevel().map(Cow::into_owned) { + let seat_clone = seat.clone(); + let mouse_button = PointerButtonEvent::button(&event); - let mut supress_button = || { - // If the logo is held then the pointer event is - // aimed at the compositor and shouldn't be passed - // to the application. - pass_event = false; - seat.supressed_buttons().add(button); - }; + let mut supress_button = || { + // If the logo is held then the pointer event is + // aimed at the compositor and shouldn't be passed + // to the application. + pass_event = false; + seat.supressed_buttons().add(button); + }; - fn dispatch_grab + 'static>( - grab: Option<(G, smithay::input::pointer::Focus)>, - seat: Seat, - serial: Serial, - state: &mut State, - ) { - if let Some((target, focus)) = grab { - seat.modifiers_shortcut_queue().clear(); + fn dispatch_grab + 'static>( + grab: Option<(G, smithay::input::pointer::Focus)>, + seat: Seat, + serial: Serial, + state: &mut State, + ) { + if let Some((target, focus)) = grab { + seat.modifiers_shortcut_queue().clear(); - seat.get_pointer() - .unwrap() - .set_grab(state, target, serial, focus); - } + seat.get_pointer() + .unwrap() + .set_grab(state, target, serial, focus); } + } - if let Some(mouse_button) = mouse_button { - match mouse_button { - smithay::backend::input::MouseButton::Left => { - supress_button(); - self.common.event_loop_handle.insert_idle( - move |state| { - let mut shell = - state.common.shell.write().unwrap(); - let res = shell.move_request( - &surface, - &seat_clone, - serial, - ReleaseMode::NoMouseButtons, - false, - &state.common.config, - &state.common.event_loop_handle, - &state.common.xdg_activation_state, - 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, - ); - }, - ); - } - _ => {} + if let Some(mouse_button) = mouse_button { + match mouse_button { + smithay::backend::input::MouseButton::Left => { + supress_button(); + self.common.event_loop_handle.insert_idle( + move |state| { + let mut shell = + state.common.shell.write().unwrap(); + let res = shell.move_request( + &surface, + &seat_clone, + serial, + ReleaseMode::NoMouseButtons, + false, + &state.common.config, + &state.common.event_loop_handle, + &state.common.xdg_activation_state, + 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, + ); + }, + ); + } + _ => {} } } } diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 5a91bf3f..c28b34b2 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1424,10 +1424,8 @@ impl Shell { &self, global_position: Point, seat: &Seat, - ) -> (Option, bool) { + ) -> Option { 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 mut under: Option = None; @@ -1484,11 +1482,7 @@ impl Shell { // Don't check override redirect windows, because we don't set keyboard focus to them explicitly. // These cases are handled by the XwaylandKeyboardGrab. if let Some(target) = self.element_under(global_position, &output) { - if !seat.get_keyboard().unwrap().modifier_state().logo { - under = Some(target); - } else { - grab_conditions_met = true; - } + under = Some(target); } else { let layers = layer_map_for_output(&output); 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