smithay/wayland/xdg_activation/
dispatch.rs
1use std::sync::{
2 atomic::{AtomicBool, Ordering},
3 Mutex,
4};
5
6use wayland_protocols::xdg::activation::v1::server::{xdg_activation_token_v1, xdg_activation_v1};
7use wayland_server::{
8 backend::ClientId, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
9};
10
11use super::{
12 ActivationTokenData, TokenBuilder, XdgActivationHandler, XdgActivationState, XdgActivationTokenData,
13};
14
15impl<D> Dispatch<xdg_activation_v1::XdgActivationV1, (), D> for XdgActivationState
16where
17 D: Dispatch<xdg_activation_v1::XdgActivationV1, ()>
18 + Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ActivationTokenData>
19 + XdgActivationHandler
20 + 'static,
21{
22 fn request(
23 state: &mut D,
24 _: &Client,
25 _: &xdg_activation_v1::XdgActivationV1,
26 request: xdg_activation_v1::Request,
27 _: &(),
28 _dh: &DisplayHandle,
29 data_init: &mut DataInit<'_, D>,
30 ) {
31 match request {
32 xdg_activation_v1::Request::Destroy => {}
33
34 xdg_activation_v1::Request::GetActivationToken { id } => {
35 data_init.init(
36 id,
37 ActivationTokenData {
38 constructed: AtomicBool::new(false),
39 build: Mutex::new(TokenBuilder {
40 serial: None,
41 app_id: None,
42 surface: None,
43 }),
44 token: Mutex::new(None),
45 },
46 );
47 }
48
49 xdg_activation_v1::Request::Activate { token, surface } => {
50 let token = token.into();
51
52 let activation_state = state.activation_state();
53
54 if let Some(token_data) = activation_state.known_tokens.get(&token).cloned() {
55 state.request_activation(token, token_data, surface);
56 }
57 }
58
59 _ => unreachable!(),
60 }
61 }
62}
63
64impl<D> GlobalDispatch<xdg_activation_v1::XdgActivationV1, (), D> for XdgActivationState
65where
66 D: GlobalDispatch<xdg_activation_v1::XdgActivationV1, ()>
67 + Dispatch<xdg_activation_v1::XdgActivationV1, ()>
68 + Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ActivationTokenData>
69 + XdgActivationHandler
70 + 'static,
71{
72 fn bind(
73 _: &mut D,
74 _: &DisplayHandle,
75 _: &Client,
76 resource: New<xdg_activation_v1::XdgActivationV1>,
77 _: &(),
78 data_init: &mut DataInit<'_, D>,
79 ) {
80 data_init.init(resource, ());
81 }
82}
83
84impl<D> Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ActivationTokenData, D> for XdgActivationState
85where
86 D: Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ActivationTokenData> + XdgActivationHandler,
87{
88 fn request(
89 state: &mut D,
90 client: &Client,
91 token: &xdg_activation_token_v1::XdgActivationTokenV1,
92 request: xdg_activation_token_v1::Request,
93 data: &ActivationTokenData,
94 _dh: &DisplayHandle,
95 _: &mut DataInit<'_, D>,
96 ) {
97 match request {
98 xdg_activation_token_v1::Request::SetSerial { serial, seat } => {
99 if data.constructed.load(Ordering::Relaxed) {
100 token.post_error(
101 xdg_activation_token_v1::Error::AlreadyUsed,
102 "The activation token has already been constructed",
103 );
104 return;
105 }
106
107 data.build.lock().unwrap().serial = Some((serial.into(), seat));
108 }
109
110 xdg_activation_token_v1::Request::SetAppId { app_id } => {
111 if data.constructed.load(Ordering::Relaxed) {
112 token.post_error(
113 xdg_activation_token_v1::Error::AlreadyUsed,
114 "The activation token has already been constructed",
115 );
116 return;
117 }
118
119 data.build.lock().unwrap().app_id = Some(app_id);
120 }
121
122 xdg_activation_token_v1::Request::SetSurface { surface } => {
123 if data.constructed.load(Ordering::Relaxed) {
124 token.post_error(
125 xdg_activation_token_v1::Error::AlreadyUsed,
126 "The activation token has already been constructed",
127 );
128 return;
129 }
130
131 data.build.lock().unwrap().surface = Some(surface);
132 }
133
134 xdg_activation_token_v1::Request::Commit => {
135 if data.constructed.load(Ordering::Relaxed) {
136 token.post_error(
137 xdg_activation_token_v1::Error::AlreadyUsed,
138 "The activation token has already been constructed",
139 );
140 return;
141 }
142
143 data.constructed.store(true, Ordering::Relaxed);
144
145 let (activation_token, token_data) = {
146 let mut guard = data.build.lock().unwrap();
147
148 XdgActivationTokenData::new(
149 Some(client.id()),
150 guard.serial.take(),
151 guard.app_id.take(),
152 guard.surface.take(),
153 )
154 };
155
156 let valid = state.token_created(activation_token.clone(), token_data.clone());
157
158 *data.token.lock().unwrap() = Some(activation_token.clone());
159 if valid {
160 state
161 .activation_state()
162 .known_tokens
163 .insert(activation_token.clone(), token_data);
164 }
165 token.done(activation_token.to_string());
166 }
167
168 xdg_activation_token_v1::Request::Destroy => {}
169
170 _ => unreachable!(),
171 }
172 }
173
174 fn destroyed(
175 _: &mut D,
176 _: ClientId,
177 _: &xdg_activation_token_v1::XdgActivationTokenV1,
178 _: &ActivationTokenData,
179 ) {
180 }
181}