1 use wayland_client::protocol::{wl_output, wl_seat, wl_surface};
2 use wayland_client::Proxy;
3 
4 use wayland_protocols::unstable::xdg_shell::v6::client::{
5     zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6,
6 };
7 use wayland_protocols::xdg_shell::client::xdg_toplevel;
8 
9 use self::zxdg_shell_v6_proto::zxdg_shell_v6::RequestsTrait as ShellRequests;
10 use self::zxdg_shell_v6_proto::zxdg_surface_v6::RequestsTrait as SurfaceRequests;
11 use self::zxdg_shell_v6_proto::zxdg_toplevel_v6::RequestsTrait as ToplevelRequests;
12 use wayland_client::protocol::wl_surface::RequestsTrait as WlSurfaceRequests;
13 use wayland_protocols::unstable::xdg_shell::v6::client as zxdg_shell_v6_proto;
14 
15 use super::{Event, ShellSurface};
16 
17 pub(crate) struct Zxdg {
18     surface: Proxy<zxdg_surface_v6::ZxdgSurfaceV6>,
19     toplevel: Proxy<zxdg_toplevel_v6::ZxdgToplevelV6>,
20 }
21 
22 impl Zxdg {
create<Impl>( surface: &Proxy<wl_surface::WlSurface>, shell: &Proxy<zxdg_shell_v6::ZxdgShellV6>, mut implementation: Impl, ) -> Zxdg where Impl: FnMut(Event) + Send + 'static,23     pub(crate) fn create<Impl>(
24         surface: &Proxy<wl_surface::WlSurface>,
25         shell: &Proxy<zxdg_shell_v6::ZxdgShellV6>,
26         mut implementation: Impl,
27     ) -> Zxdg
28     where
29         Impl: FnMut(Event) + Send + 'static,
30     {
31         let xdgs = shell
32             .get_xdg_surface(surface, |xdgs| {
33                 xdgs.implement(
34                     |evt, xdgs: Proxy<_>| match evt {
35                         zxdg_surface_v6::Event::Configure { serial } => {
36                             xdgs.ack_configure(serial);
37                         }
38                     },
39                     (),
40                 )
41             })
42             .unwrap();
43         let toplevel = xdgs
44             .get_toplevel(|toplevel| {
45                 toplevel.implement(
46                     move |evt, _| {
47                         match evt {
48                             zxdg_toplevel_v6::Event::Close => implementation(Event::Close),
49                             zxdg_toplevel_v6::Event::Configure {
50                                 width,
51                                 height,
52                                 states,
53                             } => {
54                                 use std::cmp::max;
55                                 let new_size = if width == 0 || height == 0 {
56                                     // if either w or h is zero, then we get to choose our size
57                                     None
58                                 } else {
59                                     Some((max(width, 1) as u32, max(height, 1) as u32))
60                                 };
61                                 let view: &[u32] = unsafe {
62                                     ::std::slice::from_raw_parts(
63                                         states.as_ptr() as *const _,
64                                         states.len() / 4,
65                                     )
66                                 };
67                                 let states = view
68                                     .iter()
69                                     .cloned()
70                                     // bit representation of xdg_toplevel_v6 and zxdg_toplevel_v6 matches
71                                     .flat_map(xdg_toplevel::State::from_raw)
72                                     .collect::<Vec<_>>();
73                                 implementation(Event::Configure { new_size, states });
74                             }
75                         }
76                     },
77                     (),
78                 )
79             })
80             .unwrap();
81         surface.commit();
82         Zxdg {
83             surface: xdgs,
84             toplevel,
85         }
86     }
87 }
88 
89 impl ShellSurface for Zxdg {
resize(&self, seat: &Proxy<wl_seat::WlSeat>, serial: u32, edges: xdg_toplevel::ResizeEdge)90     fn resize(&self, seat: &Proxy<wl_seat::WlSeat>, serial: u32, edges: xdg_toplevel::ResizeEdge) {
91         self.toplevel.resize(seat, serial, edges as u32);
92     }
93 
move_(&self, seat: &Proxy<wl_seat::WlSeat>, serial: u32)94     fn move_(&self, seat: &Proxy<wl_seat::WlSeat>, serial: u32) {
95         self.toplevel._move(seat, serial);
96     }
97 
set_title(&self, title: String)98     fn set_title(&self, title: String) {
99         self.toplevel.set_title(title);
100     }
101 
set_app_id(&self, app_id: String)102     fn set_app_id(&self, app_id: String) {
103         self.toplevel.set_app_id(app_id);
104     }
105 
set_fullscreen(&self, output: Option<&Proxy<wl_output::WlOutput>>)106     fn set_fullscreen(&self, output: Option<&Proxy<wl_output::WlOutput>>) {
107         self.toplevel.set_fullscreen(output)
108     }
109 
unset_fullscreen(&self)110     fn unset_fullscreen(&self) {
111         self.toplevel.unset_fullscreen();
112     }
113 
set_maximized(&self)114     fn set_maximized(&self) {
115         self.toplevel.set_maximized();
116     }
117 
unset_maximized(&self)118     fn unset_maximized(&self) {
119         self.toplevel.unset_maximized();
120     }
121 
set_minimized(&self)122     fn set_minimized(&self) {
123         self.toplevel.set_minimized();
124     }
125 
set_geometry(&self, x: i32, y: i32, width: i32, height: i32)126     fn set_geometry(&self, x: i32, y: i32, width: i32, height: i32) {
127         self.surface.set_window_geometry(x, y, width, height);
128     }
129 
set_min_size(&self, size: Option<(i32, i32)>)130     fn set_min_size(&self, size: Option<(i32, i32)>) {
131         if let Some((w, h)) = size {
132             self.toplevel.set_min_size(w, h);
133         } else {
134             self.toplevel.set_min_size(0, 0);
135         }
136     }
137 
set_max_size(&self, size: Option<(i32, i32)>)138     fn set_max_size(&self, size: Option<(i32, i32)>) {
139         if let Some((w, h)) = size {
140             self.toplevel.set_max_size(w, h);
141         } else {
142             self.toplevel.set_max_size(0, 0);
143         }
144     }
145 
get_xdg(&self) -> Option<&Proxy<xdg_toplevel::XdgToplevel>>146     fn get_xdg(&self) -> Option<&Proxy<xdg_toplevel::XdgToplevel>> {
147         None
148     }
149 }
150 
151 impl Drop for Zxdg {
drop(&mut self)152     fn drop(&mut self) {
153         self.toplevel.destroy();
154         self.surface.destroy();
155     }
156 }
157