Files
server/src/wayland/xdg/positioner.rs
Schmarni 0ebfc1153e chore(wayland): update waynest
Signed-off-by: Schmarni <marnistromer@gmail.com>
2025-09-30 22:32:09 +02:00

266 lines
6.2 KiB
Rust

use crate::{nodes::items::panel::Geometry, wayland::WaylandResult};
use mint::Vector2;
use parking_lot::Mutex;
use waynest::ObjectId;
use waynest_protocols::server::stable::xdg_shell::xdg_positioner::*;
use waynest_server::Client as _;
#[derive(Debug, Clone, Copy)]
pub struct PositionerData {
pub size: Vector2<u32>,
pub anchor_rect: Geometry,
pub offset: Vector2<i32>,
pub anchor: Anchor,
pub gravity: Gravity,
pub constraint_adjustment: ConstraintAdjustment,
pub reactive: bool,
pub parent_size: Vector2<u32>,
}
impl PositionerData {
fn gravity_has_edge(&self, edge: Gravity) -> bool {
match edge {
Gravity::Top => {
self.gravity == Gravity::Top
|| self.gravity == Gravity::TopLeft
|| self.gravity == Gravity::TopRight
}
Gravity::Bottom => {
self.gravity == Gravity::Bottom
|| self.gravity == Gravity::BottomLeft
|| self.gravity == Gravity::BottomRight
}
Gravity::Left => {
self.gravity == Gravity::Left
|| self.gravity == Gravity::TopLeft
|| self.gravity == Gravity::BottomLeft
}
Gravity::Right => {
self.gravity == Gravity::Right
|| self.gravity == Gravity::TopRight
|| self.gravity == Gravity::BottomRight
}
_ => unreachable!(),
}
}
pub fn infinite_geometry(&self) -> Geometry {
let anchor_point = match self.anchor {
Anchor::TopLeft => self.anchor_rect.origin,
Anchor::Top => [
self.anchor_rect.origin.x + (self.anchor_rect.size.x / 2) as i32,
self.anchor_rect.origin.y,
]
.into(),
Anchor::TopRight => [
self.anchor_rect.origin.x + self.anchor_rect.size.x as i32,
self.anchor_rect.origin.y,
]
.into(),
Anchor::Left => [
self.anchor_rect.origin.x,
self.anchor_rect.origin.y + (self.anchor_rect.size.y / 2) as i32,
]
.into(),
Anchor::Right => [
self.anchor_rect.origin.x + self.anchor_rect.size.x as i32,
self.anchor_rect.origin.y + (self.anchor_rect.size.y / 2) as i32,
]
.into(),
Anchor::BottomLeft => [
self.anchor_rect.origin.x,
self.anchor_rect.origin.y + self.anchor_rect.size.y as i32,
]
.into(),
Anchor::Bottom => [
self.anchor_rect.origin.x + (self.anchor_rect.size.x / 2) as i32,
self.anchor_rect.origin.y + self.anchor_rect.size.y as i32,
]
.into(),
Anchor::BottomRight => [
self.anchor_rect.origin.x + self.anchor_rect.size.x as i32,
self.anchor_rect.origin.y + self.anchor_rect.size.y as i32,
]
.into(),
_ => [
self.anchor_rect.origin.x + (self.anchor_rect.size.x / 2) as i32,
self.anchor_rect.origin.y + (self.anchor_rect.size.y / 2) as i32,
]
.into(),
};
let mut geometry = Geometry {
origin: [
anchor_point.x + self.offset.x,
anchor_point.y + self.offset.y,
]
.into(),
size: self.size,
};
// apply gravity
if self.gravity_has_edge(Gravity::Top) {
geometry.origin.y -= geometry.size.y as i32;
} else if !self.gravity_has_edge(Gravity::Bottom) {
geometry.origin.y -= (geometry.size.y / 2) as i32;
}
if self.gravity_has_edge(Gravity::Left) {
geometry.origin.x -= geometry.size.x as i32;
} else if !self.gravity_has_edge(Gravity::Right) {
geometry.origin.x -= (geometry.size.x / 2) as i32;
}
geometry
}
}
impl Default for PositionerData {
fn default() -> Self {
Self {
size: [0; 2].into(),
anchor_rect: Default::default(),
offset: [0, 0].into(),
anchor: Anchor::TopLeft,
gravity: Gravity::TopLeft,
constraint_adjustment: ConstraintAdjustment::empty(),
reactive: false,
parent_size: [0; 2].into(),
}
}
}
#[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError, connection = crate::wayland::Client)]
pub struct Positioner {
data: Mutex<PositionerData>,
id: ObjectId,
}
impl Positioner {
pub fn new(id: ObjectId) -> Self {
Self {
data: Mutex::new(PositionerData::default()),
id,
}
}
}
impl Positioner {
pub fn data(&self) -> PositionerData {
*self.data.lock()
}
}
impl XdgPositioner for Positioner {
type Connection = crate::wayland::Client;
async fn set_size(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_width: i32,
_height: i32,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.size = [_width.max(0) as u32, _height.max(0) as u32].into();
data.reactive = true;
Ok(())
}
async fn set_anchor_rect(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_x: i32,
_y: i32,
_width: i32,
_height: i32,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.anchor_rect.origin = [_x, _y].into();
data.anchor_rect.size = [_width.max(0) as u32, _height.max(0) as u32].into();
data.offset = [0, 0].into();
Ok(())
}
async fn set_anchor(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_anchor: Anchor,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.anchor = _anchor;
Ok(())
}
async fn set_gravity(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
gravity: Gravity,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.gravity = gravity;
Ok(())
}
async fn set_constraint_adjustment(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_constraint_adjustment: ConstraintAdjustment,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.constraint_adjustment = _constraint_adjustment;
Ok(())
}
async fn set_offset(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_x: i32,
_y: i32,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.offset.x += _x;
data.offset.y += _y;
Ok(())
}
async fn set_reactive(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(())
}
async fn set_parent_size(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_parent_width: i32,
_parent_height: i32,
) -> WaylandResult<()> {
let mut data = self.data.lock();
data.parent_size.x = _parent_width.max(0) as u32;
data.parent_size.y = _parent_height.max(0) as u32;
Ok(())
}
async fn set_parent_configure(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_serial: u32,
) -> WaylandResult<()> {
Ok(())
}
async fn destroy(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
client.remove(self.id);
Ok(())
}
}