1 //! SCTK environment setup.
2 
3 use sctk::reexports::client::protocol::wl_compositor::WlCompositor;
4 use sctk::reexports::client::protocol::wl_output::WlOutput;
5 use sctk::reexports::protocols::unstable::xdg_shell::v6::client::zxdg_shell_v6::ZxdgShellV6;
6 use sctk::reexports::client::protocol::wl_seat::WlSeat;
7 use sctk::reexports::protocols::unstable::xdg_decoration::v1::client::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1;
8 use sctk::reexports::client::protocol::wl_shell::WlShell;
9 use sctk::reexports::client::protocol::wl_subcompositor::WlSubcompositor;
10 use sctk::reexports::client::{Attached, DispatchData};
11 use sctk::reexports::client::protocol::wl_shm::WlShm;
12 use sctk::reexports::protocols::xdg_shell::client::xdg_wm_base::XdgWmBase;
13 use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1;
14 use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
15 use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
16 
17 use sctk::environment::{Environment, SimpleGlobal};
18 use sctk::output::{OutputHandler, OutputHandling, OutputInfo, OutputStatusListener};
19 use sctk::seat::{SeatData, SeatHandler, SeatHandling, SeatListener};
20 use sctk::shell::{Shell, ShellHandler, ShellHandling};
21 use sctk::shm::ShmHandler;
22 
23 /// Set of extra features that are supported by the compositor.
24 #[derive(Debug, Clone, Copy)]
25 pub struct WindowingFeatures {
26     cursor_grab: bool,
27 }
28 
29 impl WindowingFeatures {
30     /// Create `WindowingFeatures` based on the presented interfaces.
new(env: &Environment<WinitEnv>) -> Self31     pub fn new(env: &Environment<WinitEnv>) -> Self {
32         let cursor_grab = env.get_global::<ZwpPointerConstraintsV1>().is_some();
33         Self { cursor_grab }
34     }
35 
cursor_grab(&self) -> bool36     pub fn cursor_grab(&self) -> bool {
37         self.cursor_grab
38     }
39 }
40 
41 sctk::environment!(WinitEnv,
42     singles = [
43         WlShm => shm,
44         WlCompositor => compositor,
45         WlSubcompositor => subcompositor,
46         WlShell => shell,
47         XdgWmBase => shell,
48         ZxdgShellV6 => shell,
49         ZxdgDecorationManagerV1 => decoration_manager,
50         ZwpRelativePointerManagerV1 => relative_pointer_manager,
51         ZwpPointerConstraintsV1 => pointer_constraints,
52         ZwpTextInputManagerV3 => text_input_manager,
53     ],
54     multis = [
55         WlSeat => seats,
56         WlOutput => outputs,
57     ]
58 );
59 
60 /// The environment that we utilize.
61 pub struct WinitEnv {
62     seats: SeatHandler,
63 
64     outputs: OutputHandler,
65 
66     shm: ShmHandler,
67 
68     compositor: SimpleGlobal<WlCompositor>,
69 
70     subcompositor: SimpleGlobal<WlSubcompositor>,
71 
72     shell: ShellHandler,
73 
74     relative_pointer_manager: SimpleGlobal<ZwpRelativePointerManagerV1>,
75 
76     pointer_constraints: SimpleGlobal<ZwpPointerConstraintsV1>,
77 
78     text_input_manager: SimpleGlobal<ZwpTextInputManagerV3>,
79 
80     decoration_manager: SimpleGlobal<ZxdgDecorationManagerV1>,
81 }
82 
83 impl WinitEnv {
new() -> Self84     pub fn new() -> Self {
85         // Output tracking for available_monitors, etc.
86         let outputs = OutputHandler::new();
87 
88         // Keyboard/Pointer/Touch input.
89         let seats = SeatHandler::new();
90 
91         // Essential globals.
92         let shm = ShmHandler::new();
93         let compositor = SimpleGlobal::new();
94         let subcompositor = SimpleGlobal::new();
95 
96         // Gracefully handle shell picking, since SCTK automatically supports multiple
97         // backends.
98         let shell = ShellHandler::new();
99 
100         // Server side decorations.
101         let decoration_manager = SimpleGlobal::new();
102 
103         // Device events for pointer.
104         let relative_pointer_manager = SimpleGlobal::new();
105 
106         // Pointer grab functionality.
107         let pointer_constraints = SimpleGlobal::new();
108 
109         // IME handling.
110         let text_input_manager = SimpleGlobal::new();
111 
112         Self {
113             seats,
114             outputs,
115             shm,
116             compositor,
117             subcompositor,
118             shell,
119             decoration_manager,
120             relative_pointer_manager,
121             pointer_constraints,
122             text_input_manager,
123         }
124     }
125 }
126 
127 impl ShellHandling for WinitEnv {
get_shell(&self) -> Option<Shell>128     fn get_shell(&self) -> Option<Shell> {
129         self.shell.get_shell()
130     }
131 }
132 
133 impl SeatHandling for WinitEnv {
listen<F: FnMut(Attached<WlSeat>, &SeatData, DispatchData<'_>) + 'static>( &mut self, f: F, ) -> SeatListener134     fn listen<F: FnMut(Attached<WlSeat>, &SeatData, DispatchData<'_>) + 'static>(
135         &mut self,
136         f: F,
137     ) -> SeatListener {
138         self.seats.listen(f)
139     }
140 }
141 
142 impl OutputHandling for WinitEnv {
listen<F: FnMut(WlOutput, &OutputInfo, DispatchData<'_>) + 'static>( &mut self, f: F, ) -> OutputStatusListener143     fn listen<F: FnMut(WlOutput, &OutputInfo, DispatchData<'_>) + 'static>(
144         &mut self,
145         f: F,
146     ) -> OutputStatusListener {
147         self.outputs.listen(f)
148     }
149 }
150