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