Skip to content

Commit

Permalink
sctk: Fixes for cursor icon
Browse files Browse the repository at this point in the history
* With multiple windows, `SetCursor` is only sent for the focused
  window. Fixing a flicker between icons when two windows are using
  different cursors.
* If there is a drag surface, let that surface set the cursor. And not
  any other.
* Set cursor on `enter`, and when switching between CSDs and app area.

Fixes pop-os/libcosmic#533.
  • Loading branch information
ids1024 committed Jul 11, 2024
1 parent 26a8598 commit b096453
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 35 deletions.
15 changes: 13 additions & 2 deletions sctk/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ where

// just draw here immediately and never again for dnd icons
// TODO handle scale factor?
let _new_mouse_interaction = user_interface.draw(
let new_mouse_interaction = user_interface.draw(
&mut renderer,
state.theme(),
&Style {
Expand All @@ -940,6 +940,13 @@ where
state.cursor(),
);

mouse_interaction = new_mouse_interaction;
ev_proxy.send_event(Event::SetCursor(mouse_interaction));
// Pre-emptively remove cursor focus from other surface so they won't set cursor
for state in states.values_mut() {
state.cursor_position = None;
}

let subsurfaces = crate::subsurface_widget::take_subsurfaces();
if let Some(subsurface_state) = subsurface_state.as_mut() {
subsurface_state.update_subsurfaces(
Expand Down Expand Up @@ -1439,7 +1446,11 @@ where
}

debug.draw_finished();
if new_mouse_interaction != mouse_interaction {

// Set cursor if mouse interaction has changed, and surface has pointer focus
if state.cursor_position.is_some()
&& new_mouse_interaction != mouse_interaction
{
mouse_interaction = new_mouse_interaction;
ev_proxy
.send_event(Event::SetCursor(mouse_interaction));
Expand Down
5 changes: 3 additions & 2 deletions sctk/src/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,10 @@ where
},
},
Event::SetCursor(iced_icon) => {
if let Some(ptr) = self.state.seats.get(0).and_then(|s| s.ptr.as_ref()) {
if let Some(seat) = self.state.seats.get_mut(0) {
let icon = conversion::cursor_icon(iced_icon);
let _ = ptr.set_cursor(self.wayland_dispatcher.as_source_ref().connection(), icon);
seat.icon = Some(icon);
seat.set_cursor(self.wayland_dispatcher.as_source_ref().connection(), icon);
}

}
Expand Down
12 changes: 12 additions & 0 deletions sctk/src/event_loop/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,21 @@ pub(crate) struct SctkSeat {
pub(crate) last_touch_down: Option<(u32, i32, u32)>, // (time, point, serial)
pub(crate) _modifiers: Modifiers,
pub(crate) data_device: DataDevice,
// Cursor icon currently set (by CSDs, or application)
pub(crate) active_icon: Option<CursorIcon>,
// Cursor icon set by applicationb
pub(crate) icon: Option<CursorIcon>,
}

impl SctkSeat {
pub(crate) fn set_cursor(&mut self, conn: &Connection, icon: CursorIcon) {
if let Some(ptr) = self.ptr.as_ref() {
ptr.set_cursor(conn, icon);
self.active_icon = Some(icon);
}
}
}

#[derive(Debug, Clone)]
pub struct SctkWindow<T> {
pub(crate) id: window::Id,
Expand Down
45 changes: 14 additions & 31 deletions sctk/src/handlers/seat/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,41 +94,24 @@ impl<T: Debug> PointerHandler for SctkState<T> {
return;
}
PointerEventKind::Motion { .. } => {
if my_seat.icon != Some(icon) {
let _ = my_seat
.ptr
.as_ref()
.unwrap()
.set_cursor(conn, icon);
my_seat.icon = Some(icon);
if my_seat.active_icon != Some(icon) {
let _ = my_seat.set_cursor(conn, icon);
}
return;
}
PointerEventKind::Enter { .. } => {
my_seat.ptr_focus.replace(e.surface.clone());
if my_seat.icon != Some(icon) {
let _ = my_seat
.ptr
.as_ref()
.unwrap()
.set_cursor(conn, icon);
my_seat.icon = Some(icon);
}
}
PointerEventKind::Leave { .. } => {
my_seat.ptr_focus.take();
my_seat.icon = None;
}
PointerEventKind::Enter { .. } => {}
PointerEventKind::Leave { .. } => {}
_ => {}
}
let _ = my_seat.ptr.as_ref().unwrap().set_cursor(conn, icon);
} else if my_seat.icon.is_some() {
let _ = my_seat
.ptr
.as_ref()
.unwrap()
.set_cursor(conn, CursorIcon::Default);
my_seat.icon = None;
if my_seat.active_icon != Some(icon) {
my_seat.set_cursor(conn, icon);
}
} else if my_seat.active_icon != my_seat.icon {
// Restore cursor that was set by appliction, or default
my_seat.set_cursor(
conn,
my_seat.icon.unwrap_or(CursorIcon::Default),
);
}

if is_active {
Expand All @@ -144,7 +127,7 @@ impl<T: Debug> PointerHandler for SctkState<T> {
}
PointerEventKind::Leave { .. } => {
my_seat.ptr_focus.take();
my_seat.icon = None;
my_seat.active_icon = None;
}
PointerEventKind::Press {
time,
Expand Down
2 changes: 2 additions & 0 deletions sctk/src/handlers/seat/seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ where
last_kbd_press: None,
last_touch_down: None,
icon: None,
active_icon: None,
});
}

Expand Down Expand Up @@ -71,6 +72,7 @@ where
last_kbd_press: None,
last_touch_down: None,
icon: None,
active_icon: None,
});
self.seats.last_mut().unwrap()
}
Expand Down

0 comments on commit b096453

Please sign in to comment.