diff --git a/src/input/mod.rs b/src/input/mod.rs index 9441ae264..debf453a3 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -5,7 +5,10 @@ use crate::{ config::{xkb_config_to_wl, Action, Config, KeyModifiers, KeyPattern}, input::gestures::{GestureState, SwipeAction}, shell::{ - focus::{target::PointerFocusTarget, FocusDirection}, + focus::{ + target::{KeyboardFocusTarget, PointerFocusTarget}, + FocusDirection, + }, grabs::{ResizeEdge, SeatMenuGrabState, SeatMoveGrabState}, layout::{ floating::ResizeGrabMarker, @@ -33,7 +36,10 @@ use smithay::{ TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent, }, - desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType}, + desktop::{ + layer_map_for_output, space::SpaceElement, utils::under_from_surface_tree, + WindowSurfaceType, + }, input::{ keyboard::{FilterResult, KeysymHandle, LedState, XkbConfig}, pointer::{ @@ -724,11 +730,15 @@ impl State { ptr.frame(self); return; } - if let PointerFocusTarget::Element(element) = surface { - //if !element.is_in_input_region(&(position.to_i32_round() - *surface_loc).to_f64()) { - if !element.is_in_input_region( - &(position.as_logical() - surface_loc.to_f64()), - ) { + if let PointerFocusTarget::WlSurface(surface) = surface { + if under_from_surface_tree( + surface, + position.as_logical() - surface_loc.to_f64(), + (0, 0), + WindowSurfaceType::ALL, + ) + .is_some() + { ptr.frame(self); return; } @@ -886,7 +896,7 @@ impl State { let pos = seat.get_pointer().unwrap().current_location().as_global(); let relative_pos = pos.to_local(&output); - let mut under = None; + let mut under: Option = None; if let Some(session_lock) = self.common.shell.session_lock.as_ref() { under = session_lock @@ -947,7 +957,7 @@ impl State { if !done { // 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, _)) = + if let Some(target) = self.common.shell.element_under(pos, &output) { under = Some(target); @@ -982,12 +992,7 @@ impl State { } } } - Common::set_focus( - self, - under.and_then(|target| target.try_into().ok()).as_ref(), - &seat, - Some(serial), - ); + Common::set_focus(self, under.as_ref(), &seat, Some(serial)); } } else { if let OverviewMode::Started(Trigger::Pointer(action_button), _) = @@ -2270,7 +2275,7 @@ impl State { if let Some(session_lock) = session_lock { return session_lock.surfaces.get(output).map(|surface| { ( - PointerFocusTarget::LockSurface(surface.clone()), + PointerFocusTarget::WlSurface(surface.wl_surface().clone()), output_geo.loc, ) }); @@ -2280,24 +2285,33 @@ impl State { let layers = layer_map_for_output(output); if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - return Some((layer.clone().into(), output_geo.loc + layer_loc.as_global())); + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { + return Some(( + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), + )); } } - if let Some(or) = shell.override_redirect_windows.iter().find(|or| { - or.is_in_input_region( - &(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()), - ) - }) { - return Some((or.clone().into(), X11Surface::geometry(or).loc.as_global())); + if let Some((surface, geo)) = shell + .override_redirect_windows + .iter() + .find(|or| { + or.is_in_input_region( + &(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()), + ) + }) + .and_then(|or| { + or.wl_surface() + .map(|surface| (surface, X11Surface::geometry(or).loc.as_global())) + }) + { + return Some((surface.into(), geo)); } - Some((window.clone().into(), output_geo.loc)) + PointerFocusTarget::under_surface(window, relative_pos.as_logical()) + .map(|(target, surface_loc)| (target, output_geo.loc + surface_loc.as_global())) } else { { let layers = layer_map_for_output(output); @@ -2306,28 +2320,33 @@ impl State { .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos.as_logical())) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { return Some(( - layer.clone().into(), - output_geo.loc + layer_loc.as_global(), + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), )); } } } - if let Some(or) = shell.override_redirect_windows.iter().find(|or| { - or.is_in_input_region( - &(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()), - ) - }) { - return Some((or.clone().into(), X11Surface::geometry(or).loc.as_global())); + if let Some((surface, geo)) = shell + .override_redirect_windows + .iter() + .find(|or| { + or.is_in_input_region( + &(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()), + ) + }) + .and_then(|or| { + or.wl_surface() + .map(|surface| (surface, X11Surface::geometry(or).loc.as_global())) + }) + { + return Some((surface.into(), geo)); } - if let Some((target, loc)) = shell.element_under(global_pos, output) { + if let Some((target, loc)) = shell.surface_under(global_pos, output) { return Some((target, loc)); } { @@ -2337,16 +2356,13 @@ impl State { .or_else(|| layers.layer_under(WlrLayer::Background, relative_pos.as_logical())) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { return Some(( - layer.clone().into(), - output_geo.loc + layer_loc.as_global(), + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), )); } } diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index b78f83c45..356c9bfc5 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -25,12 +25,6 @@ use smithay::{ desktop::{space::SpaceElement, PopupManager, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, - PointerTarget, RelativeMotionEvent, - }, Seat, }, output::Output, @@ -72,7 +66,7 @@ use smithay::backend::renderer::{element::texture::TextureRenderElement, gles::G use tracing::debug; use super::{ - focus::FocusDirection, + focus::{target::PointerFocusTarget, FocusDirection}, layout::{ floating::{ResizeState, TiledCorners}, tiling::NodeDesc, @@ -258,6 +252,20 @@ impl CosmicMapped { }) } + /// Give the pointer target under a relative offset into this element. + /// + /// Returns Target + Offset relative to the target + pub fn focus_under( + &self, + relative_pos: Point, + ) -> Option<(PointerFocusTarget, Point)> { + match &self.element { + CosmicMappedInternal::Stack(stack) => stack.focus_under(relative_pos), + CosmicMappedInternal::Window(window) => window.focus_under(relative_pos), + _ => unreachable!(), + } + } + pub fn handle_move(&self, direction: Direction) -> MoveResult { if let CosmicMappedInternal::Stack(stack) = &self.element { stack.handle_move(direction) @@ -918,188 +926,6 @@ impl KeyboardTarget for CosmicMapped { } } -impl PointerTarget for CosmicMapped { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - self.last_cursor_position - .lock() - .unwrap() - .insert(seat.id(), event.location); - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::enter(s, seat, data, event), - CosmicMappedInternal::Window(w) => PointerTarget::enter(w, seat, data, event), - _ => {} - } - } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - self.last_cursor_position - .lock() - .unwrap() - .insert(seat.id(), event.location); - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::motion(s, seat, data, event), - CosmicMappedInternal::Window(w) => PointerTarget::motion(w, seat, data, event), - _ => {} - } - } - fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::relative_motion(s, seat, data, event), - CosmicMappedInternal::Window(w) => PointerTarget::relative_motion(w, seat, data, event), - _ => {} - } - } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::button(s, seat, data, event), - CosmicMappedInternal::Window(w) => PointerTarget::button(w, seat, data, event), - _ => {} - } - } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::axis(s, seat, data, frame), - CosmicMappedInternal::Window(w) => PointerTarget::axis(w, seat, data, frame), - _ => {} - } - } - fn frame(&self, seat: &Seat, data: &mut State) { - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::frame(s, seat, data), - CosmicMappedInternal::Window(w) => PointerTarget::frame(w, seat, data), - _ => {} - } - } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { - self.last_cursor_position.lock().unwrap().remove(&seat.id()); - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::leave(s, seat, data, serial, time), - CosmicMappedInternal::Window(w) => PointerTarget::leave(w, seat, data, serial, time), - _ => {} - } - } - fn gesture_swipe_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeBeginEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_swipe_begin(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_swipe_begin(w, seat, data, event) - } - _ => {} - } - } - fn gesture_swipe_update( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeUpdateEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_swipe_update(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) - } - _ => {} - } - } - fn gesture_swipe_end( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeEndEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_swipe_end(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_swipe_end(w, seat, data, event) - } - _ => {} - } - } - fn gesture_pinch_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchBeginEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_pinch_begin(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_pinch_begin(w, seat, data, event) - } - _ => {} - } - } - fn gesture_pinch_update( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchUpdateEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_pinch_update(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_pinch_update(w, seat, data, event) - } - _ => {} - } - } - fn gesture_pinch_end( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchEndEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_pinch_end(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) - } - _ => {} - } - } - fn gesture_hold_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GestureHoldBeginEvent, - ) { - match &self.element { - CosmicMappedInternal::Stack(s) => { - PointerTarget::gesture_hold_begin(s, seat, data, event) - } - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) - } - _ => {} - } - } - fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { - match &self.element { - CosmicMappedInternal::Stack(s) => PointerTarget::gesture_hold_end(s, seat, data, event), - CosmicMappedInternal::Window(w) => { - PointerTarget::gesture_hold_end(w, seat, data, event) - } - _ => {} - } - } -} - impl WaylandFocus for CosmicMapped { fn wl_surface(&self) -> Option { match &self.element { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 6e1c3ee9f..1456f322a 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -2,7 +2,7 @@ use super::{surface::RESIZE_BORDER, CosmicSurface}; use crate::{ backend::render::cursor::{CursorShape, CursorState}, shell::{ - focus::FocusDirection, + focus::{target::PointerFocusTarget, FocusDirection}, grabs::{ReleaseMode, ResizeEdge}, layout::tiling::NodeDesc, Direction, Shell, @@ -35,7 +35,7 @@ use smithay::{ ImportAll, ImportMem, Renderer, }, }, - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -123,7 +123,6 @@ pub const TAB_HEIGHT: i32 = 24; pub enum Focus { None, Header, - Window, ResizeTop, ResizeLeft, ResizeRight, @@ -422,6 +421,51 @@ impl CosmicStack { }) } + pub fn focus_under( + &self, + mut relative_pos: Point, + ) -> Option<(PointerFocusTarget, Point)> { + self.0.with_program(|p| { + let mut stack_ui = None; + let geo = p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry(); + + let point_i32 = relative_pos.to_i32_round::(); + if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) + || (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0) + || (point_i32.x - geo.loc.x >= geo.size.w + && point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER) + || (point_i32.y - geo.loc.y >= geo.size.h + && point_i32.y - geo.loc.y < geo.size.h + TAB_HEIGHT + RESIZE_BORDER) + { + stack_ui = Some(( + PointerFocusTarget::StackUI(self.clone()), + Point::from((0, 0)), + )); + } + + if point_i32.y - geo.loc.y < TAB_HEIGHT { + stack_ui = Some(( + PointerFocusTarget::StackUI(self.clone()), + Point::from((0, 0)), + )); + } + + relative_pos.y -= TAB_HEIGHT as f64; + + let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + active_window + .0 + .surface_under(relative_pos, WindowSurfaceType::ALL) + .map(|(surface, surface_offset)| { + ( + PointerFocusTarget::WlSurface(surface), + surface_offset + Point::from((0, TAB_HEIGHT)), + ) + }) + .or(stack_ui) + }) + } + pub fn offset(&self) -> Point { Point::from((0, TAB_HEIGHT)) } @@ -494,19 +538,23 @@ impl CosmicStack { if previous != active { let windows = p.windows.lock().unwrap(); if let Some(previous) = windows.get(previous) { + /* if let Some(sessions) = previous.user_data().get::() { for session in &*sessions.0.borrow() { session.cursor_leave(seat, InputType::Pointer) } } + */ PointerTarget::leave(previous, seat, data, serial, time); } + /* if let Some(sessions) = windows[active].user_data().get::() { for session in &*sessions.0.borrow() { session.cursor_enter(seat, InputType::Pointer) } } + */ PointerTarget::enter( &windows[active], seat, @@ -930,33 +978,7 @@ impl SpaceElement for CosmicStack { }) } fn is_in_input_region(&self, point: &Point) -> bool { - let mut point = *point; - let geo = self.0.with_program(|p| { - p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() - }); - - let point_i32 = point.to_i32_round::(); - if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) - || (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0) - || (point_i32.x - geo.loc.x >= geo.size.w - && point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER) - || (point_i32.y - geo.loc.y >= geo.size.h - && point_i32.y - geo.loc.y < geo.size.h + TAB_HEIGHT + RESIZE_BORDER) - { - return true; - } - - if (point_i32.y - geo.loc.y) < TAB_HEIGHT { - return true; - } - - point.y -= TAB_HEIGHT as f64; - self.0.with_program(|p| { - SpaceElement::is_in_input_region( - &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)], - &point, - ) - }) + self.focus_under(*point).is_some() } fn set_activate(&self, activated: bool) { SpaceElement::set_activate(&self.0, activated); @@ -1119,17 +1141,19 @@ impl KeyboardTarget for CosmicStack { impl PointerTarget for CosmicStack { fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); - if self.0.with_program(|p| { + self.0.with_program(|p| { let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + /* if let Some(sessions) = active_window.user_data().get::() { for session in &*sessions.0.borrow() { session.cursor_enter(seat, InputType::Pointer) } } + */ let geo = active_window.geometry(); let loc = event.location.to_i32_round::(); - let (old_focus, shape) = if loc.y - geo.loc.y < 0 && loc.x - geo.loc.x < 0 { + let (_old_focus, shape) = if loc.y - geo.loc.y < 0 && loc.x - geo.loc.x < 0 { ( p.swap_focus(Focus::ResizeTopLeft), CursorShape::NorthWestResize, @@ -1162,21 +1186,9 @@ impl PointerTarget for CosmicStack { } else if loc.y - geo.loc.y < TAB_HEIGHT { (p.swap_focus(Focus::Header), CursorShape::Default) } else { - p.swap_focus(Focus::Window); - - event.location.y -= TAB_HEIGHT as f64; - *p.last_location.lock().unwrap() = Some((event.location, event.serial, event.time)); - let active = p.active.load(Ordering::SeqCst); - p.previous_pointer.store(active, Ordering::SeqCst); - - PointerTarget::enter(active_window, seat, data, &event); - return false; + return; }; - if old_focus == Focus::Window { - PointerTarget::leave(active_window, seat, data, event.serial, event.time); - } - let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(shape); let cursor_status = seat @@ -1184,16 +1196,15 @@ impl PointerTarget for CosmicStack { .get::>() .unwrap(); *cursor_status.borrow_mut() = CursorImageStatus::default_named(); - shape == CursorShape::Default - }) { - event.location -= self.0.with_program(|p| { - p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)] - .geometry() - .loc - .to_f64() - }); - PointerTarget::enter(&self.0, seat, data, &event) - } + }); + + event.location -= self.0.with_program(|p| { + p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)] + .geometry() + .loc + .to_f64() + }); + PointerTarget::enter(&self.0, seat, data, &event) } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { @@ -1201,8 +1212,9 @@ impl PointerTarget for CosmicStack { let active = self.pointer_leave_if_previous(seat, data, event.serial, event.time, event.location); - let (previous, next) = self.0.with_program(|p| { + self.0.with_program(|p| { let active_window = &p.windows.lock().unwrap()[active]; + /* if let Some(sessions) = active_window.user_data().get::() { for session in &*sessions.0.borrow() { let buffer_loc = (event.location.x, event.location.y); // we always screencast windows at 1x1 scale @@ -1213,6 +1225,7 @@ impl PointerTarget for CosmicStack { } } } + */ let geo = active_window.geometry(); let loc = event.location.to_i32_round::(); @@ -1237,23 +1250,10 @@ impl PointerTarget for CosmicStack { } else if (loc.y - geo.loc.y) < TAB_HEIGHT { (Focus::Header, CursorShape::Default) } else { - event.location.y -= TAB_HEIGHT as f64; - *p.last_location.lock().unwrap() = Some((event.location, event.serial, event.time)); - - let previous = p.swap_focus(Focus::Window); - if previous != Focus::Window { - PointerTarget::enter(active_window, seat, data, &event); - } else { - PointerTarget::motion(active_window, seat, data, &event); - } - - return (previous, Focus::Window); + return; }; - let previous = p.swap_focus(next); - if previous == Focus::Window { - PointerTarget::leave(active_window, seat, data, event.serial, event.time); - } + let _previous = p.swap_focus(next); let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(shape); @@ -1262,8 +1262,6 @@ impl PointerTarget for CosmicStack { .get::>() .unwrap(); *cursor_status.borrow_mut() = CursorImageStatus::default_named(); - - (previous, next) }); let active_window_geo = self @@ -1271,80 +1269,46 @@ impl PointerTarget for CosmicStack { .with_program(|p| p.windows.lock().unwrap()[active].geometry()); event.location -= active_window_geo.loc.to_f64(); - match (previous, next) { - (Focus::Header, Focus::Header) => { - PointerTarget::motion(&self.0, seat, data, &event); - if event.location.y < 0.0 - || event.location.x < 64.0 - || event.location.x > (active_window_geo.size.w as f64 - 64.0) - { - if let Some(dragged_out) = self - .0 - .with_program(|p| p.potential_drag.lock().unwrap().take()) - { - if let Some(surface) = self - .0 - .with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned()) - { - let seat = seat.clone(); - surface.try_force_undecorated(false); - surface.send_configure(); - if let Some(surface) = surface.wl_surface() { - let _ = data.common.event_loop_handle.insert_idle(move |state| { - Shell::move_request( - state, - &surface, - &seat, - None, - ReleaseMode::NoMouseButtons, - true, - ) - }); - } - } - } - } - } - (_, Focus::Header) => PointerTarget::enter(&self.0, seat, data, &event), - (Focus::Header, _) => { - PointerTarget::leave(&self.0, seat, data, event.serial, event.time); - if let Some(dragged_out) = self + PointerTarget::motion(&self.0, seat, data, &event); + if event.location.y < 0.0 + || event.location.y > TAB_HEIGHT as f64 + || event.location.x < 64.0 + || event.location.x > (active_window_geo.size.w as f64 - 64.0) + { + if let Some(dragged_out) = self + .0 + .with_program(|p| p.potential_drag.lock().unwrap().take()) + { + if let Some(surface) = self .0 - .with_program(|p| p.potential_drag.lock().unwrap().take()) + .with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned()) { - if let Some(surface) = self - .0 - .with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned()) - { - let seat = seat.clone(); - surface.try_force_undecorated(false); - surface.send_configure(); - if let Some(surface) = surface.wl_surface() { - let _ = data.common.event_loop_handle.insert_idle(move |state| { - Shell::move_request( - state, - &surface, - &seat, - None, - ReleaseMode::NoMouseButtons, - true, - ) - }); - } + let seat = seat.clone(); + surface.try_force_undecorated(false); + surface.send_configure(); + if let Some(surface) = surface.wl_surface() { + let _ = data.common.event_loop_handle.insert_idle(move |state| { + Shell::move_request( + state, + &surface, + &seat, + None, + ReleaseMode::NoMouseButtons, + true, + ) + }); } } } - _ => {} } } - fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.relative_motion(seat, data, event) - } - }) + fn relative_motion( + &self, + _seat: &Seat, + _data: &mut State, + _event: &RelativeMotionEvent, + ) { } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { @@ -1362,27 +1326,6 @@ impl PointerTarget for CosmicStack { }); PointerTarget::button(&self.0, seat, data, event) } - Focus::Window => { - if self.0.with_program(|p| { - PointerTarget::button( - &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)], - seat, - data, - event, - ); - if p.group_focused.swap(false, Ordering::SeqCst) { - p.windows.lock().unwrap().iter().for_each(|w| { - SpaceElement::set_activate(w, true); - w.send_configure(); - }); - true - } else { - false - } - }) { - self.0.force_redraw(); - } - } Focus::None => {} x => { let serial = event.serial; @@ -1408,7 +1351,7 @@ impl PointerTarget for CosmicStack { Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT, Focus::ResizeLeft => ResizeEdge::LEFT, Focus::ResizeRight => ResizeEdge::RIGHT, - Focus::Header | Focus::Window | Focus::None => unreachable!(), + Focus::Header | Focus::None => unreachable!(), }, ) }); @@ -1426,14 +1369,6 @@ impl PointerTarget for CosmicStack { match self.0.with_program(|p| p.current_focus()) { Focus::Header => PointerTarget::axis(&self.0, seat, data, frame), - Focus::Window => self.0.with_program(|p| { - PointerTarget::axis( - &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)], - seat, - data, - frame, - ) - }), _ => {} } } @@ -1448,13 +1383,6 @@ impl PointerTarget for CosmicStack { match self.0.with_program(|p| p.current_focus()) { Focus::Header => PointerTarget::frame(&self.0, seat, data), - Focus::Window => self.0.with_program(|p| { - PointerTarget::frame( - &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)], - seat, - data, - ) - }), _ => {} } } @@ -1467,7 +1395,8 @@ impl PointerTarget for CosmicStack { self.pointer_leave_if_previous(seat, data, serial, time, location); } - let previous = self.0.with_program(|p| { + self.0.with_program(|p| { + /* if let Some(sessions) = p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)] .user_data() .get::() @@ -1476,132 +1405,104 @@ impl PointerTarget for CosmicStack { session.cursor_leave(seat, InputType::Pointer) } } + */ let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(CursorShape::Default); - p.swap_focus(Focus::None) + let _previous = p.swap_focus(Focus::None); }); - match previous { - Focus::Header => PointerTarget::leave(&self.0, seat, data, serial, time), - Focus::Window => self.0.with_program(|p| { - PointerTarget::leave( - &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)], - seat, - data, - serial, - time, - ) - }), - _ => {} + PointerTarget::leave(&self.0, seat, data, serial, time); + + if let Some(dragged_out) = self + .0 + .with_program(|p| p.potential_drag.lock().unwrap().take()) + { + if let Some(surface) = self + .0 + .with_program(|p| p.windows.lock().unwrap().get(dragged_out).cloned()) + { + let seat = seat.clone(); + surface.try_force_undecorated(false); + surface.send_configure(); + if let Some(surface) = surface.wl_surface() { + let _ = data.common.event_loop_handle.insert_idle(move |state| { + Shell::move_request( + state, + &surface, + &seat, + None, + ReleaseMode::NoMouseButtons, + true, + ) + }); + } + } } } fn gesture_swipe_begin( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeBeginEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_swipe_begin(seat, data, event) - } - }) } fn gesture_swipe_update( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeUpdateEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeUpdateEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_swipe_update(seat, data, event) - } - }) } fn gesture_swipe_end( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeEndEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeEndEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_swipe_end(seat, data, event) - } - }) } fn gesture_pinch_begin( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchBeginEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_pinch_begin(seat, data, event) - } - }) } fn gesture_pinch_update( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchUpdateEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchUpdateEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_pinch_update(seat, data, event) - } - }) } fn gesture_pinch_end( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchEndEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchEndEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_pinch_end(seat, data, event) - } - }) } fn gesture_hold_begin( &self, - seat: &Seat, - data: &mut State, - event: &GestureHoldBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureHoldBeginEvent, ) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_hold_begin(seat, data, event) - } - }) } - fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { - self.0.with_program(|p| { - if p.current_focus() == Focus::Window { - let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; - window.gesture_hold_end(seat, data, event) - } - }) + fn gesture_hold_end( + &self, + _seat: &Seat, + _data: &mut State, + _event: &GestureHoldEndEvent, + ) { } } diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 6961db8f1..3593d2b6c 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -1,6 +1,7 @@ use crate::{ backend::render::cursor::{CursorShape, CursorState}, shell::{ + focus::target::PointerFocusTarget, grabs::{ReleaseMode, ResizeEdge}, Shell, }, @@ -25,7 +26,7 @@ use smithay::{ ImportAll, ImportMem, Renderer, }, }, - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -97,7 +98,6 @@ impl fmt::Debug for CosmicWindowInternal { pub enum Focus { None, Header, - Window, ResizeTop, ResizeLeft, ResizeRight, @@ -181,6 +181,54 @@ impl CosmicWindow { self.0.with_program(|p| p.window.clone()) } + pub fn focus_under( + &self, + mut relative_pos: Point, + ) -> Option<(PointerFocusTarget, Point)> { + self.0.with_program(|p| { + let mut offset = Point::from((0, 0)); + let mut window_ui = None; + if p.has_ssd(false) { + let geo = p.window.geometry(); + + let point_i32 = relative_pos.to_i32_round::(); + if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) + || (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0) + || (point_i32.x - geo.loc.x >= geo.size.w + && point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER) + || (point_i32.y - geo.loc.y >= geo.size.h + && point_i32.y - geo.loc.y < geo.size.h + SSD_HEIGHT + RESIZE_BORDER) + { + window_ui = Some(( + PointerFocusTarget::WindowUI(self.clone()), + Point::from((0, 0)), + )); + } + + if point_i32.y - geo.loc.y < SSD_HEIGHT { + window_ui = Some(( + PointerFocusTarget::WindowUI(self.clone()), + Point::from((0, 0)), + )); + } + + relative_pos.y -= SSD_HEIGHT as f64; + offset.y += SSD_HEIGHT; + } + + p.window + .0 + .surface_under(relative_pos, WindowSurfaceType::ALL) + .map(|(surface, surface_offset)| { + ( + PointerFocusTarget::WlSurface(surface), + offset + surface_offset, + ) + }) + .or(window_ui) + }) + } + pub fn contains_surface(&self, window: &CosmicSurface) -> bool { self.0.with_program(|p| &p.window == window) } @@ -452,30 +500,7 @@ impl SpaceElement for CosmicWindow { }) } fn is_in_input_region(&self, point: &Point) -> bool { - let mut point = *point; - self.0.with_program(|p| { - if p.has_ssd(false) { - let geo = p.window.geometry(); - - let point_i32 = point.to_i32_round::(); - if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0) - || (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0) - || (point_i32.x - geo.loc.x >= geo.size.w - && point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER) - || (point_i32.y - geo.loc.y >= geo.size.h - && point_i32.y - geo.loc.y < geo.size.h + SSD_HEIGHT + RESIZE_BORDER) - { - return true; - } - - if point_i32.y - geo.loc.y < SSD_HEIGHT { - return true; - } - - point.y -= SSD_HEIGHT as f64; - } - SpaceElement::is_in_input_region(&p.window, &point) - }) + self.focus_under(*point).is_some() } fn set_activate(&self, activated: bool) { if self @@ -575,12 +600,14 @@ impl KeyboardTarget for CosmicWindow { impl PointerTarget for CosmicWindow { fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); - if self.0.with_program(|p| { + self.0.with_program(|p| { + /* if let Some(sessions) = p.window.user_data().get::() { for session in &*sessions.0.borrow() { session.cursor_enter(seat, InputType::Pointer) } } + */ if p.has_ssd(false) { let geo = p.window.geometry(); @@ -618,13 +645,7 @@ impl PointerTarget for CosmicWindow { } else if loc.y - geo.loc.y < SSD_HEIGHT { (p.swap_focus(Focus::Header), CursorShape::Default) } else { - let focus = p.swap_focus(Focus::Window); - assert_eq!(focus, Focus::None); - - let mut event = event.clone(); - event.location.y -= SSD_HEIGHT as f64; - PointerTarget::enter(&p.window, seat, data, &event); - return false; + return; }; assert_eq!(old_focus, Focus::None); @@ -636,21 +657,17 @@ impl PointerTarget for CosmicWindow { .get::>() .unwrap(); *cursor_status.borrow_mut() = CursorImageStatus::default_named(); - shape == CursorShape::Default - } else { - p.swap_focus(Focus::Window); - PointerTarget::enter(&p.window, seat, data, &event); - false } - }) { - event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); - PointerTarget::enter(&self.0, seat, data, &event) - } + }); + + event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); + PointerTarget::enter(&self.0, seat, data, &event) } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); - if let Some((previous, next)) = self.0.with_program(|p| { + self.0.with_program(|p| { + /* if let Some(sessions) = p.window.user_data().get::() { for session in &*sessions.0.borrow() { let buffer_loc = (event.location.x, event.location.y); // we always screencast windows at 1x1 scale @@ -661,6 +678,7 @@ impl PointerTarget for CosmicWindow { } } } + */ if p.has_ssd(false) { let geo = p.window.geometry(); @@ -684,22 +702,10 @@ impl PointerTarget for CosmicWindow { } else if loc.y < SSD_HEIGHT { (Focus::Header, CursorShape::Default) } else { - event.location.y -= SSD_HEIGHT as f64; - - let previous = p.swap_focus(Focus::Window); - if previous != Focus::Window { - PointerTarget::enter(&p.window, seat, data, &event); - } else { - PointerTarget::motion(&p.window, seat, data, &event); - } - - return Some((previous, Focus::Window)); + return; }; - let previous = p.swap_focus(next); - if previous == Focus::Window { - PointerTarget::leave(&p.window, seat, data, event.serial, event.time); - } + let _previous = p.swap_focus(next); let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(shape); @@ -708,34 +714,19 @@ impl PointerTarget for CosmicWindow { .get::>() .unwrap(); *cursor_status.borrow_mut() = CursorImageStatus::default_named(); - - Some((previous, next)) - } else { - p.swap_focus(Focus::Window); - PointerTarget::motion(&p.window, seat, data, &event); - None } - }) { - event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); - match (previous, next) { - (Focus::Header, Focus::Header) => { - PointerTarget::motion(&self.0, seat, data, &event) - } - (_, Focus::Header) => PointerTarget::enter(&self.0, seat, data, &event), - (Focus::Header, _) => { - PointerTarget::leave(&self.0, seat, data, event.serial, event.time) - } - _ => {} - }; - } + }); + + event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); + PointerTarget::motion(&self.0, seat, data, &event) } - fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::relative_motion(&p.window, seat, data, event) - } - }) + fn relative_motion( + &self, + _seat: &Seat, + _data: &mut State, + _event: &RelativeMotionEvent, + ) { } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { @@ -746,9 +737,6 @@ impl PointerTarget for CosmicWindow { }); PointerTarget::button(&self.0, seat, data, event) } - Focus::Window => self - .0 - .with_program(|p| PointerTarget::button(&p.window, seat, data, event)), Focus::None => {} x => { let serial = event.serial; @@ -771,7 +759,7 @@ impl PointerTarget for CosmicWindow { Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT, Focus::ResizeLeft => ResizeEdge::LEFT, Focus::ResizeRight => ResizeEdge::RIGHT, - Focus::Header | Focus::Window | Focus::None => unreachable!(), + Focus::Header | Focus::None => unreachable!(), }, ) }); @@ -782,9 +770,6 @@ impl PointerTarget for CosmicWindow { fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { match self.0.with_program(|p| p.current_focus()) { Focus::Header => PointerTarget::axis(&self.0, seat, data, frame), - Focus::Window => self - .0 - .with_program(|p| PointerTarget::axis(&p.window, seat, data, frame)), _ => {} } } @@ -792,131 +777,88 @@ impl PointerTarget for CosmicWindow { fn frame(&self, seat: &Seat, data: &mut State) { match self.0.with_program(|p| p.current_focus()) { Focus::Header => PointerTarget::frame(&self.0, seat, data), - Focus::Window => self - .0 - .with_program(|p| PointerTarget::frame(&p.window, seat, data)), _ => {} } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { - let previous = self.0.with_program(|p| { + self.0.with_program(|p| { + /* if let Some(sessions) = p.window.user_data().get::() { for session in &*sessions.0.borrow() { session.cursor_leave(seat, InputType::Pointer) } - } + }*/ let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(CursorShape::Default); - p.swap_focus(Focus::None) + let _previous = p.swap_focus(Focus::None); }); - match previous { - Focus::Header => PointerTarget::leave(&self.0, seat, data, serial, time), - Focus::Window => self - .0 - .with_program(|p| PointerTarget::leave(&p.window, seat, data, serial, time)), - _ => {} - } + PointerTarget::leave(&self.0, seat, data, serial, time) } fn gesture_swipe_begin( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeBeginEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_swipe_begin(&p.window, seat, data, event) - } - }) } fn gesture_swipe_update( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeUpdateEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeUpdateEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_swipe_update(&p.window, seat, data, event) - } - }) } fn gesture_swipe_end( &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeEndEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureSwipeEndEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_swipe_end(&p.window, seat, data, event) - } - }) } fn gesture_pinch_begin( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchBeginEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_pinch_begin(&p.window, seat, data, event) - } - }) } fn gesture_pinch_update( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchUpdateEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchUpdateEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_pinch_update(&p.window, seat, data, event) - } - }) } fn gesture_pinch_end( &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchEndEvent, + _seat: &Seat, + _data: &mut State, + _event: &GesturePinchEndEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_pinch_end(&p.window, seat, data, event) - } - }) } fn gesture_hold_begin( &self, - seat: &Seat, - data: &mut State, - event: &GestureHoldBeginEvent, + _seat: &Seat, + _data: &mut State, + _event: &GestureHoldBeginEvent, ) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_hold_begin(&p.window, seat, data, event) - } - }) } - fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { - self.0.with_program(|p| { - if !p.has_ssd(false) || p.current_focus() == Focus::Window { - PointerTarget::gesture_hold_end(&p.window, seat, data, event) - } - }) + fn gesture_hold_end( + &self, + _seat: &Seat, + _data: &mut State, + _event: &GestureHoldEndEvent, + ) { } } diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index c81d8b042..135ffe5cb 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -266,21 +266,21 @@ impl Common { .get::() .and_then(|x| x.take()) { - if !popup_grab.has_ended() { - if let Some(new) = popup_grab.current_grab() { - trace!("restore focus to previous popup grab"); - if let Some(keyboard) = seat.get_keyboard() { - keyboard.set_focus( - state, - Some(new.clone()), - SERIAL_COUNTER.next_serial(), - ); - } - ActiveFocus::set(&seat, Some(new)); - seat.user_data() + if !popup_grab.has_ended() { + if let Some(new) = popup_grab.current_grab() { + trace!("restore focus to previous popup grab"); + if let Some(keyboard) = seat.get_keyboard() { + keyboard.set_focus( + state, + Some(new.clone()), + SERIAL_COUNTER.next_serial(), + ); + } + ActiveFocus::set(&seat, Some(new)); + seat.user_data() .get_or_insert::(PopupGrabData::default) - .set(Some(popup_grab)); - continue; + .set(Some(popup_grab)); + continue; } } } diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 8078ed169..d4bf7bc7d 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -1,14 +1,18 @@ use std::sync::Weak; use crate::{ - shell::{element::CosmicMapped, layout::tiling::ResizeForkTarget, CosmicSurface}, + shell::{ + element::{CosmicMapped, CosmicStack, CosmicWindow}, + layout::tiling::ResizeForkTarget, + CosmicSurface, + }, utils::prelude::*, wayland::handlers::xdg_shell::popup::get_popup_toplevel, }; use id_tree::NodeId; use smithay::{ backend::input::KeyState, - desktop::{LayerSurface, PopupKind}, + desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -20,20 +24,17 @@ use smithay::{ Seat, }, reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource}, - utils::{IsAlive, Serial}, + utils::{IsAlive, Logical, Point, Serial}, wayland::{seat::WaylandFocus, session_lock::LockSurface}, - xwayland::X11Surface, }; +// discuss: should contain WlSurface, IcedElement #[derive(Debug, Clone, PartialEq)] pub enum PointerFocusTarget { - Element(CosmicMapped), - Fullscreen(CosmicSurface), - LayerSurface(LayerSurface), - Popup(PopupKind), - OverrideRedirect(X11Surface), + WlSurface(WlSurface), + StackUI(CosmicStack), + WindowUI(CosmicWindow), ResizeFork(ResizeForkTarget), - LockSurface(LockSurface), } #[derive(Debug, Clone, PartialEq)] @@ -50,16 +51,27 @@ pub enum KeyboardFocusTarget { impl From for PointerFocusTarget { fn from(target: KeyboardFocusTarget) -> Self { match target { - KeyboardFocusTarget::Element(elem) => PointerFocusTarget::Element(elem), - KeyboardFocusTarget::Fullscreen(elem) => PointerFocusTarget::Fullscreen(elem), - KeyboardFocusTarget::LayerSurface(layer) => PointerFocusTarget::LayerSurface(layer), - KeyboardFocusTarget::Popup(popup) => PointerFocusTarget::Popup(popup), - KeyboardFocusTarget::LockSurface(lock) => PointerFocusTarget::LockSurface(lock), - _ => unreachable!("A window grab cannot start a popup grab"), + KeyboardFocusTarget::Element(elem) => { + PointerFocusTarget::WlSurface(elem.active_window().wl_surface().unwrap()) + } + KeyboardFocusTarget::Fullscreen(elem) => { + PointerFocusTarget::WlSurface(elem.wl_surface().unwrap()) + } + KeyboardFocusTarget::LayerSurface(layer) => { + PointerFocusTarget::WlSurface(layer.wl_surface().clone()) + } + KeyboardFocusTarget::Popup(popup) => { + PointerFocusTarget::WlSurface(popup.wl_surface().clone()) + } + KeyboardFocusTarget::LockSurface(lock) => { + PointerFocusTarget::WlSurface(lock.wl_surface().clone()) + } + _ => unreachable!("A group cannot start a popup grab"), } } } +/* impl TryFrom for KeyboardFocusTarget { type Error = (); fn try_from(target: PointerFocusTarget) -> Result { @@ -73,6 +85,24 @@ impl TryFrom for KeyboardFocusTarget { } } } +*/ + +impl PointerFocusTarget { + pub fn under_surface>>( + surface: &CosmicSurface, + point: P, + ) -> Option<(Self, Point)> { + match surface.0.underlying_surface() { + WindowSurface::Wayland(_toplevel) => surface + .0 + .surface_under(point, WindowSurfaceType::ALL) + .map(|(wl_surface, point)| (Self::WlSurface(wl_surface), point)), + WindowSurface::X11(surface) => { + Some((Self::WlSurface(surface.wl_surface()?), Point::default())) + } + } + } +} impl KeyboardFocusTarget { pub fn toplevel(&self) -> Option { @@ -100,13 +130,11 @@ impl PartialEq for WindowGroup { impl IsAlive for PointerFocusTarget { fn alive(&self) -> bool { match self { - PointerFocusTarget::Element(e) => e.alive(), - PointerFocusTarget::Fullscreen(f) => f.alive(), - PointerFocusTarget::LayerSurface(l) => l.alive(), - PointerFocusTarget::Popup(p) => p.alive(), - PointerFocusTarget::OverrideRedirect(s) => s.alive(), + // XXX? does this change anything + PointerFocusTarget::WlSurface(s) => s.alive(), + PointerFocusTarget::StackUI(e) => e.alive(), + PointerFocusTarget::WindowUI(e) => e.alive(), PointerFocusTarget::ResizeFork(f) => f.alive(), - PointerFocusTarget::LockSurface(l) => l.alive(), } } } @@ -127,111 +155,62 @@ impl IsAlive for KeyboardFocusTarget { impl PointerTarget for PointerFocusTarget { fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::enter(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => PointerTarget::enter(w, seat, data, event), - PointerFocusTarget::LayerSurface(l) => PointerTarget::enter(l, seat, data, event), - PointerFocusTarget::Popup(p) => PointerTarget::enter(p.wl_surface(), seat, data, event), - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::enter(s, seat, data, event), + PointerFocusTarget::WlSurface(s) => PointerTarget::enter(s, seat, data, event), + PointerFocusTarget::StackUI(u) => PointerTarget::enter(u, seat, data, event), + PointerFocusTarget::WindowUI(u) => PointerTarget::enter(u, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::enter(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::enter(l.wl_surface(), seat, data, event) - } } } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::motion(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => PointerTarget::motion(w, seat, data, event), - PointerFocusTarget::LayerSurface(l) => PointerTarget::motion(l, seat, data, event), - PointerFocusTarget::Popup(p) => { - PointerTarget::motion(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::motion(s, seat, data, event), + PointerFocusTarget::WlSurface(s) => PointerTarget::motion(s, seat, data, event), + PointerFocusTarget::StackUI(u) => PointerTarget::motion(u, seat, data, event), + PointerFocusTarget::WindowUI(u) => PointerTarget::motion(u, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::motion(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::motion(l.wl_surface(), seat, data, event) - } } } fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::relative_motion(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::relative_motion(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::relative_motion(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::relative_motion(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { + PointerFocusTarget::WlSurface(s) => { PointerTarget::relative_motion(s, seat, data, event) } + PointerFocusTarget::StackUI(u) => PointerTarget::relative_motion(u, seat, data, event), + PointerFocusTarget::WindowUI(u) => PointerTarget::relative_motion(u, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::relative_motion(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::relative_motion(l.wl_surface(), seat, data, event) - } } } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::button(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => PointerTarget::button(w, seat, data, event), - PointerFocusTarget::LayerSurface(l) => PointerTarget::button(l, seat, data, event), - PointerFocusTarget::Popup(p) => { - PointerTarget::button(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::button(s, seat, data, event), + PointerFocusTarget::WlSurface(s) => PointerTarget::button(s, seat, data, event), + PointerFocusTarget::StackUI(u) => PointerTarget::button(u, seat, data, event), + PointerFocusTarget::WindowUI(u) => PointerTarget::button(u, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::button(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::button(l.wl_surface(), seat, data, event) - } } } fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { match self { - PointerFocusTarget::Element(w) => PointerTarget::axis(w, seat, data, frame), - PointerFocusTarget::Fullscreen(w) => PointerTarget::axis(w, seat, data, frame), - PointerFocusTarget::LayerSurface(l) => PointerTarget::axis(l, seat, data, frame), - PointerFocusTarget::Popup(p) => PointerTarget::axis(p.wl_surface(), seat, data, frame), - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::axis(s, seat, data, frame), + PointerFocusTarget::WlSurface(s) => PointerTarget::axis(s, seat, data, frame), + PointerFocusTarget::StackUI(u) => PointerTarget::axis(u, seat, data, frame), + PointerFocusTarget::WindowUI(u) => PointerTarget::axis(u, seat, data, frame), PointerFocusTarget::ResizeFork(f) => PointerTarget::axis(f, seat, data, frame), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::axis(l.wl_surface(), seat, data, frame) - } } } fn frame(&self, seat: &Seat, data: &mut State) { match self { - PointerFocusTarget::Element(w) => PointerTarget::frame(w, seat, data), - PointerFocusTarget::Fullscreen(w) => PointerTarget::frame(w, seat, data), - PointerFocusTarget::LayerSurface(l) => PointerTarget::frame(l, seat, data), - PointerFocusTarget::Popup(p) => PointerTarget::frame(p.wl_surface(), seat, data), - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::frame(s, seat, data), + PointerFocusTarget::WlSurface(s) => PointerTarget::frame(s, seat, data), + PointerFocusTarget::StackUI(u) => PointerTarget::frame(u, seat, data), + PointerFocusTarget::WindowUI(u) => PointerTarget::frame(u, seat, data), PointerFocusTarget::ResizeFork(f) => PointerTarget::frame(f, seat, data), - PointerFocusTarget::LockSurface(l) => PointerTarget::frame(l.wl_surface(), seat, data), } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { match self { - PointerFocusTarget::Element(w) => PointerTarget::leave(w, seat, data, serial, time), - PointerFocusTarget::Fullscreen(w) => PointerTarget::leave(w, seat, data, serial, time), - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::leave(l, seat, data, serial, time) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::leave(p.wl_surface(), seat, data, serial, time) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::leave(s, seat, data, serial, time) - } + PointerFocusTarget::WlSurface(s) => PointerTarget::leave(s, seat, data, serial, time), + PointerFocusTarget::StackUI(u) => PointerTarget::leave(u, seat, data, serial, time), + PointerFocusTarget::WindowUI(u) => PointerTarget::leave(u, seat, data, serial, time), PointerFocusTarget::ResizeFork(f) => PointerTarget::leave(f, seat, data, serial, time), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::leave(l.wl_surface(), seat, data, serial, time) - } } } fn gesture_swipe_begin( @@ -241,27 +220,18 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_begin(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_swipe_begin(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_begin(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_begin(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_begin(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_begin(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_begin(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_swipe_begin(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_swipe_update( @@ -271,27 +241,18 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeUpdateEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_update(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_update(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_update(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_update(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_update(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_swipe_update(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_update(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_update(l.wl_surface(), seat, data, event) - } } } fn gesture_swipe_end( @@ -301,27 +262,18 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeEndEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_end(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_swipe_end(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_end(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_end(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_end(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_end(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_end(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_swipe_end(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_end(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_begin( @@ -331,27 +283,18 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_begin(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_pinch_begin(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_begin(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_begin(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_begin(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_pinch_begin(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_begin(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_pinch_begin(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_update( @@ -361,27 +304,18 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchUpdateEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_update(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_pinch_update(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_update(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_update(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_update(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_pinch_update(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_update(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_pinch_update(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_update(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_update(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_end( @@ -391,27 +325,18 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchEndEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_end(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_end(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_end(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_pinch_end(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_end(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_pinch_end(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_end(l.wl_surface(), seat, data, event) - } } } fn gesture_hold_begin( @@ -421,50 +346,32 @@ impl PointerTarget for PointerFocusTarget { event: &GestureHoldBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) - } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_begin(l, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_hold_begin(s, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_begin(p.wl_surface(), seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_hold_begin(u, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_hold_begin(s, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_hold_begin(u, seat, data, event) } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_hold_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::gesture_hold_end(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_hold_end(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_end(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_end(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { + PointerFocusTarget::WlSurface(s) => { PointerTarget::gesture_hold_end(s, seat, data, event) } + PointerFocusTarget::StackUI(u) => PointerTarget::gesture_hold_end(u, seat, data, event), + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_hold_end(u, seat, data, event) + } PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_hold_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_end(l.wl_surface(), seat, data, event) - } } } } @@ -590,59 +497,40 @@ impl WaylandFocus for KeyboardFocusTarget { impl WaylandFocus for PointerFocusTarget { fn wl_surface(&self) -> Option { Some(match self { - PointerFocusTarget::Element(w) => WaylandFocus::wl_surface(w)?, - PointerFocusTarget::Fullscreen(w) => WaylandFocus::wl_surface(w)?, - PointerFocusTarget::LayerSurface(l) => l.wl_surface().clone(), - PointerFocusTarget::Popup(p) => p.wl_surface().clone(), - PointerFocusTarget::OverrideRedirect(s) => { - return s.wl_surface(); - } - PointerFocusTarget::ResizeFork(_) => { + PointerFocusTarget::WlSurface(s) => s.clone(), + PointerFocusTarget::ResizeFork(_) + | PointerFocusTarget::StackUI(_) + | PointerFocusTarget::WindowUI(_) => { return None; } - PointerFocusTarget::LockSurface(l) => l.wl_surface().clone(), }) } fn same_client_as(&self, object_id: &ObjectId) -> bool { match self { - PointerFocusTarget::Element(w) => WaylandFocus::same_client_as(w, object_id), - PointerFocusTarget::Fullscreen(w) => WaylandFocus::same_client_as(w, object_id), - PointerFocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id), - PointerFocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id), - PointerFocusTarget::OverrideRedirect(s) => WaylandFocus::same_client_as(s, object_id), + PointerFocusTarget::WlSurface(s) => s.id().same_client_as(object_id), + PointerFocusTarget::StackUI(stack) => stack + .active() + .wl_surface() + .map(|s| s.id().same_client_as(object_id)) + .unwrap_or(false), + PointerFocusTarget::WindowUI(window) => window + .wl_surface() + .map(|s| s.id().same_client_as(object_id)) + .unwrap_or(false), PointerFocusTarget::ResizeFork(_) => false, - PointerFocusTarget::LockSurface(l) => l.wl_surface().id().same_client_as(object_id), } } } -impl From for PointerFocusTarget { - fn from(w: CosmicMapped) -> Self { - PointerFocusTarget::Element(w) - } -} - -impl From for PointerFocusTarget { - fn from(s: CosmicSurface) -> Self { - PointerFocusTarget::Fullscreen(s) - } -} - -impl From for PointerFocusTarget { - fn from(l: LayerSurface) -> Self { - PointerFocusTarget::LayerSurface(l) +impl From for PointerFocusTarget { + fn from(s: WlSurface) -> Self { + PointerFocusTarget::WlSurface(s) } } impl From for PointerFocusTarget { fn from(p: PopupKind) -> Self { - PointerFocusTarget::Popup(p) - } -} - -impl From for PointerFocusTarget { - fn from(s: X11Surface) -> Self { - PointerFocusTarget::OverrideRedirect(s) + PointerFocusTarget::WlSurface(p.wl_surface().clone()) } } @@ -654,7 +542,7 @@ impl From for PointerFocusTarget { impl From for PointerFocusTarget { fn from(l: LockSurface) -> Self { - PointerFocusTarget::LockSurface(l) + PointerFocusTarget::WlSurface(l.wl_surface().clone()) } } diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 345842e98..50a38bbe3 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -760,18 +760,24 @@ impl Drop for MoveGrab { if let Some((mapped, position)) = position { let serial = SERIAL_COUNTER.next_serial(); - pointer.motion( - state, - Some(( - PointerFocusTarget::from(mapped.clone()), - position.as_logical() - window.geometry().loc, - )), - &MotionEvent { - location: pointer.current_location(), - serial, - time: 0, - }, - ); + let current_location = pointer.current_location(); + + if let Some((target, offset)) = + mapped.focus_under(current_location - position.as_logical().to_f64()) + { + pointer.motion( + state, + Some(( + target, + position.as_logical() - window.geometry().loc + offset, + )), + &MotionEvent { + location: pointer.current_location(), + serial, + time: 0, + }, + ); + } Common::set_focus( state, Some(&KeyboardFocusTarget::from(mapped)), diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 7a9d1fb9b..092879c52 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -686,7 +686,13 @@ impl FloatingLayout { self.space.element_geometry(elem).map(RectExt::as_local) } - pub fn element_under( + pub fn element_under(&mut self, location: Point) -> Option { + self.space + .element_under(location.as_logical()) + .map(|(mapped, _)| mapped.clone().into()) + } + + pub fn surface_under( &mut self, location: Point, ) -> Option<(PointerFocusTarget, Point)> { @@ -694,6 +700,7 @@ impl FloatingLayout { .space .element_under(location.as_logical()) .map(|(mapped, p)| (mapped.clone(), p.as_local())); + if let Some((mapped, _)) = res.as_ref() { let geometry = self.space.element_geometry(mapped).unwrap(); let offset = location.y.round() as i32 - geometry.loc.y; @@ -705,7 +712,16 @@ impl FloatingLayout { } else { self.hovered_stack.take(); } - res.map(|(m, p)| (m.into(), p)) + + res.and_then(|(element, space_offset)| { + let geometry = self.space.element_geometry(&element).unwrap().as_local(); + let point = location - geometry.loc.to_f64(); + element + .focus_under(point.as_logical()) + .map(|(surface, surface_offset)| { + (surface, space_offset + surface_offset.as_local()) + }) + }) } pub fn stacking_indicator(&self) -> Option> { diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index f048af19d..76e5c48df 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -3088,6 +3088,26 @@ impl TilingLayout { pub fn element_under( &mut self, location_f64: Point, + ) -> Option { + let location = location_f64.to_i32_round(); + + for (mapped, geo) in self.mapped() { + if !mapped.bbox().contains((location - geo.loc).as_logical()) { + continue; + } + if mapped.is_in_input_region( + &((location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64()), + ) { + return Some(mapped.clone().into()); + } + } + + None + } + + pub fn surface_under( + &mut self, + location_f64: Point, overview: OverviewMode, ) -> Option<(PointerFocusTarget, Point)> { let gaps = self.gaps(); @@ -3115,13 +3135,12 @@ impl TilingLayout { if !mapped.bbox().contains((location - geo.loc).as_logical()) { continue; } - if mapped.is_in_input_region( - &((location_f64 - geo.loc.to_f64()).as_logical() - + mapped.geometry().loc.to_f64()), + if let Some((target, surface_offset)) = mapped.focus_under( + (location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(), ) { return Some(( - mapped.clone().into(), - geo.loc - mapped.geometry().loc.as_local(), + target, + geo.loc - mapped.geometry().loc.as_local() + surface_offset.as_local(), )); } } @@ -3163,12 +3182,15 @@ impl TilingLayout { let test_point = (location.to_f64() - last_geometry.loc.to_f64() + mapped.geometry().loc.to_f64().as_local()) .as_logical(); - mapped.is_in_input_region(&test_point).then(|| { - ( - mapped.clone().into(), - last_geometry.loc - mapped.geometry().loc.as_local(), - ) - }) + mapped + .focus_under(test_point) + .map(|(surface, surface_offset)| { + ( + surface, + last_geometry.loc - mapped.geometry().loc.as_local() + + surface_offset.as_local(), + ) + }) } Some(( id, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 0f610ed78..56e5529c9 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2057,14 +2057,45 @@ impl Shell { &mut self, location: Point, output: &Output, + ) -> Option { + self.workspaces.sets.get_mut(output).and_then(|set| { + set.sticky_layer + .space + .element_under(location.to_local(output).as_logical()) + .map(|(mapped, _)| mapped.clone().into()) + .or_else(|| set.workspaces[set.active].element_under(location)) + }) + } + pub fn surface_under( + &mut self, + location: Point, + output: &Output, ) -> Option<(PointerFocusTarget, Point)> { let overview = self.overview_mode.clone(); self.workspaces.sets.get_mut(output).and_then(|set| { set.sticky_layer .space .element_under(location.to_local(output).as_logical()) - .map(|(mapped, p)| (mapped.clone().into(), p.as_local().to_global(output))) - .or_else(|| set.workspaces[set.active].element_under(location, overview)) + .and_then(|(mapped, element_offset)| { + let geometry = set + .sticky_layer + .space + .element_geometry(mapped) + .unwrap() + .as_local(); + let point = location.to_local(output) - geometry.loc.to_f64(); + mapped + .focus_under(point.as_logical()) + .map(|(surface, surface_offset)| { + ( + surface, + (element_offset + surface_offset) + .as_local() + .to_global(output), + ) + }) + }) + .or_else(|| set.workspaces[set.active].surface_under(location, overview)) }) } @@ -2455,7 +2486,7 @@ impl Shell { state.common.theme.clone(), ) .into(); - start_data.focus = Some((new_mapped.clone().into(), Point::from((0, 0)))); + start_data.focus = new_mapped.focus_under((0., 0.).into()); new_mapped } else { old_mapped.clone() @@ -2843,8 +2874,10 @@ impl Shell { return; }; - let focus = Some((mapped.clone().into(), (new_loc - geometry.loc).as_logical())); - + let element_offset = (new_loc - geometry.loc).as_logical(); + let focus = mapped + .focus_under(element_offset.to_f64()) + .map(|(target, surface_offset)| (target, (surface_offset + element_offset))); start_data.location = new_loc.as_logical().to_f64(); start_data.focus = focus.clone(); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index aa4ff4ae5..50823020a 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -493,15 +493,22 @@ impl Workspace { .find(|e| e.windows().any(|(w, _)| &w == surface)) } - pub fn element_under( + pub fn element_under(&mut self, location: Point) -> Option { + let location = location.to_local(&self.output); + self.floating_layer + .element_under(location) + .or_else(|| self.tiling_layer.element_under(location)) + } + + pub fn surface_under( &mut self, location: Point, overview: OverviewMode, ) -> Option<(PointerFocusTarget, Point)> { let location = location.to_local(&self.output); self.floating_layer - .element_under(location) - .or_else(|| self.tiling_layer.element_under(location, overview)) + .surface_under(location) + .or_else(|| self.tiling_layer.surface_under(location, overview)) .map(|(m, p)| (m, p.to_global(&self.output))) } diff --git a/src/wayland/handlers/xdg_shell/popup.rs b/src/wayland/handlers/xdg_shell/popup.rs index 6853874a7..9f54aa1a0 100644 --- a/src/wayland/handlers/xdg_shell/popup.rs +++ b/src/wayland/handlers/xdg_shell/popup.rs @@ -19,11 +19,10 @@ use smithay::{ seat::WaylandFocus, shell::xdg::{ PopupSurface, PositionerState, SurfaceCachedState, ToplevelSurface, - XdgPopupSurfaceRoleAttributes, XDG_POPUP_ROLE, + XdgPopupSurfaceData, XDG_POPUP_ROLE, }, }, }; -use std::sync::Mutex; use tracing::{trace, warn}; impl Shell { @@ -96,7 +95,7 @@ pub fn update_reactive_popups<'a>( let positioner = with_states(&surface.wl_surface(), |states| { let attributes = states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap(); @@ -378,7 +377,7 @@ pub fn get_popup_toplevel(popup: &PopupSurface) -> Option { parent = with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap() @@ -402,7 +401,7 @@ fn get_popup_toplevel_coords(popup: &PopupSurface) -> Point { offset += with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap() @@ -413,7 +412,7 @@ fn get_popup_toplevel_coords(popup: &PopupSurface) -> Point { parent = with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap()