Skip to content

Commit ab70fe5

Browse files
committed
wayland-csd-frame version 0.1.0
0 parents  commit ab70fe5

File tree

7 files changed

+365
-0
lines changed

7 files changed

+365
-0
lines changed

.github/workflows/ci.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
env:
9+
RUST_BACKTRACE: 1
10+
CARGO_INCREMENTAL: 0
11+
RUSTFLAGS: "-Cdebuginfo=0 --deny=warnings"
12+
RUSTDOCFLAGS: "--deny=warnings"
13+
14+
jobs:
15+
fmt:
16+
name: Check Formatting
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v2
20+
- uses: hecrj/setup-rust-action@v1
21+
with:
22+
rust-version: nightly
23+
components: rustfmt
24+
- name: Check Formatting
25+
run: cargo +nightly fmt --all -- --check
26+
27+
tests:
28+
name: Tests
29+
runs-on: ubuntu-latest
30+
strategy:
31+
matrix:
32+
rust_version: ["1.64", stable, nightly]
33+
34+
steps:
35+
- uses: actions/checkout@v2
36+
37+
- uses: hecrj/setup-rust-action@v1
38+
with:
39+
rust-version: ${{ matrix.rust_version }}
40+
41+
- name: Check documentation
42+
run: cargo doc --no-deps --document-private-items
43+
44+
- name: Run tests
45+
run: cargo test --verbose

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
/Cargo.lock

Cargo.toml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "wayland-csd-frame"
3+
version = "0.1.0"
4+
authors = ["Kirill Chibisov <[email protected]>"]
5+
repository = "https://github.com/rust-windowing/wayland-csd-frame"
6+
description = "Common trait and types for wayland CSD interop"
7+
keywords = ["windowing", "wayland"]
8+
readme = "README.md"
9+
license = "MIT"
10+
edition = "2021"
11+
categories = ["gui"]
12+
rust-version = "1.64.0"
13+
14+
[dependencies]
15+
bitflags = "2.0"
16+
cursor-icon = "1.0.0"
17+
wayland-backend = { version = "0.1.1", default-features = false }

LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2023 Kirill Chibisov
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# wayland-csd-frame
2+
3+
`wayland-csd-frame` aims to provide common client side decorations (CSD) frame
4+
for xdg-shell Wayland windows establishing a stable interface between windowing
5+
libraries (e.g winit) and decorations drawing libraries.
6+
7+
This library defines a simple interface other crates providing decoration
8+
frames could use to integrate with crates like winit. An example of crates
9+
using this interface to provide decorations frame:
10+
11+
- https://github.com/PolyMeilex/sctk-adwaita an Adwaita-like frame.
12+
- https://github.com/smithay/client-toolkit provides bare bones `FallbackFrame`.

rustfmt.toml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
format_code_in_doc_comments = true
2+
match_block_trailing_comma = true
3+
condense_wildcard_suffixes = true
4+
use_field_init_shorthand = true
5+
normalize_doc_attributes = true
6+
overflow_delimited_expr = true
7+
imports_granularity = "Module"
8+
use_small_heuristics = "Max"
9+
normalize_comments = true
10+
reorder_impl_items = true
11+
use_try_shorthand = true
12+
newline_style = "Unix"
13+
format_strings = true
14+
wrap_comments = true
15+
comment_width = 80
16+
edition = "2021"

src/lib.rs

+254
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#![deny(rust_2018_idioms)]
2+
#![deny(rustdoc::broken_intra_doc_links)]
3+
#![deny(unsafe_op_in_unsafe_fn)]
4+
#![deny(improper_ctypes, improper_ctypes_definitions)]
5+
#![deny(clippy::all)]
6+
#![deny(missing_debug_implementations)]
7+
#![deny(missing_docs)]
8+
#![forbid(unsafe_code)]
9+
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
10+
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
11+
12+
//! The interface for wayland client side decorations (CSD).
13+
//!
14+
//! The crate is intended to be used by libraries providing client
15+
//! side decorations for the xdg-shell protocol.
16+
//!
17+
//! Examples could be found in [`client toolkit`] and [`sctk-adwaita`].
18+
//!
19+
//! [`client toolkit`]: https://github.com/smithay/client-toolkit
20+
//! [`sctk-adwaita`]: https://github.com/PolyMeilex/sctk-adwaita
21+
22+
use std::num::NonZeroU32;
23+
24+
use bitflags::bitflags;
25+
use wayland_backend::client::ObjectId;
26+
27+
#[doc(inline)]
28+
pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError};
29+
30+
/// The interface for the client side decorations.
31+
pub trait DecorationsFrame: Sized {
32+
/// Emulate click on the decorations.
33+
///
34+
/// The `click` is a variant of click to use, see [`FrameClick`] for more
35+
/// information.
36+
///
37+
/// The return value is a [`FrameAction`] you should apply, this action
38+
/// could be ignored.
39+
///
40+
/// The location of the click is the one passed to
41+
/// [`Self::click_point_moved`].
42+
fn on_click(&mut self, click: FrameClick, pressed: bool) -> Option<FrameAction>;
43+
44+
/// Emulate pointer moved event on the decorations frame.
45+
///
46+
/// The `x` and `y` are location in the surface local coordinates relative
47+
/// to the `surface`.
48+
///
49+
/// The return value is the new cursor icon you should apply to provide
50+
/// better visual feedback for the user. However, you might want to
51+
/// ignore it, if you're using touch events to drive the movements.
52+
fn click_point_moved(&mut self, surface_id: &ObjectId, x: f64, y: f64) -> Option<CursorIcon>;
53+
54+
/// All clicks left the decorations.
55+
///
56+
/// This function should be called when input leaves the decorations.
57+
fn click_point_left(&mut self);
58+
59+
/// Update the state of the frame.
60+
///
61+
/// The state is usually obtained from the `xdg_toplevel::configure` event.
62+
fn update_state(&mut self, state: WindowState);
63+
64+
/// Update the window manager capabilites.
65+
///
66+
/// The capabilites are usually obtained from the
67+
/// `xdg_toplevel::wm_capabilities` event.
68+
fn update_wm_capabilities(&mut self, wm_capabilities: WindowManagerCapabilities);
69+
70+
/// Resize the window to the new size.
71+
///
72+
/// The size must be without the borders, as in [`Self::subtract_borders]`
73+
/// were used on it.
74+
///
75+
/// **Note:** The [`Self::update_state`] and
76+
/// [`Self::update_wm_capabilities`] **must be** applied before calling
77+
/// this function.
78+
///
79+
/// # Panics
80+
///
81+
/// Panics when resizing the hidden frame.
82+
fn resize(&mut self, width: NonZeroU32, height: NonZeroU32);
83+
84+
/// Return the coordinates of the top-left corner of the borders relative to
85+
/// the content.
86+
///
87+
/// Values **must** thus be non-positive.
88+
fn location(&self) -> (i32, i32);
89+
90+
/// Subtract the borders from the given `width` and `height`.
91+
///
92+
/// `None` will be returned for the particular dimension when the given
93+
/// value for it was too small.
94+
fn subtract_borders(
95+
&self,
96+
width: NonZeroU32,
97+
height: NonZeroU32,
98+
) -> (Option<NonZeroU32>, Option<NonZeroU32>);
99+
100+
/// Add the borders to the given `width` and `height`.
101+
///
102+
/// Passing zero for both width and height could be used to get the size
103+
/// of the decorations frame.
104+
fn add_borders(&self, width: u32, height: u32) -> (u32, u32);
105+
106+
/// Whether the given frame is dirty and should be redrawn.
107+
fn is_dirty(&self) -> bool;
108+
109+
/// Set the frame as hidden.
110+
///
111+
/// The frame **must be** visible by default.
112+
fn set_hidden(&mut self, hidden: bool);
113+
114+
/// Get the frame hidden state.
115+
///
116+
/// Get the state of the last [`DecorationsFrame::set_hidden`].
117+
fn is_hidden(&self) -> bool;
118+
119+
/// Mark the frame as resizable.
120+
///
121+
/// By default the frame is resizable.
122+
fn set_resizable(&mut self, resizable: bool);
123+
124+
/// Draw the decorations frame.
125+
///
126+
/// The user of the frame **must** commit the base surface afterwards.
127+
fn draw(&mut self);
128+
129+
/// Set the frames title.
130+
fn set_title(&mut self, title: impl Into<String>);
131+
}
132+
133+
/// The Frame action user should perform in responce to mouse click events.
134+
#[non_exhaustive]
135+
#[derive(Debug, Clone, Copy)]
136+
pub enum FrameAction {
137+
/// The window should be minimized.
138+
Minimize,
139+
/// The window should be maximized.
140+
Maximize,
141+
/// The window should be unmaximized.
142+
UnMaximize,
143+
/// The window should be closed.
144+
Close,
145+
/// An interactive move should be started.
146+
Move,
147+
/// An interactive resize should be started with the provided edge.
148+
Resize(ResizeEdge),
149+
/// Show window menu.
150+
///
151+
/// The coordinates are relative to the base surface, as in should be
152+
/// directly passed to the `xdg_toplevel::show_window_menu`.
153+
ShowMenu(i32, i32),
154+
}
155+
156+
/// The user clicked or touched the decoractions frame.
157+
#[non_exhaustive]
158+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159+
pub enum FrameClick {
160+
/// The user done normal click, likely with left mouse button or single
161+
/// finger touch.
162+
Normal,
163+
164+
/// The user done right mouse click or some touch sequence that was treated
165+
/// as alternate click.
166+
///
167+
/// The alternate click exists solely to provide alternative action, like
168+
/// show window menu when doing right mouse button cilck on the header
169+
/// decorations, nothing more.
170+
Alternate,
171+
}
172+
173+
bitflags! {
174+
/// The configured state of the window.
175+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
176+
pub struct WindowState: u16 {
177+
/// The surface is maximized. The window geometry specified in the
178+
/// configure event must be obeyed by the client. The client should
179+
/// draw without shadow or other decoration outside of the window
180+
/// geometry.
181+
const MAXIMIZED = 0b0000_0000_0000_0001;
182+
/// The surface is fullscreen. The window geometry specified in the
183+
/// configure event is a maximum; the client cannot resize beyond it.
184+
/// For a surface to cover the whole fullscreened area, the geometry
185+
/// dimensions must be obeyed by the client. For more details, see
186+
/// xdg_toplevel.set_fullscreen.
187+
const FULLSCREEN = 0b0000_0000_0000_0010;
188+
/// The surface is being resized. The window geometry specified in the
189+
/// configure event is a maximum; the client cannot resize beyond it.
190+
/// Clients that have aspect ratio or cell sizing configuration can use
191+
/// a smaller size, however.
192+
const RESIZING = 0b0000_0000_0000_0100;
193+
/// Client window decorations should be painted as if the window is
194+
/// active. Do not assume this means that the window actually has
195+
/// keyboard or pointer focus.
196+
const ACTIVATED = 0b0000_0000_0000_1000;
197+
/// The window is currently in a tiled layout and the left edge is
198+
/// considered to be adjacent to another part of the tiling grid.
199+
const TILED_LEFT = 0b0000_0000_0001_0000;
200+
/// The window is currently in a tiled layout and the right edge is
201+
/// considered to be adjacent to another part of the tiling grid.
202+
const TILED_RIGHT = 0b0000_0000_0010_0000;
203+
/// The window is currently in a tiled layout and the top edge is
204+
/// considered to be adjacent to another part of the tiling grid.
205+
const TILED_TOP = 0b0000_0000_0100_0000;
206+
/// The window is currently in a tiled layout and the bottom edge is
207+
/// considered to be adjacent to another part of the tiling grid.
208+
const TILED_BOTTOM = 0b0000_0000_1000_0000;
209+
/// The window has any of the mentioned tiled bits set.
210+
const TILED = Self::TILED_TOP.bits() | Self::TILED_LEFT.bits() | Self::TILED_RIGHT.bits() | Self::TILED_BOTTOM.bits();
211+
}
212+
}
213+
214+
bitflags! {
215+
/// The capabilities of the window manager.
216+
///
217+
/// This is a hint to hide UI elements which provide functionality
218+
/// not supported by compositor.
219+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
220+
pub struct WindowManagerCapabilities : u16 {
221+
/// `show_window_menu` is available.
222+
const WINDOW_MENU = 0b0000_0000_0000_0001;
223+
/// Window can be maximized and unmaximized.
224+
const MAXIMIZE = 0b0000_0000_0000_0010;
225+
/// Window can be fullscreened and unfullscreened.
226+
const FULLSCREEN = 0b0000_0000_0000_0100;
227+
/// Window could be minimized.
228+
const MINIMIZE = 0b0000_0000_0000_1000;
229+
}
230+
}
231+
232+
/// Which edge or corner is being dragged.
233+
#[non_exhaustive]
234+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
235+
pub enum ResizeEdge {
236+
/// Nothing is being dragged.
237+
None,
238+
/// The top edge is being dragged.
239+
Top,
240+
/// The bottom edge is being dragged.
241+
Bottom,
242+
/// The left edge is being dragged.
243+
Left,
244+
/// The top left corner is being dragged.
245+
TopLeft,
246+
/// The bottom left corner is being dragged.
247+
BottomLeft,
248+
/// The right edge is being dragged.
249+
Right,
250+
/// The top right corner is being dragged.
251+
TopRight,
252+
/// The bottom right corner is being dragged.
253+
BottomRight,
254+
}

0 commit comments

Comments
 (0)