Skip to content

Commit

Permalink
feat: support to move wlr_layer_shell
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioRibera committed Jan 3, 2025
1 parent 9910590 commit 36a3906
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
11 changes: 11 additions & 0 deletions src/platform/wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//! * `wayland-csd-adwaita` (default).
//! * `wayland-csd-adwaita-crossfont`.
//! * `wayland-csd-adwaita-notitle`.
#[cfg(wayland_platform)]
use sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer};

use crate::dpi::{LogicalPosition, LogicalSize};
Expand Down Expand Up @@ -91,14 +92,19 @@ pub trait WindowAttributesExtWayland {
/// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
fn with_name(self, general: impl Into<String>, instance: impl Into<String>) -> Self;

#[cfg(wayland_platform)]
fn with_anchor(self, anchor: Anchor) -> Self;

#[cfg(wayland_platform)]
fn with_exclusive_zone(self, exclusive_zone: i32) -> Self;

#[cfg(wayland_platform)]
fn with_margin(self, top: i32, right: i32, bottom: i32, left: i32) -> Self;

#[cfg(wayland_platform)]
fn with_keyboard_interactivity(self, keyboard_interactivity: KeyboardInteractivity) -> Self;

#[cfg(wayland_platform)]
fn with_layer(self, layer: Layer) -> Self;

#[cfg(wayland_platform)]
Expand All @@ -117,24 +123,28 @@ impl WindowAttributesExtWayland for WindowAttributes {
}

#[inline]
#[cfg(wayland_platform)]
fn with_anchor(mut self, anchor: Anchor) -> Self {
self.platform_specific.wayland.anchor = Some(anchor);
self
}

#[inline]
#[cfg(wayland_platform)]
fn with_exclusive_zone(mut self, exclusive_zone: i32) -> Self {
self.platform_specific.wayland.exclusive_zone = Some(exclusive_zone);
self
}

#[inline]
#[cfg(wayland_platform)]
fn with_margin(mut self, top: i32, right: i32, bottom: i32, left: i32) -> Self {
self.platform_specific.wayland.margin = Some((top, right, bottom, left));
self
}

#[inline]
#[cfg(wayland_platform)]
fn with_keyboard_interactivity(
mut self,
keyboard_interactivity: KeyboardInteractivity,
Expand All @@ -144,6 +154,7 @@ impl WindowAttributesExtWayland for WindowAttributes {
}

#[inline]
#[cfg(wayland_platform)]
fn with_layer(mut self, layer: Layer) -> Self {
self.platform_specific.wayland.layer = Some(layer);
self
Expand Down
9 changes: 5 additions & 4 deletions src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,12 +401,13 @@ impl CoreWindow for Window {
}

fn outer_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
Err(NotSupportedError::new("window position information is not available on Wayland")
.into())
// XXX just for LayerShell
self.window_state.lock().unwrap().outer_position()
}

fn set_outer_position(&self, _position: Position) {
// Not possible.
fn set_outer_position(&self, position: Position) {
// XXX just for LayerShell
self.window_state.lock().unwrap().set_outer_position(position);
}

fn surface_size(&self) -> PhysicalSize<u32> {
Expand Down
34 changes: 26 additions & 8 deletions src/platform_impl/linux/wayland/window/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::{Arc, Mutex, Weak};
use std::time::Duration;

use ahash::HashSet;
use dpi::{PhysicalPosition, Position};
use sctk::compositor::{CompositorState, Region, SurfaceData, SurfaceDataExt};
use sctk::reexports::client::backend::ObjectId;
use sctk::reexports::client::protocol::wl_seat::WlSeat;
Expand Down Expand Up @@ -76,7 +77,7 @@ pub struct WindowState {
/// Queue handle.
pub queue_handle: QueueHandle<WinitState>,

/// State that differes based on being an XDG shell or a WLR layer shell
/// State that differs based on being an XDG shell or a WLR layer shell
shell_specific: ShellSpecificState,

/// Theme variant.
Expand All @@ -85,9 +86,6 @@ pub struct WindowState {
/// The current window title.
title: String,

/// Whether the frame is resizable.
resizable: bool,

// NOTE: we can't use simple counter, since it's racy when seat getting destroyed and new
// is created, since add/removed stuff could be delivered a bit out of order.
/// Seats that has keyboard focus on that window.
Expand Down Expand Up @@ -226,7 +224,6 @@ impl WindowState {
pointer_constraints,
pointers: Default::default(),
queue_handle: queue_handle.clone(),
resizable: true,
scale_factor: 1.,
shm: winit_state.shm.wl_shm().clone(),
custom_cursor_pool: winit_state.custom_cursor_pool.clone(),
Expand Down Expand Up @@ -269,11 +266,10 @@ impl WindowState {
},
size: initial_size.to_logical(1.0),
selected_cursor: Default::default(),
decorate: true,
decorate: false,
frame_callback_state: FrameCallbackState::None,
seat_focus: Default::default(),
has_pending_move: None,
resizable: true,
custom_cursor_pool: winit_state.custom_cursor_pool.clone(),
initial_size: Some(initial_size),
text_inputs: Vec::new(),
Expand Down Expand Up @@ -733,6 +729,27 @@ impl WindowState {
}
}

#[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
Err(NotSupportedError::new("window position information is not available on xdg Wayland")
.into())
}

pub fn set_outer_position(&self, position: Position) {
let position = position.to_logical(self.scale_factor);

match &self.shell_specific {
ShellSpecificState::Xdg { .. } => {
warn!("Change window position is not available on xdg Wayland",)
},
// XXX just works for LayerShell
// Probably we can save this change to get in the `outer_position` function
ShellSpecificState::WlrLayer { surface, .. } => {
surface.set_margin(position.y, 0, 0, position.x)
},
}
}

/// Get the outer size of the window.
#[inline]
pub fn outer_size(&self) -> LogicalSize<u32> {
Expand Down Expand Up @@ -862,7 +879,8 @@ impl WindowState {
outer_size.height as i32,
);

// Update the target viewport, this is used if and only if fractional scaling is in use.
// Update the target viewport, this is used if and only if fractional scaling is in
// use.
if let Some(viewport) = viewport.as_ref() {
// Set inner size without the borders.
viewport.set_destination(self.size.width as _, self.size.height as _);
Expand Down

0 comments on commit 36a3906

Please sign in to comment.