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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed (breaking)

- Replace `RequestSetCursorShape` with `RequestSetCursor`, using `Cursor::Shape` or `Cursor::ThemeName`. Remove `ShapeName` and string-based shape parsing
- Remove the pointer-enter fallback from `take_popup_grab_serial`

### Changed

- Improve xdg toplevel support with compositor state tracking and window controls in `exwlshellev` and `iced_exwlshell`
- Allow xdg toplevel windows to parent popups
- Add `popup_grab_serial` alongside `take_popup_grab_serial`
- Support custom theme cursors, correct cursor mappings and fallbacks, and reuse the cursor surface

## [0.20.1] - 2026-09-11
### Hot Fix
- Fix: iced_exdevtools cannot compiled due to the new winit-core
Expand Down
4 changes: 2 additions & 2 deletions exwlshellev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ fn main() {
LayerShellEvent::RequestMessages(DispatchMessage::MouseButton { .. }) => ReturnData::None,
LayerShellEvent::RequestMessages(DispatchMessage::MouseEnter {
pointer, ..
}) => ReturnData::RequestSetCursorShape((
"crosshair".to_owned(),
}) => ReturnData::RequestSetCursor((
Cursor::Shape(CursorShape::Crosshair),
pointer.clone(),
)),
LayerShellEvent::RequestMessages(DispatchMessage::MouseMotion {
Expand Down
5 changes: 4 additions & 1 deletion exwlshellev/examples/simpleshell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ fn main() {
ReturnData::None
}
ExWlShellEvent::RequestMessages(DispatchMessage::MouseEnter { pointer, .. }) => {
ReturnData::RequestSetCursorShape(("crosshair".to_owned(), pointer.clone()))
ReturnData::RequestSetCursor((
Cursor::Shape(CursorShape::Crosshair),
pointer.clone(),
))
}
ExWlShellEvent::RequestMessages(DispatchMessage::MouseMotion {
time,
Expand Down
35 changes: 32 additions & 3 deletions exwlshellev/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use wayland_client::{
},
};

use crate::CursorShape;
use crate::size::{LayerSize, PixelSize};

use crate::{blur::BlurOption, id, xkb_keyboard::KeyEvent};
Expand Down Expand Up @@ -172,6 +173,19 @@ pub struct NewXdgWindowSettings {
pub client_side_decorations: bool,
}

/// Window state reported by `xdg_toplevel::configure`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ToplevelState {
/// The surface is maximized.
pub maximized: bool,
/// The surface is fullscreen.
pub fullscreen: bool,
/// At least one edge is tiled against another surface or the output.
pub tiled: bool,
/// The compositor considers this surface active.
pub activated: bool,
}

/// input panel settings to create a new input panel surface
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NewInputPanelSettings {
Expand Down Expand Up @@ -201,6 +215,15 @@ impl Default for NewLayerShellSettings {
}
}

/// A standard cursor shape or a named cursor from the current theme.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Cursor {
/// Use the [cursor-shape](https://wayland.app/protocols/cursor-shape-v1#wp_cursor_shape_device_v1:enum:shape) protocol, with the matching theme cursor as a fallback.
Shape(CursorShape),
/// Load a cursor by its exact Xcursor name, even when the cursor-shape protocol is available.
ThemeName(String),
}

/// the return data
/// Note: when event is RequestBuffer, you must return WlBuffer
/// Note: when receive InitRequest, you can request to bind extra wayland-protocols. this time you
Expand All @@ -210,8 +233,8 @@ impl Default for NewLayerShellSettings {
///
/// When send RequestExit, it will tell the event to finish.
///
/// When send RequestSetCursorShape, you can set current pointer shape. please take
/// [cursor-shape](https://wayland.app/protocols/cursor-shape-v1#wp_cursor_shape_device_v1:enum:shape) as reference.
/// Use `RequestSetCursor` with [`Cursor::Shape`] for standard shapes or [`Cursor::ThemeName`] for
/// an exact cursor name from the theme.
///
/// None means nothing will happened, no request, and no return data
#[derive(Debug, PartialEq, Eq)]
Expand All @@ -224,7 +247,7 @@ pub enum ReturnData<INFO> {
RequestCompositor,
RedrawAllRequest,
RedrawIndexRequest(Id),
RequestSetCursorShape((String, WlPointer)),
RequestSetCursor((Cursor, WlPointer)),
NewLayerShell((NewLayerShellSettings, id::Id, Option<INFO>)),
NewPopUp((NewPopUpSettings, id::Id, Option<INFO>)),
PopUpReposition((PopUpRepositionSettings, id::Id)),
Expand Down Expand Up @@ -365,6 +388,7 @@ pub(crate) enum DispatchMessageInner {
Locked,
LockFinished,
Ime(Ime),
ToplevelStateChanged(ToplevelState),
}

/// This tell the DispatchMessage by dispatch
Expand Down Expand Up @@ -473,6 +497,8 @@ pub enum DispatchMessage {
LockDenied,
LockFinished,
Closed,
/// The compositor changed the state of an xdg toplevel window.
ToplevelStateChanged(ToplevelState),
}

impl From<DispatchMessageInner> for DispatchMessage {
Expand Down Expand Up @@ -584,6 +610,9 @@ impl From<DispatchMessageInner> for DispatchMessage {
DispatchMessageInner::OutputChanged(output) => DispatchMessage::OutputChanged(output),
DispatchMessageInner::Locked => DispatchMessage::Locked,
DispatchMessageInner::LockFinished => DispatchMessage::LockFinished,
DispatchMessageInner::ToplevelStateChanged(state) => {
DispatchMessage::ToplevelStateChanged(state)
}
}
}
}
Loading
Loading