use std::{
num::NonZeroU32,
sync::{Arc, Weak},
};
use crate::reexports::client::{
protocol::{wl_output, wl_seat, wl_surface},
Connection, Proxy, QueueHandle,
};
use crate::reexports::csd_frame::{WindowManagerCapabilities, WindowState};
use crate::reexports::protocols::{
xdg::decoration::zv1::client::zxdg_toplevel_decoration_v1::{self, Mode},
xdg::shell::client::{xdg_surface, xdg_toplevel},
};
use crate::shell::WaylandSurface;
use self::inner::WindowInner;
use super::XdgSurface;
pub(super) mod inner;
pub trait WindowHandler: Sized {
fn request_close(&mut self, conn: &Connection, qh: &QueueHandle<Self>, window: &Window);
fn configure(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
window: &Window,
configure: WindowConfigure,
serial: u32,
);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecorationMode {
Client,
Server,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct WindowConfigure {
pub new_size: (Option<NonZeroU32>, Option<NonZeroU32>),
pub suggested_bounds: Option<(u32, u32)>,
pub decoration_mode: DecorationMode,
pub state: WindowState,
pub capabilities: WindowManagerCapabilities,
}
impl WindowConfigure {
#[inline]
pub fn is_maximized(&self) -> bool {
self.state.contains(WindowState::MAXIMIZED)
}
#[inline]
pub fn is_fullscreen(&self) -> bool {
self.state.contains(WindowState::FULLSCREEN)
}
#[inline]
pub fn is_resizing(&self) -> bool {
self.state.contains(WindowState::RESIZING)
}
#[inline]
pub fn is_tiled(&self) -> bool {
self.state.contains(WindowState::TILED)
}
#[inline]
pub fn is_activated(&self) -> bool {
self.state.contains(WindowState::ACTIVATED)
}
#[inline]
pub fn is_tiled_left(&self) -> bool {
self.state.contains(WindowState::TILED_LEFT)
}
#[inline]
pub fn is_tiled_right(&self) -> bool {
self.state.contains(WindowState::TILED_RIGHT)
}
#[inline]
pub fn is_tiled_top(&self) -> bool {
self.state.contains(WindowState::TILED_TOP)
}
#[inline]
pub fn is_tiled_bottom(&self) -> bool {
self.state.contains(WindowState::TILED_BOTTOM)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WindowDecorations {
ServerDefault,
RequestServer,
RequestClient,
ClientOnly,
None,
}
#[derive(Debug, Clone)]
pub struct Window(pub(super) Arc<WindowInner>);
impl Window {
pub fn from_xdg_toplevel(toplevel: &xdg_toplevel::XdgToplevel) -> Option<Window> {
toplevel.data::<WindowData>().and_then(|data| data.0.upgrade()).map(Window)
}
pub fn from_xdg_surface(surface: &xdg_surface::XdgSurface) -> Option<Window> {
surface.data::<WindowData>().and_then(|data| data.0.upgrade()).map(Window)
}
pub fn from_toplevel_decoration(
decoration: &zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1,
) -> Option<Window> {
decoration.data::<WindowData>().and_then(|data| data.0.upgrade()).map(Window)
}
pub fn show_window_menu(&self, seat: &wl_seat::WlSeat, serial: u32, position: (i32, i32)) {
self.xdg_toplevel().show_window_menu(seat, serial, position.0, position.1);
}
pub fn set_title(&self, title: impl Into<String>) {
self.xdg_toplevel().set_title(title.into());
}
pub fn set_app_id(&self, app_id: impl Into<String>) {
self.xdg_toplevel().set_app_id(app_id.into());
}
pub fn set_parent(&self, parent: Option<&Window>) {
self.xdg_toplevel().set_parent(parent.map(Window::xdg_toplevel));
}
pub fn set_maximized(&self) {
self.xdg_toplevel().set_maximized()
}
pub fn unset_maximized(&self) {
self.xdg_toplevel().unset_maximized()
}
pub fn set_minimized(&self) {
self.xdg_toplevel().set_minimized()
}
pub fn set_fullscreen(&self, output: Option<&wl_output::WlOutput>) {
self.xdg_toplevel().set_fullscreen(output)
}
pub fn unset_fullscreen(&self) {
self.xdg_toplevel().unset_fullscreen()
}
pub fn request_decoration_mode(&self, mode: Option<DecorationMode>) {
if let Some(toplevel_decoration) = &self.0.toplevel_decoration {
match mode {
Some(DecorationMode::Client) => toplevel_decoration.set_mode(Mode::ClientSide),
Some(DecorationMode::Server) => toplevel_decoration.set_mode(Mode::ServerSide),
None => toplevel_decoration.unset_mode(),
}
}
}
pub fn move_(&self, seat: &wl_seat::WlSeat, serial: u32) {
self.xdg_toplevel()._move(seat, serial)
}
pub fn resize(&self, seat: &wl_seat::WlSeat, serial: u32, edges: xdg_toplevel::ResizeEdge) {
self.xdg_toplevel().resize(seat, serial, edges)
}
pub fn set_min_size(&self, min_size: Option<(u32, u32)>) {
let min_size = min_size.unwrap_or_default();
self.xdg_toplevel().set_min_size(min_size.0 as i32, min_size.1 as i32);
}
pub fn set_max_size(&self, max_size: Option<(u32, u32)>) {
let max_size = max_size.unwrap_or_default();
self.xdg_toplevel().set_max_size(max_size.0 as i32, max_size.1 as i32);
}
pub fn xdg_toplevel(&self) -> &xdg_toplevel::XdgToplevel {
&self.0.xdg_toplevel
}
}
impl WaylandSurface for Window {
fn wl_surface(&self) -> &wl_surface::WlSurface {
self.0.xdg_surface.wl_surface()
}
}
impl XdgSurface for Window {
fn xdg_surface(&self) -> &xdg_surface::XdgSurface {
self.0.xdg_surface.xdg_surface()
}
}
impl PartialEq for Window {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
#[derive(Debug, Clone)]
pub struct WindowData(pub(crate) Weak<WindowInner>);
#[macro_export]
macro_rules! delegate_xdg_window {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
$crate::reexports::protocols::xdg::shell::client::xdg_surface::XdgSurface: $crate::shell::xdg::window::WindowData
] => $crate::shell::xdg::XdgShell);
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
$crate::reexports::protocols::xdg::shell::client::xdg_toplevel::XdgToplevel: $crate::shell::xdg::window::WindowData
] => $crate::shell::xdg::XdgShell);
};
}