diff --git a/Cargo.lock b/Cargo.lock index 5a80db20..162d9e69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,6 +547,20 @@ name = "calloop" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +dependencies = [ + "bitflags 2.4.2", + "log", + "polling 3.3.2", + "rustix 0.38.30", + "slab", + "thiserror", +] + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "async-task", "bitflags 2.4.2", @@ -563,7 +577,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" dependencies = [ - "calloop", + "calloop 0.12.4", "rustix 0.38.30", "wayland-backend", "wayland-client", @@ -827,7 +841,7 @@ dependencies = [ "anyhow", "bitflags 2.4.2", "bytemuck", - "calloop", + "calloop 0.13.0", "cosmic-comp-config", "cosmic-config", "cosmic-protocols", @@ -887,10 +901,10 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "atomicwrites", - "calloop", + "calloop 0.13.0", "cosmic-config-derive", "dirs", "iced_futures", @@ -905,7 +919,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "quote", "syn 1.0.109", @@ -926,7 +940,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.11.2" -source = "git+https://github.com/pop-os/cosmic-text.git#b08676909f882f553ab574601b35b58276a52458" +source = "git+https://github.com/pop-os/cosmic-text.git#ff5501d9a36e51c50d908413caf7632d8f7533b7" dependencies = [ "bitflags 2.4.2", "fontdb", @@ -948,7 +962,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "almost", "cosmic-config", @@ -2296,7 +2310,7 @@ dependencies = [ [[package]] name = "iced" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "iced_core", "iced_futures", @@ -2310,7 +2324,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "bitflags 1.3.2", "log", @@ -2328,7 +2342,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "futures", "iced_core", @@ -2340,7 +2354,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2364,7 +2378,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2376,7 +2390,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "iced_core", "iced_futures", @@ -2387,7 +2401,7 @@ dependencies = [ [[package]] name = "iced_style" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "iced_core", "once_cell", @@ -2397,7 +2411,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "bytemuck", "cosmic-text", @@ -2414,7 +2428,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2433,7 +2447,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "iced_renderer", "iced_runtime", @@ -2763,7 +2777,7 @@ checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic/#d02a4fefff319a3bd20936f9be30c4913bf49bab" +source = "git+https://github.com/pop-os/libcosmic/#cc439b2ceaf41226ab86416ae0ad3651c9a6e10a" dependencies = [ "apply", "chrono", @@ -4491,12 +4505,12 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=c17297b#c17297b68e8bc761ebddf6900926d78b19a5d8d1" +source = "git+https://github.com/smithay//smithay?rev=e5f0068#e5f006818df7ebb92d206985f45e713ba1e9c1c9" dependencies = [ "appendlist", "ash", "bitflags 2.4.2", - "calloop", + "calloop 0.13.0", "cc", "cgmath", "cursor-icon", @@ -4546,7 +4560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" dependencies = [ "bitflags 2.4.2", - "calloop", + "calloop 0.12.4", "calloop-wayland-source", "cursor-icon", "libc", @@ -6033,7 +6047,7 @@ dependencies = [ "atomic-waker", "bitflags 2.4.2", "bytemuck", - "calloop", + "calloop 0.12.4", "cfg_aliases 0.1.1", "core-foundation", "core-graphics", diff --git a/Cargo.toml b/Cargo.toml index 263f42c1..9fbcbf38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ anyhow = {version = "1.0.51", features = ["backtrace"]} bitflags = "2.4" bytemuck = "1.12" -calloop = {version = "0.12.2", features = ["executor"]} +calloop = {version = "0.13.0", features = ["executor"]} cosmic-comp-config = {path = "cosmic-comp-config"} cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]} cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]} @@ -117,4 +117,4 @@ inherits = "release" lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = {git = "https://github.com/smithay//smithay", rev = "c17297b"} +smithay = {git = "https://github.com/smithay//smithay", rev = "e5f0068"} diff --git a/src/input/mod.rs b/src/input/mod.rs index 549457f1..197a0640 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, @@ -32,7 +35,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::{ @@ -41,6 +47,7 @@ use smithay::{ GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, RelativeMotionEvent, }, + touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, Seat, SeatState, }, output::Output, @@ -726,11 +733,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; } @@ -907,7 +918,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 @@ -968,7 +979,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); @@ -1003,12 +1014,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), _) = @@ -1308,19 +1314,18 @@ impl State { let under = State::surface_under(position, &output, &mut self.common.shell) .map(|(target, pos)| (target, pos.as_logical())); - if let Some((target, pos)) = under { - if let Some(wl_surface) = target.wl_surface() { - let serial = SERIAL_COUNTER.next_serial(); - let touch = seat.get_touch().unwrap(); - touch.down( - serial, - event.time_msec(), - &wl_surface, - position.as_logical() - pos.to_f64(), - event.slot(), - ); - } - } + let serial = SERIAL_COUNTER.next_serial(); + let touch = seat.get_touch().unwrap(); + touch.down( + self, + under, + &DownEvent { + slot: event.slot(), + location: position.as_logical(), + serial, + time: event.time_msec(), + }, + ); } } InputEvent::TouchMotion { event, .. } => { @@ -1341,30 +1346,44 @@ impl State { let under = State::surface_under(position, &output, &mut self.common.shell) .map(|(target, pos)| (target, pos.as_logical())); - if let Some((_target, pos)) = under { - let touch = seat.get_touch().unwrap(); - touch.motion( - event.time_msec(), - event.slot(), - position.as_logical() - pos.to_f64(), - ); - } + let touch = seat.get_touch().unwrap(); + touch.motion( + self, + under, + &TouchMotionEvent { + slot: event.slot(), + location: position.as_logical(), + time: event.time_msec(), + }, + ); } } InputEvent::TouchUp { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()) { let serial = SERIAL_COUNTER.next_serial(); let touch = seat.get_touch().unwrap(); - touch.up(serial, event.time_msec(), event.slot()); + touch.up( + self, + &UpEvent { + slot: event.slot(), + time: event.time_msec(), + serial, + }, + ); } } InputEvent::TouchCancel { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()) { let touch = seat.get_touch().unwrap(); - touch.cancel(); + touch.cancel(self); + } + } + InputEvent::TouchFrame { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let touch = seat.get_touch().unwrap(); + touch.frame(self); } } - InputEvent::TouchFrame { event: _, .. } => {} InputEvent::TabletToolAxis { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { let Some(output) = @@ -2291,7 +2310,10 @@ impl State { if let Some(session_lock) = session_lock { return session_lock.surfaces.get(output).map(|surface| { ( - PointerFocusTarget::LockSurface(surface.clone()), + PointerFocusTarget::WlSurface { + surface: surface.wl_surface().clone(), + toplevel: None, + }, output_geo.loc, ) }); @@ -2301,24 +2323,42 @@ 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(( + PointerFocusTarget::WlSurface { + surface: wl_surface, + toplevel: None, + }, + 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())); - } - Some((window.clone().into(), output_geo.loc)) + 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(( + PointerFocusTarget::WlSurface { + surface, + toplevel: None, + }, + geo, + )); + } + 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); @@ -2327,28 +2367,42 @@ 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(), + PointerFocusTarget::WlSurface { + surface: wl_surface, + toplevel: None, + }, + 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((target, loc)) = shell.element_under(global_pos, output) { + 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(( + PointerFocusTarget::WlSurface { + surface, + toplevel: None, + }, + geo, + )); + } + if let Some((target, loc)) = shell.surface_under(global_pos, output) { return Some((target, loc)); } { @@ -2358,16 +2412,16 @@ 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(), + PointerFocusTarget::WlSurface { + surface: wl_surface, + toplevel: None, + }, + 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 b78f83c4..356c9bfc 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 9dae1534..532972af 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, @@ -12,7 +12,6 @@ use crate::{ iced::{IcedElement, Program}, prelude::*, }, - wayland::handlers::screencopy::SessionHolder, }; use calloop::LoopHandle; use cosmic::{ @@ -34,7 +33,7 @@ use smithay::{ ImportAll, ImportMem, Renderer, }, }, - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -47,7 +46,7 @@ use smithay::{ }, output::Output, render_elements, - utils::{Buffer, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, Transform}, + utils::{Buffer, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size}, wayland::seat::WaylandFocus, }; use std::{ @@ -58,7 +57,6 @@ use std::{ atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering}, Arc, Mutex, }, - time::Duration, }; mod tab; @@ -97,7 +95,6 @@ pub struct CosmicStackInternal { potential_drag: Arc>>, override_alive: Arc, last_seat: Arc, Serial)>>>, - last_location: Arc, Serial, u32)>>>, geometry: Arc>>>, mask: Arc>>, } @@ -123,7 +120,6 @@ pub const TAB_HEIGHT: i32 = 24; pub enum Focus { None, Header, - Window, ResizeTop, ResizeLeft, ResizeRight, @@ -170,7 +166,6 @@ impl CosmicStack { potential_drag: Arc::new(Mutex::new(None)), override_alive: Arc::new(AtomicBool::new(true)), last_seat: Arc::new(Mutex::new(None)), - last_location: Arc::new(Mutex::new(None)), geometry: Arc::new(Mutex::new(None)), mask: Arc::new(Mutex::new(None)), }, @@ -422,6 +417,54 @@ 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, + toplevel: Some(active_window.clone().into()), + }, + surface_offset + Point::from((0, TAB_HEIGHT)), + ) + }) + .or(stack_ui) + }) + } + pub fn offset(&self) -> Point { Point::from((0, TAB_HEIGHT)) } @@ -480,59 +523,6 @@ impl CosmicStack { }) } - fn pointer_leave_if_previous( - &self, - seat: &Seat, - data: &mut State, - serial: Serial, - time: u32, - location: Point, - ) -> usize { - self.0.with_program(|p| { - let active = p.active.load(Ordering::SeqCst); - let previous = p.previous_pointer.swap(active, Ordering::SeqCst); - if previous != active { - let windows = p.windows.lock().unwrap(); - if let Some(previous) = windows.get(previous) { - for session in previous.cursor_sessions() { - session.set_cursor_pos(None); - } - PointerTarget::leave(previous, seat, data, serial, time); - } - - for session in windows[active].cursor_sessions() { - session.set_cursor_pos(Some( - location - .to_buffer( - 1.0, - Transform::Normal, - &windows[active].geometry().size.to_f64(), - ) - .to_i32_round(), - )); - if let Some((_, hotspot)) = - seat.cursor_geometry((0.0, 0.0), Duration::from_millis(time as u64).into()) - { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - PointerTarget::enter( - &windows[active], - seat, - data, - &MotionEvent { - location, - serial, - time, - }, - ); - } - active - }) - } - pub(in super::super) fn focus_stack(&self) { self.0 .with_program(|p| p.group_focused.store(true, Ordering::SeqCst)); @@ -941,33 +931,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); @@ -1130,11 +1094,11 @@ 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)]; 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, @@ -1167,43 +1131,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); - - for session in active_window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer(1.0, Transform::Normal, &geo.size.to_f64()) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - - return false; + return; }; - if old_focus == Focus::Window { - PointerTarget::leave(active_window, seat, data, event.serial, event.time); - - for session in active_window.cursor_sessions() { - session.set_cursor_pos(None); - } - } - let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(shape); let cursor_status = seat @@ -1211,24 +1141,21 @@ 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) { let mut event = event.clone(); - 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 = p.active.load(Ordering::SeqCst); let active_window = &p.windows.lock().unwrap()[active]; let geo = active_window.geometry(); let loc = event.location.to_i32_round::(); @@ -1253,44 +1180,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); - } - - for session in active_window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer(1.0, Transform::Normal, &geo.size.to_f64()) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - - 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); - - for session in active_window.cursor_sessions() { - session.set_cursor_pos(None); - } - } + let _previous = p.swap_focus(next); let cursor_state = seat.user_data().get::().unwrap(); cursor_state.set_shape(shape); @@ -1299,99 +1192,56 @@ impl PointerTarget for CosmicStack { .get::>() .unwrap(); *cursor_status.borrow_mut() = CursorImageStatus::default_named(); - - (previous, next) }); - let active_window_geo = self - .0 - .with_program(|p| p.windows.lock().unwrap()[active].geometry()); + let active_window_geo = self.0.with_program(|p| { + p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].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) { - if let Some((location, _serial, _time)) = self - .0 - .with_program(|p| p.last_location.lock().unwrap().clone()) - { - self.pointer_leave_if_previous(seat, data, event.serial, event.time, location); - } - match self.0.with_program(|p| p.current_focus()) { Focus::Header => { self.0.with_program(|p| { @@ -1399,27 +1249,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; @@ -1445,7 +1274,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!(), }, ) }); @@ -1454,188 +1283,117 @@ impl PointerTarget for CosmicStack { } fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { - if let Some((location, serial, time)) = self - .0 - .with_program(|p| p.last_location.lock().unwrap().clone()) - { - self.pointer_leave_if_previous(seat, data, serial, time, location); - } - 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, - ) - }), _ => {} } } fn frame(&self, seat: &Seat, data: &mut State) { - if let Some((location, serial, time)) = self - .0 - .with_program(|p| p.last_location.lock().unwrap().clone()) - { - self.pointer_leave_if_previous(seat, data, serial, time, location); - } - 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, - ) - }), _ => {} } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { - if let Some((location, serial, time)) = self - .0 - .with_program(|p| p.last_location.lock().unwrap().clone()) - { - self.pointer_leave_if_previous(seat, data, serial, time, location); - } - - let previous = self.0.with_program(|p| { - for session in - p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].cursor_sessions() - { - session.set_cursor_pos(None); - } - + self.0.with_program(|p| { 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/surface.rs b/src/shell/element/surface.rs index 375ae512..2dad2e46 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -18,12 +18,6 @@ use smithay::{ }, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, - PointerTarget, RelativeMotionEvent, - }, Seat, }, output::Output, @@ -670,11 +664,22 @@ impl KeyboardTarget for CosmicSurface { if self.0.is_x11() { keys = vec![]; } - KeyboardTarget::enter(&self.0, seat, data, keys, serial) + + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::enter(toplevel.wl_surface(), seat, data, keys, serial) + } + WindowSurface::X11(x11) => KeyboardTarget::enter(x11, seat, data, keys, serial), + } } fn leave(&self, seat: &Seat, data: &mut State, serial: smithay::utils::Serial) { - KeyboardTarget::leave(&self.0, seat, data, serial) + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::leave(toplevel.wl_surface(), seat, data, serial) + } + WindowSurface::X11(x11) => KeyboardTarget::leave(x11, seat, data, serial), + } } fn key( @@ -686,7 +691,14 @@ impl KeyboardTarget for CosmicSurface { serial: smithay::utils::Serial, time: u32, ) { - KeyboardTarget::key(&self.0, seat, data, key, state, serial, time) + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::key(toplevel.wl_surface(), seat, data, key, state, serial, time) + } + WindowSurface::X11(x11) => { + KeyboardTarget::key(x11, seat, data, key, state, serial, time) + } + } } fn modifiers( @@ -696,110 +708,14 @@ impl KeyboardTarget for CosmicSurface { modifiers: ModifiersState, serial: smithay::utils::Serial, ) { - KeyboardTarget::modifiers(&self.0, seat, data, modifiers, serial) - } -} - -impl PointerTarget for CosmicSurface { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - PointerTarget::enter(&self.0, seat, data, event) - } - - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - PointerTarget::motion(&self.0, seat, data, event) - } - - fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { - PointerTarget::relative_motion(&self.0, seat, data, event) - } - - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { - PointerTarget::button(&self.0, seat, data, event) - } - - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { - PointerTarget::axis(&self.0, seat, data, frame) - } - - fn frame(&self, seat: &Seat, data: &mut State) { - PointerTarget::frame(&self.0, seat, data) - } - - fn leave( - &self, - seat: &Seat, - data: &mut State, - serial: smithay::utils::Serial, - time: u32, - ) { - PointerTarget::leave(&self.0, seat, data, serial, time) - } - - fn gesture_swipe_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeBeginEvent, - ) { - PointerTarget::gesture_swipe_begin(&self.0, seat, data, event) - } - - fn gesture_swipe_update( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeUpdateEvent, - ) { - PointerTarget::gesture_swipe_update(&self.0, seat, data, event) - } - - fn gesture_swipe_end( - &self, - seat: &Seat, - data: &mut State, - event: &GestureSwipeEndEvent, - ) { - PointerTarget::gesture_swipe_end(&self.0, seat, data, event) - } - - fn gesture_pinch_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchBeginEvent, - ) { - PointerTarget::gesture_pinch_begin(&self.0, seat, data, event) - } - - fn gesture_pinch_update( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchUpdateEvent, - ) { - PointerTarget::gesture_pinch_update(&self.0, seat, data, event) - } - - fn gesture_pinch_end( - &self, - seat: &Seat, - data: &mut State, - event: &GesturePinchEndEvent, - ) { - PointerTarget::gesture_pinch_end(&self.0, seat, data, event) - } - - fn gesture_hold_begin( - &self, - seat: &Seat, - data: &mut State, - event: &GestureHoldBeginEvent, - ) { - PointerTarget::gesture_hold_begin(&self.0, seat, data, event) - } - - fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { - PointerTarget::gesture_hold_end(&self.0, seat, data, event) + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::modifiers(toplevel.wl_surface(), seat, data, modifiers, serial) + } + WindowSurface::X11(x11) => { + KeyboardTarget::modifiers(x11, seat, data, modifiers, serial) + } + } } } diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 8b94ca64..95310541 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, }, @@ -9,7 +10,6 @@ use crate::{ iced::{IcedElement, Program}, prelude::*, }, - wayland::handlers::screencopy::SessionHolder, }; use calloop::LoopHandle; use cosmic::{iced::Command, widget::mouse_area, Apply}; @@ -24,7 +24,7 @@ use smithay::{ ImportAll, ImportMem, Renderer, }, }, - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -38,7 +38,7 @@ use smithay::{ output::Output, reexports::wayland_server::protocol::wl_surface::WlSurface, render_elements, - utils::{Buffer as BufferCoords, IsAlive, Logical, Point, Rectangle, Serial, Size, Transform}, + utils::{Buffer as BufferCoords, IsAlive, Logical, Point, Rectangle, Serial, Size}, wayland::seat::WaylandFocus, }; use std::{ @@ -49,7 +49,6 @@ use std::{ atomic::{AtomicBool, AtomicU8, Ordering}, Arc, Mutex, }, - time::Duration, }; use wayland_backend::server::ObjectId; @@ -97,7 +96,6 @@ impl fmt::Debug for CosmicWindowInternal { pub enum Focus { None, Header, - Window, ResizeTop, ResizeLeft, ResizeRight, @@ -181,6 +179,57 @@ 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, + toplevel: Some(p.window.clone().into()), + }, + offset + surface_offset, + ) + }) + .or(window_ui) + }) + } + pub fn contains_surface(&self, window: &CosmicSurface) -> bool { self.0.with_program(|p| &p.window == window) } @@ -452,30 +501,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,7 +601,7 @@ 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 p.has_ssd(false) { let geo = p.window.geometry(); let loc = event.location.to_i32_round::(); @@ -612,34 +638,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); - - for session in p.window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer( - 1.0, - Transform::Normal, - &p.window.geometry().size.to_f64(), - ) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - return false; + return; }; assert_eq!(old_focus, Focus::None); @@ -651,37 +650,16 @@ 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); - for session in p.window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer(1.0, Transform::Normal, &p.window.geometry().size.to_f64()) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - 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 p.has_ssd(false) { let geo = p.window.geometry(); let loc = event.location.to_i32_round::(); @@ -704,43 +682,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); - } - - for session in p.window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer( - 1.0, - Transform::Normal, - &p.window.geometry().size.to_f64(), - ) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - - 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); @@ -749,52 +694,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); - - for session in p.window.cursor_sessions() { - session.set_cursor_pos(Some( - event - .location - .to_buffer(1.0, Transform::Normal, &p.window.geometry().size.to_f64()) - .to_i32_round(), - )); - if let Some((_, hotspot)) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time as u64).into(), - ) { - session.set_cursor_hotspot(hotspot); - } else { - session.set_cursor_hotspot((0, 0)); - } - } - - 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) { @@ -805,9 +717,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; @@ -830,7 +739,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!(), }, ) }); @@ -841,9 +750,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)), _ => {} } } @@ -851,129 +757,81 @@ 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| { - for session in p.window.cursor_sessions() { - session.set_cursor_pos(None); - } - + self.0.with_program(|p| { 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 c81d8b04..135ffe5c 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 8078ed16..9a4e14bc 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -1,39 +1,64 @@ -use std::sync::Weak; +use std::{sync::Weak, time::Duration}; 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, + wayland::handlers::{screencopy::SessionHolder, xdg_shell::popup::get_popup_toplevel}, }; use id_tree::NodeId; use smithay::{ backend::input::KeyState, - desktop::{LayerSurface, PopupKind}, + desktop::{space::SpaceElement, LayerSurface, PopupKind, WindowSurface, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, - PointerTarget, RelativeMotionEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, + }, + touch::{ + DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget, + UpEvent, }, Seat, }, reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource}, - utils::{IsAlive, Serial}, + utils::{IsAlive, Logical, Point, Serial, Transform}, wayland::{seat::WaylandFocus, session_lock::LockSurface}, - xwayland::X11Surface, }; #[derive(Debug, Clone, PartialEq)] pub enum PointerFocusTarget { - Element(CosmicMapped), - Fullscreen(CosmicSurface), - LayerSurface(LayerSurface), - Popup(PopupKind), - OverrideRedirect(X11Surface), + WlSurface { + surface: WlSurface, + toplevel: Option, + }, + StackUI(CosmicStack), + WindowUI(CosmicWindow), ResizeFork(ResizeForkTarget), - LockSurface(LockSurface), +} + +#[derive(Debug, Clone, PartialEq)] +pub enum PointerFocusToplevel { + Surface(CosmicSurface), + Popup(PopupKind), +} + +impl From for PointerFocusToplevel { + fn from(value: CosmicSurface) -> Self { + PointerFocusToplevel::Surface(value) + } +} + +impl From for PointerFocusToplevel { + fn from(value: PopupKind) -> Self { + PointerFocusToplevel::Popup(value) + } } #[derive(Debug, Clone, PartialEq)] @@ -50,26 +75,87 @@ 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) => { + let window = elem.active_window(); + let surface = window.wl_surface().unwrap(); + PointerFocusTarget::WlSurface { + surface, + toplevel: Some(window.into()), + } + } + KeyboardFocusTarget::Fullscreen(elem) => PointerFocusTarget::WlSurface { + surface: elem.wl_surface().unwrap(), + toplevel: Some(elem.into()), + }, + KeyboardFocusTarget::LayerSurface(layer) => PointerFocusTarget::WlSurface { + surface: layer.wl_surface().clone(), + toplevel: None, + }, + KeyboardFocusTarget::Popup(popup) => PointerFocusTarget::WlSurface { + surface: popup.wl_surface().clone(), + toplevel: Some(popup.into()), + }, + KeyboardFocusTarget::LockSurface(lock) => PointerFocusTarget::WlSurface { + surface: lock.wl_surface().clone(), + toplevel: None, + }, + _ => unreachable!("A group cannot start a popup grab"), } } } -impl TryFrom for KeyboardFocusTarget { - type Error = (); - fn try_from(target: PointerFocusTarget) -> Result { - match target { - PointerFocusTarget::Element(mapped) => Ok(KeyboardFocusTarget::Element(mapped)), - PointerFocusTarget::Fullscreen(surf) => Ok(KeyboardFocusTarget::Fullscreen(surf)), - PointerFocusTarget::LayerSurface(layer) => Ok(KeyboardFocusTarget::LayerSurface(layer)), - PointerFocusTarget::Popup(popup) => Ok(KeyboardFocusTarget::Popup(popup)), - PointerFocusTarget::LockSurface(lock) => Ok(KeyboardFocusTarget::LockSurface(lock)), - _ => Err(()), +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 { + surface: wl_surface, + toplevel: Some(surface.clone().into()), + }, + point, + ) + }), + WindowSurface::X11(x11_surface) => Some(( + Self::WlSurface { + surface: x11_surface.wl_surface()?, + toplevel: Some(surface.clone().into()), + }, + Point::default(), + )), + } + } + + pub fn toplevel(&self, data: &mut State) -> Option { + match &self { + PointerFocusTarget::WlSurface { + toplevel: Some(PointerFocusToplevel::Surface(surface)), + .. + } => Some(surface.clone()), + PointerFocusTarget::WlSurface { + toplevel: Some(PointerFocusToplevel::Popup(PopupKind::Xdg(popup))), + .. + } => get_popup_toplevel(popup) + .and_then(|s| { + data.common + .shell + .element_for_surface(&s) + .map(|mapped| (mapped, s)) + }) + .and_then(|(m, s)| { + m.windows() + .find(|(w, _)| w.wl_surface().map(|s2| s == s2).unwrap_or(false)) + .map(|(s, _)| s) + }), + PointerFocusTarget::StackUI(stack) => Some(stack.active()), + PointerFocusTarget::WindowUI(window) => Some(window.surface()), + _ => None, } } } @@ -100,13 +186,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 { surface, .. } => surface.alive(), + PointerFocusTarget::StackUI(e) => e.alive(), + PointerFocusTarget::WindowUI(e) => e.alive(), PointerFocusTarget::ResizeFork(f) => f.alive(), - PointerFocusTarget::LockSurface(l) => l.alive(), } } } @@ -125,113 +209,119 @@ impl IsAlive for KeyboardFocusTarget { } impl PointerTarget for PointerFocusTarget { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + if let Some(element) = self.toplevel(data) { + for session in element.cursor_sessions() { + session.set_cursor_pos(Some( + event + .location + .to_buffer(1.0, Transform::Normal, &element.geometry().size.to_f64()) + .to_i32_round(), + )); + if let Some((_, hotspot)) = seat + .cursor_geometry((0.0, 0.0), Duration::from_millis(event.time as u64).into()) + { + session.set_cursor_hotspot(hotspot); + } else { + session.set_cursor_hotspot((0, 0)); + } + } + } + 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::ResizeFork(f) => PointerTarget::enter(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::enter(l.wl_surface(), seat, data, event) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::enter(surface, 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), } } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + if let Some(element) = self.toplevel(data) { + for session in element.cursor_sessions() { + session.set_cursor_pos(Some( + event + .location + .to_buffer(1.0, Transform::Normal, &element.geometry().size.to_f64()) + .to_i32_round(), + )); + if let Some((_, hotspot)) = seat + .cursor_geometry((0.0, 0.0), Duration::from_millis(event.time as u64).into()) + { + session.set_cursor_hotspot(hotspot); + } else { + session.set_cursor_hotspot((0, 0)); + } + } + } + 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::WlSurface { surface, .. } => { + PointerTarget::motion(surface, seat, data, event) } - PointerFocusTarget::OverrideRedirect(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) => { - PointerTarget::relative_motion(s, seat, data, event) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::relative_motion(surface, 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::WlSurface { surface, .. } => { + PointerTarget::button(surface, seat, data, event) } - PointerFocusTarget::OverrideRedirect(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::ResizeFork(f) => PointerTarget::axis(f, seat, data, frame), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::axis(l.wl_surface(), seat, data, frame) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::axis(surface, 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), } } 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 { surface, .. } => { + PointerTarget::frame(surface, 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) + if let Some(element) = self.toplevel(data) { + for session in element.cursor_sessions() { + session.set_cursor_pos(None); + session.set_cursor_hotspot((0, 0)); } - PointerFocusTarget::Popup(p) => { - PointerTarget::leave(p.wl_surface(), seat, data, serial, time) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::leave(s, seat, data, serial, time) + } + + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::leave(surface, 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 +331,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::WlSurface { surface, .. } => { + PointerTarget::gesture_swipe_begin(surface, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_begin(l, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_begin(u, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_begin(p.wl_surface(), 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 +352,18 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeUpdateEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::gesture_swipe_update(surface, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_update(u, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_update(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_update(p.wl_surface(), 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 +373,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::WlSurface { surface, .. } => { + PointerTarget::gesture_swipe_end(surface, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_end(l, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_swipe_end(u, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_end(p.wl_surface(), 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 +394,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 { surface, .. } => { + PointerTarget::gesture_pinch_begin(surface, 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 +415,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::WlSurface { surface, .. } => { + PointerTarget::gesture_pinch_update(surface, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_update(l, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_pinch_update(u, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_update(p.wl_surface(), 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 +436,18 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchEndEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::gesture_pinch_end(surface, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_pinch_end(u, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_end(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_end(p.wl_surface(), 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 +457,118 @@ impl PointerTarget for PointerFocusTarget { event: &GestureHoldBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::gesture_hold_begin(surface, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) + PointerFocusTarget::StackUI(u) => { + PointerTarget::gesture_hold_begin(u, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_begin(l, seat, data, event) + PointerFocusTarget::WindowUI(u) => { + PointerTarget::gesture_hold_begin(u, seat, data, event) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_begin(p.wl_surface(), seat, data, event) + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_hold_begin(f, seat, data, event) + } + } + } + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + PointerTarget::gesture_hold_end(surface, seat, data, event) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_hold_begin(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_begin(f, seat, data, event) + PointerTarget::gesture_hold_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_begin(l.wl_surface(), seat, data, event) + } + } +} + +impl TouchTarget for PointerFocusTarget { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent, seq: Serial) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::down(surface, seat, data, event, seq) } + // TODO: implement TouchTarget for iced/CosmicWindow/CosmicStack/ResizeFork/Grabs + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} } } - fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent, seq: Serial) { 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::WlSurface { surface, .. } => { + TouchTarget::up(surface, seat, data, event, seq) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_end(l, seat, data, event) + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} + } + } + + fn motion(&self, seat: &Seat, data: &mut State, event: &TouchMotionEvent, seq: Serial) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::motion(surface, seat, data, event, seq) } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_end(p.wl_surface(), seat, data, event) + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} + } + } + + fn frame(&self, seat: &Seat, data: &mut State, seq: Serial) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::frame(surface, seat, data, seq) } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_hold_end(s, seat, data, event) + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} + } + } + + fn cancel(&self, seat: &Seat, data: &mut State, seq: Serial) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::cancel(surface, seat, data, seq) } - PointerFocusTarget::ResizeFork(f) => { - PointerTarget::gesture_hold_end(f, seat, data, event) + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} + } + } + + fn shape(&self, seat: &Seat, data: &mut State, event: &ShapeEvent, seq: Serial) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::shape(surface, seat, data, event, seq) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_end(l.wl_surface(), seat, data, event) + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} + } + } + + fn orientation( + &self, + seat: &Seat, + data: &mut State, + event: &OrientationEvent, + seq: Serial, + ) { + match self { + PointerFocusTarget::WlSurface { surface, .. } => { + TouchTarget::orientation(surface, seat, data, event, seq) } + PointerFocusTarget::WindowUI(_window) => {} + PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::ResizeFork(_fork) => {} } } } @@ -484,7 +588,7 @@ impl KeyboardTarget for KeyboardFocusTarget { } KeyboardFocusTarget::Group(_) => {} KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::enter(l, seat, data, keys, serial) + KeyboardTarget::enter(l.wl_surface(), seat, data, keys, serial) } KeyboardFocusTarget::Popup(p) => { KeyboardTarget::enter(p.wl_surface(), seat, data, keys, serial) @@ -499,7 +603,9 @@ impl KeyboardTarget for KeyboardFocusTarget { KeyboardFocusTarget::Element(w) => KeyboardTarget::leave(w, seat, data, serial), KeyboardFocusTarget::Fullscreen(w) => KeyboardTarget::leave(w, seat, data, serial), KeyboardFocusTarget::Group(_) => {} - KeyboardFocusTarget::LayerSurface(l) => KeyboardTarget::leave(l, seat, data, serial), + KeyboardFocusTarget::LayerSurface(l) => { + KeyboardTarget::leave(l.wl_surface(), seat, data, serial) + } KeyboardFocusTarget::Popup(p) => { KeyboardTarget::leave(p.wl_surface(), seat, data, serial) } @@ -526,7 +632,7 @@ impl KeyboardTarget for KeyboardFocusTarget { } KeyboardFocusTarget::Group(_) => {} KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::key(l, seat, data, key, state, serial, time) + KeyboardTarget::key(l.wl_surface(), seat, data, key, state, serial, time) } KeyboardFocusTarget::Popup(p) => { KeyboardTarget::key(p.wl_surface(), seat, data, key, state, serial, time) @@ -552,7 +658,7 @@ impl KeyboardTarget for KeyboardFocusTarget { } KeyboardFocusTarget::Group(_) => {} KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::modifiers(l, seat, data, modifiers, serial) + KeyboardTarget::modifiers(l.wl_surface(), seat, data, modifiers, serial) } KeyboardFocusTarget::Popup(p) => { KeyboardTarget::modifiers(p.wl_surface(), seat, data, modifiers, serial) @@ -590,59 +696,37 @@ 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 { surface, .. } => surface.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 { surface, .. } => surface.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(p: PopupKind) -> Self { - PointerFocusTarget::Popup(p) - } -} - -impl From for PointerFocusTarget { - fn from(s: X11Surface) -> Self { - PointerFocusTarget::OverrideRedirect(s) + PointerFocusTarget::WlSurface { + surface: p.wl_surface().clone(), + toplevel: None, + } } } @@ -654,7 +738,10 @@ impl From for PointerFocusTarget { impl From for PointerFocusTarget { fn from(l: LockSurface) -> Self { - PointerFocusTarget::LockSurface(l) + PointerFocusTarget::WlSurface { + surface: l.wl_surface().clone(), + toplevel: None, + } } } diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 345842e9..50a38bbe 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 7a9d1fb9..092879c5 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 f048af19..76e5c48d 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 0f610ed7..56e5529c 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 ecb0b935..86436185 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -490,15 +490,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/compositor.rs b/src/wayland/handlers/compositor.rs index fd9d5116..02e122d8 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -136,7 +136,7 @@ impl CompositorHandler for State { } } } - }) + }); } fn commit(&mut self, surface: &WlSurface) { diff --git a/src/wayland/handlers/seat.rs b/src/wayland/handlers/seat.rs index 6ef87138..f959e40e 100644 --- a/src/wayland/handlers/seat.rs +++ b/src/wayland/handlers/seat.rs @@ -19,6 +19,7 @@ use std::cell::RefCell; impl SeatHandler for State { type KeyboardFocus = KeyboardFocusTarget; type PointerFocus = PointerFocusTarget; + type TouchFocus = PointerFocusTarget; fn seat_state(&mut self) -> &mut SeatState { &mut self.common.seat_state diff --git a/src/wayland/handlers/xdg_shell/popup.rs b/src/wayland/handlers/xdg_shell/popup.rs index 6853874a..9f54aa1a 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()