1 use std::{cell::RefCell, convert::TryInto, rc::Rc}; 2 3 use wayland_client::{ 4 protocol::{wl_output, wl_seat, wl_surface}, 5 DispatchData, 6 }; 7 8 use wayland_protocols::xdg_shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base}; 9 10 use super::{Event, ShellSurface}; 11 12 pub(crate) struct Xdg { 13 surface: xdg_surface::XdgSurface, 14 toplevel: xdg_toplevel::XdgToplevel, 15 } 16 17 impl Xdg { create<Impl>( surface: &wl_surface::WlSurface, shell: &xdg_wm_base::XdgWmBase, implementation: Impl, ) -> Xdg where Impl: FnMut(Event, DispatchData) + 'static,18 pub(crate) fn create<Impl>( 19 surface: &wl_surface::WlSurface, 20 shell: &xdg_wm_base::XdgWmBase, 21 implementation: Impl, 22 ) -> Xdg 23 where 24 Impl: FnMut(Event, DispatchData) + 'static, 25 { 26 let pending_configure = Rc::new(RefCell::new(None)); 27 let pending_configure_2 = pending_configure.clone(); 28 29 let implementation = Rc::new(RefCell::new(implementation)); 30 let implementation_2 = implementation.clone(); 31 let xdgs = shell.get_xdg_surface(surface); 32 xdgs.quick_assign(move |xdgs, evt, ddata| match evt { 33 xdg_surface::Event::Configure { serial } => { 34 xdgs.ack_configure(serial); 35 if let Some((new_size, states)) = pending_configure_2.borrow_mut().take() { 36 (&mut *implementation_2.borrow_mut())( 37 Event::Configure { new_size, states }, 38 ddata, 39 ); 40 } 41 } 42 _ => unreachable!(), 43 }); 44 let toplevel = xdgs.get_toplevel(); 45 toplevel.quick_assign(move |_, evt, ddata| { 46 match evt { 47 xdg_toplevel::Event::Close => { 48 (&mut *implementation.borrow_mut())(Event::Close, ddata) 49 } 50 xdg_toplevel::Event::Configure { width, height, states } => { 51 use std::cmp::max; 52 let new_size = if width == 0 || height == 0 { 53 // if either w or h is zero, then we get to choose our size 54 None 55 } else { 56 Some((max(width, 1) as u32, max(height, 1) as u32)) 57 }; 58 let translated_states = states 59 .chunks_exact(4) 60 .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) 61 .flat_map(xdg_toplevel::State::from_raw) 62 .collect::<Vec<_>>(); 63 64 *pending_configure.borrow_mut() = Some((new_size, translated_states)); 65 } 66 _ => unreachable!(), 67 } 68 }); 69 surface.commit(); 70 Xdg { surface: xdgs.detach(), toplevel: toplevel.detach() } 71 } 72 } 73 74 impl ShellSurface for Xdg { resize(&self, seat: &wl_seat::WlSeat, serial: u32, edges: xdg_toplevel::ResizeEdge)75 fn resize(&self, seat: &wl_seat::WlSeat, serial: u32, edges: xdg_toplevel::ResizeEdge) { 76 self.toplevel.resize(seat, serial, edges); 77 } 78 move_(&self, seat: &wl_seat::WlSeat, serial: u32)79 fn move_(&self, seat: &wl_seat::WlSeat, serial: u32) { 80 self.toplevel._move(seat, serial); 81 } 82 set_title(&self, title: String)83 fn set_title(&self, title: String) { 84 self.toplevel.set_title(title); 85 } 86 set_app_id(&self, app_id: String)87 fn set_app_id(&self, app_id: String) { 88 self.toplevel.set_app_id(app_id); 89 } 90 set_fullscreen(&self, output: Option<&wl_output::WlOutput>)91 fn set_fullscreen(&self, output: Option<&wl_output::WlOutput>) { 92 self.toplevel.set_fullscreen(output) 93 } 94 unset_fullscreen(&self)95 fn unset_fullscreen(&self) { 96 self.toplevel.unset_fullscreen(); 97 } 98 set_maximized(&self)99 fn set_maximized(&self) { 100 self.toplevel.set_maximized(); 101 } 102 unset_maximized(&self)103 fn unset_maximized(&self) { 104 self.toplevel.unset_maximized(); 105 } 106 set_minimized(&self)107 fn set_minimized(&self) { 108 self.toplevel.set_minimized(); 109 } 110 show_window_menu(&self, seat: &wl_seat::WlSeat, serial: u32, x: i32, y: i32)111 fn show_window_menu(&self, seat: &wl_seat::WlSeat, serial: u32, x: i32, y: i32) { 112 self.toplevel.show_window_menu(seat, serial, x, y); 113 } 114 set_geometry(&self, x: i32, y: i32, width: i32, height: i32)115 fn set_geometry(&self, x: i32, y: i32, width: i32, height: i32) { 116 self.surface.set_window_geometry(x, y, width, height); 117 } 118 set_min_size(&self, size: Option<(i32, i32)>)119 fn set_min_size(&self, size: Option<(i32, i32)>) { 120 if let Some((w, h)) = size { 121 self.toplevel.set_min_size(w, h); 122 } else { 123 self.toplevel.set_min_size(0, 0); 124 } 125 } 126 set_max_size(&self, size: Option<(i32, i32)>)127 fn set_max_size(&self, size: Option<(i32, i32)>) { 128 if let Some((w, h)) = size { 129 self.toplevel.set_max_size(w, h); 130 } else { 131 self.toplevel.set_max_size(0, 0); 132 } 133 } 134 get_xdg(&self) -> Option<&xdg_toplevel::XdgToplevel>135 fn get_xdg(&self) -> Option<&xdg_toplevel::XdgToplevel> { 136 Some(&self.toplevel) 137 } 138 } 139 140 impl Drop for Xdg { drop(&mut self)141 fn drop(&mut self) { 142 self.toplevel.destroy(); 143 self.surface.destroy(); 144 } 145 } 146