From af15e20e9b883b7fdc7f9ff3872da0b9ca621f94 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 10 Jul 2024 19:43:54 +0200 Subject: [PATCH] wl_surface: move dnd logic to separate module --- src/gfx_api.rs | 9 +----- src/ifs/ipc/wl_data_device.rs | 5 ++- src/ifs/wl_seat.rs | 12 +++---- src/ifs/wl_seat/pointer_owner.rs | 26 +++++++-------- src/ifs/wl_surface.rs | 31 +++++++++--------- src/ifs/wl_surface/dnd_icon.rs | 55 ++++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 src/ifs/wl_surface/dnd_icon.rs diff --git a/src/gfx_api.rs b/src/gfx_api.rs index ec622241..51027c19 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -370,14 +370,7 @@ impl dyn GfxFramebuffer { } } if let Some(dnd_icon) = seat.dnd_icon() { - let extents = dnd_icon.extents.get().move_( - x.round_down() + dnd_icon.buf_x.get(), - y.round_down() + dnd_icon.buf_y.get(), - ); - if extents.intersects(&rect) { - let (x, y) = rect.translate(extents.x1(), extents.y1()); - renderer.render_surface(&dnd_icon, x, y, None); - } + dnd_icon.render(&mut renderer, &rect, x.round_down(), y.round_down()); } if render_cursor { let cursor_user_group = seat.cursor_group(); diff --git a/src/ifs/ipc/wl_data_device.rs b/src/ifs/ipc/wl_data_device.rs index 772438bd..5362dbc8 100644 --- a/src/ifs/ipc/wl_data_device.rs +++ b/src/ifs/ipc/wl_data_device.rs @@ -9,7 +9,7 @@ use { IterableIpcVtable, OfferData, Role, }, wl_seat::{WlSeatError, WlSeatGlobal}, - wl_surface::{SurfaceRole, WlSurfaceError}, + wl_surface::WlSurfaceError, }, leaks::Tracker, object::{Object, Version}, @@ -115,8 +115,7 @@ impl WlDataDeviceRequestHandler for WlDataDevice { }; let icon = if req.icon.is_some() { let icon = self.client.lookup(req.icon)?; - icon.set_role(SurfaceRole::DndIcon)?; - Some(icon) + Some(icon.into_dnd_icon(&self.seat)?) } else { None }; diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index d165878b..08847360 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -61,7 +61,7 @@ use { zwp_pointer_gesture_swipe_v1::ZwpPointerGestureSwipeV1, zwp_relative_pointer_v1::ZwpRelativePointerV1, }, - wl_surface::WlSurface, + wl_surface::{dnd_icon::DndIcon, WlSurface}, xdg_toplevel_drag_v1::XdgToplevelDragV1, }, leaks::Tracker, @@ -723,11 +723,11 @@ impl WlSeatGlobal { self: &Rc, origin: &Rc, source: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { if let Some(icon) = &icon { - icon.set_output(&self.pointer_cursor.output()); + icon.surface().set_output(&self.pointer_cursor.output()); } self.pointer_owner .start_drag(self, origin, source, icon, serial) @@ -819,7 +819,7 @@ impl WlSeatGlobal { self.primary_selection.get() } - pub fn dnd_icon(&self) -> Option> { + pub fn dnd_icon(&self) -> Option> { self.pointer_owner.dnd_icon() } @@ -926,7 +926,7 @@ impl WlSeatGlobal { pub fn set_visible(&self, visible: bool) { self.cursor_user_group.set_visible(visible); if let Some(icon) = self.dnd_icon() { - icon.set_visible(visible); + icon.surface().set_visible(visible); } if let Some(tl_drag) = self.toplevel_drag() { if let Some(tl) = tl_drag.toplevel.get() { @@ -965,7 +965,7 @@ impl WlSeatGlobal { impl CursorUserOwner for WlSeatGlobal { fn output_changed(&self, output: &Rc) { if let Some(dnd) = self.pointer_owner.dnd_icon() { - dnd.set_output(output); + dnd.surface().set_output(output); } if let Some(drag) = self.pointer_owner.toplevel_drag() { if let Some(tl) = drag.toplevel.get() { diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index ed815ce5..5a436f2a 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -10,7 +10,7 @@ use { wl_pointer::PendingScroll, Dnd, DroppedDnd, WlSeatError, WlSeatGlobal, BTN_LEFT, BTN_RIGHT, CHANGE_CURSOR_MOVED, CHANGE_TREE, }, - wl_surface::WlSurface, + wl_surface::{dnd_icon::DndIcon, WlSurface}, xdg_toplevel_drag_v1::XdgToplevelDragV1, }, state::DeviceHandlerData, @@ -120,7 +120,7 @@ impl PointerOwnerHolder { seat: &Rc, origin: &Rc, source: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { self.owner @@ -144,7 +144,7 @@ impl PointerOwnerHolder { self.owner.get().dnd_target_removed(seat); } - pub fn dnd_icon(&self) -> Option> { + pub fn dnd_icon(&self) -> Option> { self.owner.get().dnd_icon() } @@ -211,7 +211,7 @@ trait PointerOwner { seat: &Rc, origin: &Rc, source: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { let _ = origin; @@ -232,7 +232,7 @@ trait PointerOwner { fn dnd_target_removed(&self, seat: &Rc) { self.cancel_dnd(seat); } - fn dnd_icon(&self) -> Option> { + fn dnd_icon(&self) -> Option> { None } fn toplevel_drag(&self) -> Option> { @@ -264,7 +264,7 @@ struct DndPointerOwner { button: u32, dnd: Dnd, target: CloneCell>, - icon: CloneCell>>, + icon: CloneCell>>, pos_x: Cell, pos_y: Cell, } @@ -446,7 +446,7 @@ impl PointerOwner for SimpleGrabPointerOwner { seat: &Rc, origin: &Rc, src: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { self.usecase @@ -486,7 +486,7 @@ impl PointerOwner for DndPointerOwner { } } if let Some(icon) = self.icon.get() { - icon.set_dnd_icon_seat(seat.id(), None); + icon.disable(); } seat.pointer_owner.set_default_pointer_owner(seat); seat.tree_changed.trigger(); @@ -542,7 +542,7 @@ impl PointerOwner for DndPointerOwner { ipc::detach_seat(&**src, seat); } if let Some(icon) = self.icon.get() { - icon.set_dnd_icon_seat(seat.id(), None); + icon.disable(); } seat.pointer_owner.set_default_pointer_owner(seat); seat.tree_changed.trigger(); @@ -558,7 +558,7 @@ impl PointerOwner for DndPointerOwner { seat.state.tree_changed(); } - fn dnd_icon(&self) -> Option> { + fn dnd_icon(&self) -> Option> { self.icon.get() } @@ -593,7 +593,7 @@ trait SimplePointerOwnerUsecase: Sized + Clone + 'static { seat: &Rc, origin: &Rc, src: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { let _ = grab; @@ -638,7 +638,7 @@ impl SimplePointerOwnerUsecase for DefaultPointerUsecase { seat: &Rc, origin: &Rc, src: Option>, - icon: Option>, + icon: Option>, serial: u32, ) -> Result<(), WlSeatError> { let button = match grab.buttons.iter().next() { @@ -655,7 +655,7 @@ impl SimplePointerOwnerUsecase for DefaultPointerUsecase { return Ok(()); } if let Some(icon) = &icon { - icon.set_dnd_icon_seat(seat.id, Some(seat)); + icon.enable(); } if let Some(new) = &src { ipc::attach_seat(&**new, seat, ipc::Role::Dnd)?; diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 9bb58ca4..1e66b20d 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1,5 +1,6 @@ pub mod commit_timeline; pub mod cursor; +pub mod dnd_icon; pub mod ext_session_lock_surface_v1; pub mod wl_subsurface; pub mod wp_alpha_modifier_surface_v1; @@ -41,6 +42,7 @@ use { wl_surface::{ commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError}, cursor::CursorSurface, + dnd_icon::DndIcon, wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface}, wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1, wp_fractional_scale_v1::WpFractionalScaleV1, @@ -273,7 +275,7 @@ pub struct WlSurface { seat_state: NodeSeatState, toplevel: CloneCell>>, cursors: SmallMap, 1>, - dnd_icons: SmallMap, 1>, + dnd_icons: SmallMap, 1>, pub tracker: Tracker, idle_inhibitors: SmallMap, 1>, viewporter: CloneCell>>, @@ -758,6 +760,17 @@ impl WlSurface { Ok(()) } + pub fn into_dnd_icon( + self: &Rc, + seat: &Rc, + ) -> Result, WlSurfaceError> { + self.set_role(SurfaceRole::DndIcon)?; + Ok(Rc::new(DndIcon { + surface: self.clone(), + seat: seat.clone(), + })) + } + fn unset_ext(&self) { self.ext.set(self.client.state.none_surface_ext.clone()); } @@ -806,8 +819,8 @@ impl WlSurface { } fn unset_dnd_icons(&self) { - while let Some((_, seat)) = self.dnd_icons.pop() { - seat.remove_dnd_icon() + while let Some((_, dnd_icon)) = self.dnd_icons.pop() { + dnd_icon.seat.remove_dnd_icon(); } } } @@ -1349,18 +1362,6 @@ impl WlSurface { .consume_pending_child(self, child, &mut consume) } - pub fn set_dnd_icon_seat(&self, id: SeatId, seat: Option<&Rc>) { - match seat { - None => { - self.dnd_icons.remove(&id); - } - Some(seat) => { - self.dnd_icons.insert(id, seat.clone()); - } - } - self.set_visible(self.dnd_icons.is_not_empty() && self.client.state.root_visible()); - } - pub fn alpha(&self) -> Option { self.alpha.get() } diff --git a/src/ifs/wl_surface/dnd_icon.rs b/src/ifs/wl_surface/dnd_icon.rs new file mode 100644 index 00000000..e41f11aa --- /dev/null +++ b/src/ifs/wl_surface/dnd_icon.rs @@ -0,0 +1,55 @@ +use { + crate::{ + ifs::{wl_seat::WlSeatGlobal, wl_surface::WlSurface}, + rect::Rect, + renderer::Renderer, + }, + std::rc::Rc, +}; + +pub struct DndIcon { + pub(super) surface: Rc, + pub(super) seat: Rc, +} + +impl DndIcon { + pub fn surface(&self) -> &Rc { + &self.surface + } + + fn update_visible(&self) { + let is_visible = + self.surface.dnd_icons.is_not_empty() && self.surface.client.state.root_visible(); + self.surface.set_visible(is_visible); + } + + pub fn enable(self: &Rc) { + self.surface.dnd_icons.insert(self.seat.id(), self.clone()); + self.update_visible(); + } + + pub fn disable(self: &Rc) { + self.surface.dnd_icons.remove(&self.seat.id()); + self.update_visible(); + } + + pub fn surface_position(&self, seat_x: i32, seat_y: i32) -> (i32, i32) { + ( + seat_x + self.surface.buf_x.get(), + seat_y + self.surface.buf_y.get(), + ) + } + + fn extents(&self, x: i32, y: i32) -> Rect { + let (x, y) = self.surface_position(x, y); + self.surface.extents.get().move_(x, y) + } + + pub fn render(&self, renderer: &mut Renderer<'_>, cursor_rect: &Rect, x: i32, y: i32) { + let extents = self.extents(x, y); + if extents.intersects(&cursor_rect) { + let (x, y) = cursor_rect.translate(extents.x1(), extents.y1()); + renderer.render_surface(&self.surface, x, y, None); + } + } +}