Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

toplevel-drag: implement version 2 #286

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ fn start_compositor2(
cpu_worker,
ui_drag_enabled: Cell::new(true),
ui_drag_threshold_squared: Cell::new(10),
toplevel_drag_ids: Default::default(),
});
state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state);
Expand Down
4 changes: 3 additions & 1 deletion src/gfx_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,9 @@ pub fn create_render_pass(
renderer.render_highlight(&highlight.move_(-rect.x1(), -rect.y1()));
}
if let Some(drag) = seat.toplevel_drag() {
drag.render(&mut renderer, &rect, x, y);
if drag.enabled.get() {
drag.render(&mut renderer, &rect, x, y);
}
}
if let Some(dnd_icon) = seat.dnd_icon() {
dnd_icon.render(&mut renderer, &rect, x, y);
Expand Down
1 change: 0 additions & 1 deletion src/ifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ pub mod xdg_activation_token_v1;
pub mod xdg_activation_v1;
pub mod xdg_positioner;
pub mod xdg_toplevel_drag_manager_v1;
pub mod xdg_toplevel_drag_v1;
pub mod xdg_wm_base;
pub mod xdg_wm_dialog_v1;
pub mod zwlr_layer_shell_v1;
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/ipc/wl_data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use {
SOURCE_STATE_DROPPED,
},
wl_seat::WlSeatGlobal,
xdg_toplevel_drag_v1::XdgToplevelDragV1,
wl_surface::xdg_surface::xdg_toplevel::xdg_toplevel_drag_v1::XdgToplevelDragV1,
},
leaks::Tracker,
object::{Object, Version},
Expand Down
6 changes: 4 additions & 2 deletions src/ifs/wl_seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ use {
zwp_pointer_gesture_swipe_v1::ZwpPointerGestureSwipeV1,
zwp_relative_pointer_v1::ZwpRelativePointerV1,
},
wl_surface::{dnd_icon::DndIcon, WlSurface},
xdg_toplevel_drag_v1::XdgToplevelDragV1,
wl_surface::{
dnd_icon::DndIcon,
xdg_surface::xdg_toplevel::xdg_toplevel_drag_v1::XdgToplevelDragV1, WlSurface,
},
},
leaks::Tracker,
object::{Object, Version},
Expand Down
6 changes: 4 additions & 2 deletions src/ifs/wl_seat/pointer_owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use {
wl_pointer::PendingScroll, Dnd, DroppedDnd, NodeSeatState, WlSeatError,
WlSeatGlobal, BTN_LEFT, BTN_RIGHT, CHANGE_CURSOR_MOVED, CHANGE_TREE,
},
wl_surface::{dnd_icon::DndIcon, WlSurface},
xdg_toplevel_drag_v1::XdgToplevelDragV1,
wl_surface::{
dnd_icon::DndIcon,
xdg_surface::xdg_toplevel::xdg_toplevel_drag_v1::XdgToplevelDragV1, WlSurface,
},
},
rect::Rect,
tree::{
Expand Down
21 changes: 17 additions & 4 deletions src/ifs/wl_surface/xdg_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use {
wl_surface::{
xdg_surface::{
xdg_popup::{XdgPopup, XdgPopupError, XdgPopupParent},
xdg_toplevel::{XdgToplevel, WM_CAPABILITIES_SINCE},
xdg_toplevel::{
xdg_toplevel_drag_v1::ToplevelDragId, XdgToplevel, WM_CAPABILITIES_SINCE,
},
},
PendingState, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
},
Expand Down Expand Up @@ -141,6 +143,8 @@ impl XdgPopupParent for Popup {
#[derive(Default, Debug)]
pub struct PendingXdgSurfaceData {
geometry: Option<Rect>,
toplevel_drag_offset: Option<(i32, i32)>,
toplevel_drag_id: Option<ToplevelDragId>,
}

impl PendingXdgSurfaceData {
Expand All @@ -153,12 +157,18 @@ impl PendingXdgSurfaceData {
};
}
opt!(geometry);
opt!(toplevel_drag_offset);
opt!(toplevel_drag_id);
}
}

pub trait XdgSurfaceExt: Debug {
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
Ok(())
fn initial_configure(self: Rc<Self>) {
// nothing
}

fn before_apply_commit(self: Rc<Self>, pending: &mut PendingXdgSurfaceData) {
let _ = pending;
}

fn post_commit(self: Rc<Self>) {
Expand Down Expand Up @@ -493,7 +503,7 @@ impl SurfaceExt for XdgSurface {
) -> Result<(), WlSurfaceError> {
if !self.have_initial_commit.get() {
if let Some(ext) = self.ext.get() {
ext.initial_configure()?;
ext.initial_configure();
self.do_send_configure();
self.have_initial_commit.set(true);
}
Expand All @@ -509,6 +519,9 @@ impl SurfaceExt for XdgSurface {
}
}
}
if let Some(ext) = self.ext.get() {
ext.before_apply_commit(pending);
}
}
Ok(())
}
Expand Down
5 changes: 2 additions & 3 deletions src/ifs/wl_surface/xdg_surface/xdg_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use {
fixed::Fixed,
ifs::{
wl_seat::{tablet::TabletTool, NodeSeatState, WlSeatGlobal},
wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt},
wl_surface::xdg_surface::{XdgSurface, XdgSurfaceExt},
xdg_positioner::{
XdgPositioned, XdgPositioner, CA_FLIP_X, CA_FLIP_Y, CA_RESIZE_X, CA_RESIZE_Y,
CA_SLIDE_X, CA_SLIDE_Y,
Expand Down Expand Up @@ -374,13 +374,12 @@ impl StackedNode for XdgPopup {
}

impl XdgSurfaceExt for XdgPopup {
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
fn initial_configure(self: Rc<Self>) {
if let Some(parent) = self.parent.get() {
self.update_position(&*parent);
let rel = self.relative_position.get();
self.send_configure(rel.x1(), rel.y1(), rel.width(), rel.height());
}
Ok(())
}

fn post_commit(self: Rc<Self>) {
Expand Down
36 changes: 32 additions & 4 deletions src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod xdg_dialog_v1;
pub mod xdg_toplevel_drag_v1;

use {
crate::{
Expand All @@ -12,12 +13,11 @@ use {
wl_seat::{tablet::TabletTool, NodeSeatState, SeatId, WlSeatGlobal},
wl_surface::{
xdg_surface::{
xdg_toplevel::xdg_dialog_v1::XdgDialogV1, XdgSurface, XdgSurfaceError,
xdg_toplevel::xdg_dialog_v1::XdgDialogV1, PendingXdgSurfaceData, XdgSurface,
XdgSurfaceExt,
},
WlSurface,
},
xdg_toplevel_drag_v1::XdgToplevelDragV1,
},
leaks::Tracker,
object::{Object, Version},
Expand All @@ -41,6 +41,7 @@ use {
rc::Rc,
},
thiserror::Error,
xdg_toplevel_drag_v1::XdgToplevelDragV1,
};

#[derive(Copy, Clone, Debug, FromPrimitive)]
Expand Down Expand Up @@ -681,14 +682,41 @@ impl ToplevelNodeBase for XdgToplevel {
}

impl XdgSurfaceExt for XdgToplevel {
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
fn initial_configure(self: Rc<Self>) {
let rect = self.xdg.absolute_desired_extents.get();
if rect.is_empty() {
self.send_configure(0, 0);
} else {
self.send_configure_checked(rect.width(), rect.height());
}
Ok(())
}

fn before_apply_commit(self: Rc<Self>, pending: &mut PendingXdgSurfaceData) {
if let Some((x_off, y_off)) = pending.toplevel_drag_offset.take() {
if let Some(drag) = self.drag.get() {
if drag.is_ongoing() {
if self.node_visible() {
self.xdg.damage();
}
let extents = self.xdg.absolute_desired_extents.get();
let extents = extents.move_(drag.x_off.get() - x_off, drag.y_off.get() - y_off);
self.clone().tl_change_extents(&extents);
if self.node_visible() {
self.xdg.damage();
}
}
drag.x_off.set(x_off);
drag.y_off.set(y_off);
}
}
if let Some(id) = pending.toplevel_drag_id.take() {
if let Some(drag) = self.drag.get() {
if id == drag.toplevel_id.get() {
drag.enabled.set(true);
drag.start_drag();
}
}
}
}

fn post_commit(self: Rc<Self>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,48 @@ use {
thiserror::Error,
};

fn clamp_offset(offset: i32) -> i32 {
const OFFSET_CLAMP: i32 = 100_000;
offset.clamp(-OFFSET_CLAMP, OFFSET_CLAMP)
}

const SET_OFFSET_SINCE: Version = Version(2);

linear_ids!(ToplevelDragIds, ToplevelDragId, u64);

pub struct XdgToplevelDragV1 {
pub id: XdgToplevelDragV1Id,
pub toplevel_id: Cell<ToplevelDragId>,
pub client: Rc<Client>,
pub source: Rc<WlDataSource>,
pub tracker: Tracker<Self>,
pub toplevel: CloneCell<Option<Rc<XdgToplevel>>>,
pub x_off: Cell<i32>,
pub y_off: Cell<i32>,
pub version: Version,
pub enabled: Cell<bool>,
}

impl XdgToplevelDragV1 {
pub fn new(id: XdgToplevelDragV1Id, source: &Rc<WlDataSource>, version: Version) -> Self {
Self {
id,
toplevel_id: Cell::new(source.data.client.state.toplevel_drag_ids.next()),
client: source.data.client.clone(),
source: source.clone(),
tracker: Default::default(),
toplevel: Default::default(),
x_off: Cell::new(0),
y_off: Cell::new(0),
version,
enabled: Cell::new(true),
}
}

pub fn is_ongoing(&self) -> bool {
self.source.data.was_used() && !self.source.data.was_dropped_or_cancelled()
self.enabled.get()
&& self.source.data.was_used()
&& !self.source.data.was_dropped_or_cancelled()
}

fn detach(&self) {
Expand Down Expand Up @@ -101,17 +116,37 @@ impl XdgToplevelDragV1RequestHandler for XdgToplevelDragV1 {
if toplevel.drag.set(Some(slf.clone())).is_some() {
return Err(XdgToplevelDragV1Error::AlreadyDragged);
}
if let Some(prev) = self.toplevel.set(Some(toplevel)) {
if let Some(prev) = self.toplevel.set(Some(toplevel.clone())) {
if prev.xdg.surface.buffer.is_some() {
return Err(XdgToplevelDragV1Error::ToplevelAttached);
}
if prev.id != req.toplevel {
prev.drag.set(None);
}
}
self.x_off.set(req.x_offset);
self.y_off.set(req.y_offset);
self.start_drag();
let x_off = clamp_offset(req.x_offset);
let y_off = clamp_offset(req.y_offset);
if self.version >= SET_OFFSET_SINCE {
let id = self.client.state.toplevel_drag_ids.next();
self.toplevel_id.set(id);
self.enabled.set(false);
let pending = &mut *toplevel.xdg.pending();
pending.toplevel_drag_id = Some(id);
pending.toplevel_drag_offset = Some((x_off, y_off));
} else {
self.x_off.set(x_off);
self.y_off.set(y_off);
self.start_drag();
}
Ok(())
}

fn set_offset(&self, req: SetOffset, _slf: &Rc<Self>) -> Result<(), Self::Error> {
if let Some(tl) = self.toplevel.get() {
let x_off = clamp_offset(req.x_offset);
let y_off = clamp_offset(req.y_offset);
tl.xdg.pending().toplevel_drag_offset = Some((x_off, y_off));
}
Ok(())
}
}
Expand All @@ -133,7 +168,7 @@ impl XdgToplevelDragV1 {
}

pub fn finish_drag(&self, seat: &Rc<WlSeatGlobal>) {
if self.source.data.was_used() {
if self.enabled.get() && self.source.data.was_used() {
if let Some(tl) = self.toplevel.get() {
let output = seat.get_output();
let (x, y) = seat.pointer_cursor().position();
Expand Down
4 changes: 2 additions & 2 deletions src/ifs/xdg_toplevel_drag_manager_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {
crate::{
client::{Client, ClientError},
globals::{Global, GlobalName},
ifs::xdg_toplevel_drag_v1::XdgToplevelDragV1,
ifs::wl_surface::xdg_surface::xdg_toplevel::xdg_toplevel_drag_v1::XdgToplevelDragV1,
leaks::Tracker,
object::{Object, Version},
wire::{xdg_toplevel_drag_manager_v1::*, XdgToplevelDragManagerV1Id},
Expand Down Expand Up @@ -52,7 +52,7 @@ impl Global for XdgToplevelDragManagerV1Global {
}

fn version(&self) -> u32 {
1
2
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use {
},
wl_surface::{
wl_subsurface::SubsurfaceIds,
xdg_surface::xdg_toplevel::xdg_toplevel_drag_v1::ToplevelDragIds,
zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1},
zwp_input_popup_surface_v2::ZwpInputPopupSurfaceV2,
NoneSurfaceExt,
Expand Down Expand Up @@ -220,6 +221,7 @@ pub struct State {
pub cpu_worker: Rc<CpuWorker>,
pub ui_drag_enabled: Cell<bool>,
pub ui_drag_threshold_squared: Cell<i32>,
pub toplevel_drag_ids: ToplevelDragIds,
}

// impl Drop for State {
Expand Down
5 changes: 5 additions & 0 deletions wire/xdg_toplevel_drag_v1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ request attach {
x_offset: i32,
y_offset: i32,
}

request set_offset (since = 2) {
x_offset: i32,
y_offset: i32,
}
Loading