Skip to content
Merged
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
35 changes: 33 additions & 2 deletions src/backend/wayland/handlers/pointer/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use log::warn;
use smithay_client_toolkit::seat::pointer::CursorIcon;
use wayland_client::Connection;
use smithay_client_toolkit::seat::pointer::{CursorIcon, PointerData};
use wayland_client::{Connection, Proxy};

use super::*;
use crate::backend::wayland::toolbar::ToolbarCursorHint;
Expand All @@ -11,6 +11,15 @@ use crate::input::{

impl WaylandState {
pub(super) fn update_pointer_cursor(&mut self, toolbar_hover: bool, conn: &Connection) {
if self.toolbar_dragging() && self.pointer_lock_active() {
self.hide_pointer_cursor();
return;
}

if self.cursor_hidden {
self.cursor_hidden = false;
self.current_pointer_shape = None;
}
let icon = self.compute_cursor_icon(toolbar_hover);
if let Some(pointer) = self.themed_pointer.as_ref()
&& self.current_pointer_shape != Some(icon)
Expand Down Expand Up @@ -100,6 +109,10 @@ impl WaylandState {
}
}

if self.toolbar_dragging() {
return CursorIcon::Grabbing;
}

// Inline toolbar cursor hints (when using inline mode)
if self.inline_toolbars_active()
&& self.pointer_over_toolbar()
Expand Down Expand Up @@ -198,4 +211,22 @@ impl WaylandState {
// Default: crosshair for drawing
CursorIcon::Crosshair
}

pub(in crate::backend::wayland) fn hide_pointer_cursor(&mut self) {
if self.cursor_hidden {
return;
}
let Some(pointer) = self.current_pointer() else {
return;
};
let serial = pointer
.data::<PointerData>()
.and_then(|data| data.latest_button_serial().or(data.latest_enter_serial()));
let Some(serial) = serial else {
return;
};
pointer.set_cursor(serial, None, 0, 0);
self.cursor_hidden = true;
self.current_pointer_shape = None;
}
}
1 change: 1 addition & 0 deletions src/backend/wayland/handlers/pointer/enter_leave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,6 @@ impl WaylandState {
self.end_toolbar_move_drag();
}
self.current_pointer_shape = None;
self.cursor_hidden = false;
}
}
5 changes: 5 additions & 0 deletions src/backend/wayland/handlers/pointer/motion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use log::debug;
use smithay_client_toolkit::seat::pointer::PointerEvent;
use wayland_client::Connection;

use crate::backend::wayland::state::drag_log;
use crate::backend::wayland::toolbar_intent::intent_to_event;

use super::*;
Expand All @@ -17,6 +18,10 @@ impl WaylandState {
if self.is_move_dragging()
&& let Some(kind) = self.active_move_drag_kind()
{
drag_log(format!(
"pointer motion: drag_active kind={:?}, pos=({:.3}, {:.3}), on_toolbar={}, inline_active={}",
kind, event.position.0, event.position.1, on_toolbar, inline_active
));
debug!(
"Move drag motion: kind={:?}, pos=({}, {}), on_toolbar={}",
kind, event.position.0, event.position.1, on_toolbar
Expand Down
23 changes: 18 additions & 5 deletions src/backend/wayland/handlers/pointer/press.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use log::debug;
use smithay_client_toolkit::seat::pointer::{BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, PointerEvent};
use wayland_client::QueueHandle;

use crate::backend::wayland::state::drag_log;
use crate::backend::wayland::toolbar_intent::intent_to_event;
use crate::input::MouseButton;
use crate::ui::toolbar::ToolbarEvent;
Expand Down Expand Up @@ -49,11 +50,23 @@ impl WaylandState {
self.is_move_dragging()
);
}
if inline_active
&& ((button == BTN_LEFT && self.inline_toolbar_press(event.position))
|| self.pointer_over_toolbar())
{
return;
if inline_active {
if button == BTN_LEFT && self.inline_toolbar_press(event.position) {
drag_log(format!(
"pointer press: inline handled, drag_active={}, pos=({:.3}, {:.3}), surface={}",
self.toolbar_dragging(),
event.position.0,
event.position.1,
surface_id(&event.surface)
));
if self.toolbar_dragging() {
self.lock_pointer_for_drag(qh, &event.surface);
}
return;
}
if self.pointer_over_toolbar() {
return;
}
}
if on_toolbar {
if button == BTN_LEFT
Expand Down
26 changes: 26 additions & 0 deletions src/backend/wayland/handlers/pointer/release.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use log::debug;
use smithay_client_toolkit::seat::pointer::{BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, PointerEvent};

use crate::backend::wayland::state::drag_log;
use crate::input::MouseButton;

use super::*;
Expand Down Expand Up @@ -37,10 +38,24 @@ impl WaylandState {
}
if inline_active {
if button == BTN_LEFT && self.inline_toolbar_release(event.position) {
drag_log(format!(
"pointer release: inline handled, pos=({:.3}, {:.3}), drag_active={}, pointer_over_toolbar={}",
event.position.0,
event.position.1,
self.is_move_dragging(),
self.pointer_over_toolbar()
));
self.unlock_pointer();
return;
}
if self.pointer_over_toolbar() || self.toolbar_dragging() {
drag_log(format!(
"pointer release: inline end drag, pos=({:.3}, {:.3}), drag_active={}, pointer_over_toolbar={}",
event.position.0,
event.position.1,
self.is_move_dragging(),
self.pointer_over_toolbar()
));
self.end_toolbar_move_drag();
self.unlock_pointer();
return;
Expand All @@ -50,13 +65,24 @@ impl WaylandState {
if button == BTN_LEFT {
self.set_toolbar_dragging(false);
}
drag_log(format!(
"pointer release: toolbar end drag, pos=({:.3}, {:.3}), drag_active={}, pointer_over_toolbar={}",
event.position.0,
event.position.1,
self.is_move_dragging(),
self.pointer_over_toolbar()
));
self.end_toolbar_move_drag();
self.unlock_pointer();
return;
}
// End move drag if released on the main surface
if button == BTN_LEFT && self.is_move_dragging() {
self.set_toolbar_dragging(false);
drag_log(format!(
"pointer release: main surface end drag, pos=({:.3}, {:.3})",
event.position.0, event.position.1
));
self.end_toolbar_move_drag();
self.unlock_pointer();
return;
Expand Down
2 changes: 2 additions & 0 deletions src/backend/wayland/handlers/seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ impl SeatHandler for WaylandState {
debug!("Pointer initialized with theme");
self.themed_pointer = Some(pointer);
self.current_pointer_shape = None;
self.cursor_hidden = false;
}
Err(err) => {
warn!("Pointer initialized without theme: {}", err);
Expand Down Expand Up @@ -76,6 +77,7 @@ impl SeatHandler for WaylandState {
info!("Pointer capability removed");
self.themed_pointer = None;
self.current_pointer_shape = None;
self.cursor_hidden = false;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/backend/wayland/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type ScreencopyManager = wayland_protocols_wlr::screencopy::v1::client::zwlr_scr
pub(super) use helpers::{
damage_summary, debug_damage_logging_enabled, debug_toolbar_drag_logging_enabled, drag_log,
force_inline_toolbars_requested, scale_damage_regions, surface_id,
toolbar_drag_preview_enabled, toolbar_pointer_lock_enabled,
toolbar_drag_preview_enabled, toolbar_drag_throttle_interval, toolbar_pointer_lock_enabled,
};

pub(in crate::backend::wayland) struct WaylandGlobals {
Expand Down Expand Up @@ -175,6 +175,7 @@ pub(super) struct WaylandState {
pub(super) locked_pointer: Option<ZwpLockedPointerV1>,
pub(super) current_pointer_shape: Option<CursorIcon>,
pub(super) relative_pointer: Option<ZwpRelativePointerV1>,
pub(super) cursor_hidden: bool,

// Tablet / stylus (feature-gated)
#[cfg(tablet)]
Expand Down
1 change: 1 addition & 0 deletions src/backend/wayland/state/core/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl WaylandState {
current_pointer_shape: None,
locked_pointer: None,
relative_pointer: None,
cursor_hidden: false,
#[cfg(tablet)]
tablet_manager,
#[cfg(tablet)]
Expand Down
4 changes: 4 additions & 0 deletions src/backend/wayland/state/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub struct StateData {
pub(super) active_drag_kind: Option<MoveDragKind>,
pub(super) drag_top_base_x: Option<f64>,
pub(super) drag_top_base_y: Option<f64>,
pub(super) toolbar_drag_pending_apply: bool,
pub(super) last_toolbar_drag_apply: Option<Instant>,
pub(super) pending_activation_token: Option<String>,
pub(super) pending_freeze_on_start: bool,
pub(super) frozen_enabled: bool,
Expand Down Expand Up @@ -119,6 +121,8 @@ impl StateData {
active_drag_kind: None,
drag_top_base_x: None,
drag_top_base_y: None,
toolbar_drag_pending_apply: false,
last_toolbar_drag_apply: None,
pending_activation_token: None,
pending_freeze_on_start: false,
frozen_enabled: false,
Expand Down
22 changes: 21 additions & 1 deletion src/backend/wayland/state/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::OnceLock;
use std::{sync::OnceLock, time::Duration};

use wayland_client::{Proxy, protocol::wl_surface};

Expand Down Expand Up @@ -106,6 +106,26 @@ pub(in crate::backend::wayland) fn toolbar_drag_preview_enabled() -> bool {
})
}

pub(in crate::backend::wayland) fn toolbar_drag_throttle_interval() -> Option<Duration> {
static VALUE: OnceLock<Option<Duration>> = OnceLock::new();
*VALUE.get_or_init(|| {
let raw =
std::env::var("WAYSCRIBER_TOOLBAR_DRAG_THROTTLE_MS").unwrap_or_else(|_| "12".into());
let trimmed = raw.trim();
if trimmed.is_empty() {
return Some(Duration::from_millis(12));
}
let Ok(ms) = trimmed.parse::<u64>() else {
return Some(Duration::from_millis(12));
};
if ms == 0 {
None
} else {
Some(Duration::from_millis(ms))
}
})
}

pub(in crate::backend::wayland) fn drag_log(message: impl AsRef<str>) {
if debug_toolbar_drag_logging_enabled() {
log::info!("{}", message.as_ref());
Expand Down
19 changes: 16 additions & 3 deletions src/backend/wayland/state/toolbar/drag/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,32 @@ impl WaylandState {
let top_size = top_size(snapshot);
let side_start_y = Self::SIDE_BASE_MARGIN_TOP + self.data.toolbar_side_offset;
let top_bottom_y = Self::INLINE_TOP_Y + self.data.toolbar_top_offset_y + top_size.1 as f64;
let base = Self::INLINE_SIDE_X + self.data.toolbar_side_offset_x;
let base = Self::INLINE_SIDE_X;
// When dragging the side toolbar, don't push the top bar; keep its base stable so it
// doesn't shift while moving the side bar.
let allow_push = self.active_move_drag_kind() != Some(MoveDragKind::Side);
geometry::compute_inline_top_base_x(
let result = geometry::compute_inline_top_base_x(
base,
side_visible,
side_size.0 as f64,
side_start_y,
top_bottom_y,
Self::INLINE_TOP_PUSH,
allow_push,
)
);
if self.is_move_dragging() || self.toolbar_dragging() {
drag_log(format!(
"inline_top_base_x: base={:.3}, side_visible={}, side_width={:.3}, side_start_y={:.3}, top_bottom_y={:.3}, allow_push={}, result={:.3}",
base,
side_visible,
side_size.0 as f64,
side_start_y,
top_bottom_y,
allow_push,
result
));
}
result
}

pub(in crate::backend::wayland::state::toolbar) fn inline_top_base_y(&self) -> f64 {
Expand Down
37 changes: 37 additions & 0 deletions src/backend/wayland/state/toolbar/drag/clamp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
use std::time::Instant;

use super::*;

impl WaylandState {
fn toolbar_drag_should_apply(&mut self) -> bool {
let Some(interval) = toolbar_drag_throttle_interval() else {
return true;
};
let now = Instant::now();
let should_apply = match self.data.last_toolbar_drag_apply {
Some(last) => now.duration_since(last) >= interval,
None => true,
};
if should_apply {
self.data.last_toolbar_drag_apply = Some(now);
}
should_apply
}

pub(in crate::backend::wayland::state::toolbar) fn apply_toolbar_offsets_throttled(
&mut self,
snapshot: &ToolbarSnapshot,
) {
if self.toolbar_drag_preview_active() || toolbar_drag_throttle_interval().is_none() {
let _ = self.apply_toolbar_offsets(snapshot);
self.data.toolbar_drag_pending_apply = false;
self.data.last_toolbar_drag_apply = Some(Instant::now());
return;
}

if self.toolbar_drag_should_apply() {
let _ = self.apply_toolbar_offsets(snapshot);
self.data.toolbar_drag_pending_apply = false;
} else {
let _ = self.clamp_toolbar_offsets(snapshot);
self.data.toolbar_drag_pending_apply = true;
}
}

pub(in crate::backend::wayland::state::toolbar) fn clamp_toolbar_offsets(
&mut self,
snapshot: &ToolbarSnapshot,
Expand Down
Loading