wayland_window/shell/
mod.rs

1use FrameIData;
2use wayland_client::{EventQueueHandle, Proxy};
3use wayland_client::protocol::*;
4use wayland_protocols::unstable::xdg_shell::v6 as xdg_shell;
5
6mod xdg;
7mod wl;
8
9/// Enum over the supported shells
10pub enum Shell {
11    /// A xdg_shell from unstable v6
12    Xdg(xdg_shell::client::zxdg_shell_v6::ZxdgShellV6),
13    /// A wl_shell
14    Wl(wl_shell::WlShell),
15}
16
17impl Shell {
18    pub(crate) fn needs_readiness(&self) -> bool {
19        match *self {
20            Shell::Xdg(_) => true,
21            Shell::Wl(_) => false,
22        }
23    }
24}
25
26pub(crate) enum Surface {
27    Xdg(self::xdg::Surface),
28    Wl(wl_shell_surface::WlShellSurface),
29}
30
31/// Configure data for a decorated surface handler.
32#[derive(Debug, Clone)]
33pub enum Configure {
34    /// Configure data from xdg_shell
35    Xdg(Vec<xdg_shell::client::zxdg_toplevel_v6::State>),
36    /// Configure data from wl_shell
37    Wl(wl_shell_surface::Resize),
38}
39
40impl Surface {
41    pub fn from_shell(surface: &wl_surface::WlSurface, shell: &Shell) -> Self {
42        match *shell {
43            // Create the `xdg_surface` and assign the `toplevel` role.
44            Shell::Xdg(ref shell) => {
45                let xdg_surface = shell
46                    .get_xdg_surface(surface)
47                    .expect("shell cannot be destroyed");
48                let toplevel = xdg_surface
49                    .get_toplevel()
50                    .expect("xdg_surface cannot be destroyed");
51                surface.commit();
52                Surface::Xdg(self::xdg::Surface {
53                    surface: xdg_surface,
54                    toplevel: toplevel,
55                })
56            }
57
58            // Create a `wl_shell_surface` and set it as the `toplevel`.
59            Shell::Wl(ref shell) => {
60                let shell_surface = shell.get_shell_surface(surface);
61                shell_surface.set_toplevel();
62                Surface::Wl(shell_surface)
63            }
64        }
65    }
66
67    pub(crate) fn clone(&self) -> Option<Surface> {
68        match *self {
69            Surface::Xdg(ref s) => s.clone().map(Surface::Xdg),
70            Surface::Wl(ref s) => s.clone().map(Surface::Wl),
71        }
72    }
73
74    pub(crate) fn register_to<ID: 'static>(&self, evqh: &mut EventQueueHandle, idata: FrameIData<ID>) {
75        match *self {
76            Surface::Xdg(ref xdg) => {
77                evqh.register(
78                    &xdg.toplevel,
79                    self::xdg::xdg_toplevel_implementation(),
80                    idata.clone(),
81                );
82                evqh.register(&xdg.surface, self::xdg::xdg_surface_implementation(), idata);
83            }
84            Surface::Wl(ref shell_surface) => {
85                evqh.register(
86                    shell_surface,
87                    self::wl::wl_shell_surface_implementation(),
88                    idata,
89                );
90            }
91        }
92    }
93
94    pub(crate) fn destroy(&self) {
95        match *self {
96            Surface::Xdg(ref xdg) => xdg.destroy(),
97            Surface::Wl(ref _shell_surface) => { /* we can't destroy it :'( */ }
98        }
99    }
100
101    pub(crate) fn resize(&self, seat: &wl_seat::WlSeat, serial: u32, direction: wl_shell_surface::Resize) {
102        match *self {
103            Surface::Xdg(ref xdg) => {
104                xdg.toplevel.resize(seat, serial, direction.to_raw());
105            }
106            Surface::Wl(ref shell_surface) => shell_surface.resize(seat, serial, direction),
107        }
108    }
109
110    pub(crate) fn _move(&self, seat: &wl_seat::WlSeat, serial: u32) {
111        match *self {
112            Surface::Xdg(ref xdg) => {
113                xdg.toplevel._move(seat, serial);
114            }
115            Surface::Wl(ref shell_surface) => shell_surface._move(seat, serial),
116        }
117    }
118
119    pub(crate) fn set_title(&self, title: String) {
120        match *self {
121            Surface::Xdg(ref xdg) => {
122                xdg.toplevel.set_title(title);
123            }
124            Surface::Wl(ref wl) => {
125                wl.set_title(title);
126            }
127        }
128    }
129
130    pub(crate) fn set_app_id(&self, title: String) {
131        match *self {
132            Surface::Xdg(ref xdg) => {
133                xdg.toplevel.set_app_id(title);
134            }
135            Surface::Wl(ref wl) => {
136                wl.set_class(title);
137            }
138        }
139    }
140
141    pub(crate) fn set_fullscreen(&self, output: Option<&wl_output::WlOutput>) {
142        match *self {
143            Surface::Xdg(ref xdg) => {
144                xdg.toplevel.set_fullscreen(output);
145            }
146            Surface::Wl(ref wl) => {
147                let method = wl_shell_surface::FullscreenMethod::Default;
148                let framerate = 0; // Let the server decide the framerate.
149                wl.set_fullscreen(method, framerate, output);
150            }
151        }
152    }
153
154    pub(crate) fn unset_fullscreen(&self) {
155        match *self {
156            Surface::Xdg(ref xdg) => {
157                xdg.toplevel.unset_fullscreen();
158            }
159            Surface::Wl(ref wl) => {
160                wl.set_toplevel();
161            }
162        }
163    }
164
165    pub(crate) fn set_maximized(&self) {
166        match *self {
167            Surface::Xdg(ref xdg) => {
168                xdg.toplevel.set_maximized();
169            }
170            Surface::Wl(ref wl) => {
171                wl.set_maximized(None);
172            }
173        }
174    }
175
176    pub(crate) fn unset_maximized(&self) {
177        match *self {
178            Surface::Xdg(ref xdg) => {
179                xdg.toplevel.unset_maximized();
180            }
181            Surface::Wl(ref wl) => {
182                wl.set_toplevel();
183            }
184        }
185    }
186
187    pub(crate) fn set_minimized(&self) {
188        match *self {
189            Surface::Xdg(ref xdg) => {
190                xdg.toplevel.set_minimized();
191            }
192            Surface::Wl(_) => { /* not available */ }
193        }
194    }
195
196    pub(crate) fn set_min_size(&self, size: Option<(i32, i32)>) {
197        if let Surface::Xdg(ref xdg) = *self {
198            let (w, h) = size.unwrap_or((0, 0));
199            xdg.toplevel.set_min_size(w, h);
200        }
201    }
202
203    pub(crate) fn set_max_size(&self, size: Option<(i32, i32)>) {
204        if let Surface::Xdg(ref xdg) = *self {
205            let (w, h) = size.unwrap_or((0, 0));
206            xdg.toplevel.set_max_size(w, h);
207        }
208    }
209}