1
0
Fork 0
forked from wry/wry

wl_surface: move dnd logic to separate module

This commit is contained in:
Julian Orth 2024-07-10 19:43:54 +02:00
parent f871ea1d67
commit af15e20e9b
6 changed files with 93 additions and 45 deletions

View file

@ -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();

View file

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

View file

@ -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<Self>,
origin: &Rc<WlSurface>,
source: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
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<Rc<WlSurface>> {
pub fn dnd_icon(&self) -> Option<Rc<DndIcon>> {
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<OutputNode>) {
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() {

View file

@ -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<WlSeatGlobal>,
origin: &Rc<WlSurface>,
source: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
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<Rc<WlSurface>> {
pub fn dnd_icon(&self) -> Option<Rc<DndIcon>> {
self.owner.get().dnd_icon()
}
@ -211,7 +211,7 @@ trait PointerOwner {
seat: &Rc<WlSeatGlobal>,
origin: &Rc<WlSurface>,
source: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
serial: u32,
) -> Result<(), WlSeatError> {
let _ = origin;
@ -232,7 +232,7 @@ trait PointerOwner {
fn dnd_target_removed(&self, seat: &Rc<WlSeatGlobal>) {
self.cancel_dnd(seat);
}
fn dnd_icon(&self) -> Option<Rc<WlSurface>> {
fn dnd_icon(&self) -> Option<Rc<DndIcon>> {
None
}
fn toplevel_drag(&self) -> Option<Rc<XdgToplevelDragV1>> {
@ -264,7 +264,7 @@ struct DndPointerOwner {
button: u32,
dnd: Dnd,
target: CloneCell<Rc<dyn Node>>,
icon: CloneCell<Option<Rc<WlSurface>>>,
icon: CloneCell<Option<Rc<DndIcon>>>,
pos_x: Cell<Fixed>,
pos_y: Cell<Fixed>,
}
@ -446,7 +446,7 @@ impl<T: SimplePointerOwnerUsecase> PointerOwner for SimpleGrabPointerOwner<T> {
seat: &Rc<WlSeatGlobal>,
origin: &Rc<WlSurface>,
src: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
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<Rc<WlSurface>> {
fn dnd_icon(&self) -> Option<Rc<DndIcon>> {
self.icon.get()
}
@ -593,7 +593,7 @@ trait SimplePointerOwnerUsecase: Sized + Clone + 'static {
seat: &Rc<WlSeatGlobal>,
origin: &Rc<WlSurface>,
src: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
serial: u32,
) -> Result<(), WlSeatError> {
let _ = grab;
@ -638,7 +638,7 @@ impl SimplePointerOwnerUsecase for DefaultPointerUsecase {
seat: &Rc<WlSeatGlobal>,
origin: &Rc<WlSurface>,
src: Option<Rc<WlDataSource>>,
icon: Option<Rc<WlSurface>>,
icon: Option<Rc<DndIcon>>,
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)?;

View file

@ -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<Option<Rc<dyn ToplevelNode>>>,
cursors: SmallMap<CursorUserId, Rc<CursorSurface>, 1>,
dnd_icons: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
dnd_icons: SmallMap<SeatId, Rc<DndIcon>, 1>,
pub tracker: Tracker<Self>,
idle_inhibitors: SmallMap<ZwpIdleInhibitorV1Id, Rc<ZwpIdleInhibitorV1>, 1>,
viewporter: CloneCell<Option<Rc<WpViewport>>>,
@ -758,6 +760,17 @@ impl WlSurface {
Ok(())
}
pub fn into_dnd_icon(
self: &Rc<Self>,
seat: &Rc<WlSeatGlobal>,
) -> Result<Rc<DndIcon>, 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<WlSeatGlobal>>) {
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<f32> {
self.alpha.get()
}

View file

@ -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<WlSurface>,
pub(super) seat: Rc<WlSeatGlobal>,
}
impl DndIcon {
pub fn surface(&self) -> &Rc<WlSurface> {
&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>) {
self.surface.dnd_icons.insert(self.seat.id(), self.clone());
self.update_visible();
}
pub fn disable(self: &Rc<Self>) {
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);
}
}
}