wayland_protocols_async/zwlr_foreign_toplevel_management_v1/
handler.rs

1use std::{sync::Mutex};
2use slotmap::{new_key_type, SlotMap};
3use tokio::{sync::{mpsc::{Sender, Receiver}, oneshot}, io::unix::AsyncFd};
4use wayland_client::{EventQueue, protocol::{wl_seat::{WlSeat, self}, wl_registry::{WlRegistry, self}, wl_output::{WlOutput, self}}, globals::{self, GlobalListContents}, Connection, QueueHandle, Dispatch, event_created_child, Proxy};
5use wayland_protocols_wlr::foreign_toplevel::v1::client::{zwlr_foreign_toplevel_manager_v1::{ZwlrForeignToplevelManagerV1, self}, zwlr_foreign_toplevel_handle_v1::{ZwlrForeignToplevelHandleV1, self}};
6
7use super::errors::{ToplevelHandlerError, ToplevelHandlerErrorCodes};
8
9new_key_type! { pub struct ToplevelKey; }
10
11#[derive(Debug)]
12pub enum ToplevelMessage {
13    GetToplevels { reply_to: oneshot::Sender<Vec<ToplevelKey>> },
14    GetToplevelMeta { key: ToplevelKey, reply_to: oneshot::Sender<Option<ToplevelMeta>> },
15    Activate { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
16    SetFullscreen { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
17    SetMaximize { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
18    SetMinimize { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
19    UnsetFullscreen { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
20    UnsetMaximize { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
21    UnsetMinimize { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
22    Close { key: ToplevelKey, reply_to: oneshot::Sender<Result<bool, ToplevelHandlerError>> },
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub enum ToplevelWState {
27    Maximized = 0,
28    Minimized = 1,
29    Activated = 2,
30    Fullscreen = 3
31}
32
33fn map_state_to_wstate(state: Vec<u8>) -> Vec<ToplevelWState> {
34    let mut wstate: Vec<ToplevelWState> = vec![];
35    let mut state_iter = state
36    .chunks_exact(4)
37    .map(|b| u32::from_ne_bytes(b.try_into().unwrap()));
38
39    let is_maximized = state_iter.clone().any(|s| s == zwlr_foreign_toplevel_handle_v1::State::Maximized as u32);
40    let is_minimized = state_iter.clone().any(|s| s == zwlr_foreign_toplevel_handle_v1::State::Minimized as u32);
41    let is_activated = state_iter.clone().any(|s| s == zwlr_foreign_toplevel_handle_v1::State::Activated as u32);
42    let is_fullscreen = state_iter.clone().any(|s| s == zwlr_foreign_toplevel_handle_v1::State::Fullscreen as u32);
43
44    if is_maximized {
45        wstate.push(ToplevelWState::Maximized);
46    }
47    
48    if is_minimized {
49        wstate.push(ToplevelWState::Minimized);
50    }
51
52    if is_activated {
53        wstate.push(ToplevelWState::Activated);
54    }
55
56    if is_fullscreen {
57        wstate.push(ToplevelWState::Fullscreen);
58    }
59
60    println!("base state {:?} {:?} {:?}", state, wstate, is_activated);
61
62    wstate
63}
64
65#[derive(Debug)]
66pub enum ToplevelEvent {
67    Created { key: ToplevelKey },
68    Title { key: ToplevelKey, title: String },
69    AppId { key: ToplevelKey, app_id: String },
70    Done { key: ToplevelKey, title: String, app_id: String, state: Option<Vec<ToplevelWState>> },
71    State { key: ToplevelKey, state: Vec<ToplevelWState> },
72    Closed { key: ToplevelKey },
73    OutputEnter { key: ToplevelKey, output: WlOutput },
74    OutputLeave { key: ToplevelKey, output: WlOutput },
75    Parent { key: ToplevelKey, parent: Option<ZwlrForeignToplevelHandleV1> },
76}
77
78#[derive(Debug, Clone)]
79pub struct Toplevel {
80    pub title: String,
81    pub app_id: String,
82    pub state: Option<Vec<ToplevelWState>>,
83    _handle: ZwlrForeignToplevelHandleV1,
84}
85
86#[derive(Debug, Clone)]
87pub struct ToplevelMeta {
88    app_id: String,
89    title: String,
90    state: Option<Vec<ToplevelWState>>,
91}
92
93impl Toplevel {
94    fn new(handle: ZwlrForeignToplevelHandleV1) -> Self {
95        Toplevel {
96            title: "".to_string(),
97            app_id: "".to_string(),  // default
98            state: None,
99            _handle: handle,
100        }
101    }
102}
103
104
105pub struct ToplevelState {
106    event_tx: Sender<ToplevelEvent>,
107    seat: Option<WlSeat>,
108    output: Option<WlOutput>,
109    toplevels: SlotMap<ToplevelKey, Toplevel>,
110}
111
112pub struct ToplevelHandler {
113    event_queue: EventQueue<ToplevelState>,
114    state: ToplevelState,
115}
116
117impl ToplevelHandler {
118    pub fn new(event_tx: Sender<ToplevelEvent>) -> Self {
119        let conn = wayland_client::Connection::connect_to_env()
120            .map_err(|_| "could not connect to wayland socket, try setting WAYLAND_DISPLAY.")
121            .unwrap();
122        let (globals, mut event_queue) = globals::registry_queue_init::<ToplevelState>(&conn).unwrap();
123        let qh = event_queue.handle();
124
125        let _toplevel_manager = globals
126            .bind::<ZwlrForeignToplevelManagerV1, _, _>(&qh, core::ops::RangeInclusive::new(3, 3), ())
127            .map_err(|_| "compositor does not implement foreign toplevel manager (v3).").unwrap();
128
129        let seat = globals
130            .bind::<WlSeat, _, _>(&qh, core::ops::RangeInclusive::new(1, 1), ())
131            .map_err(|_| "failed to retrieve the seat from global.")
132            .unwrap();
133        let output = globals
134            .bind::<WlOutput, _, _>(&qh, core::ops::RangeInclusive::new(1, 1), ())
135            .map_err(|_| "failed to retrieve the output from global.")
136            .unwrap();
137
138        let mut state = ToplevelState {
139            event_tx,
140            seat: Some(seat),
141            output: Some(output),
142            toplevels: SlotMap::with_key(),
143        };
144
145        event_queue.roundtrip(&mut state).unwrap();
146    
147        ToplevelHandler {
148            event_queue,
149            state,
150        }
151    }
152
153    pub async fn run(&mut self, mut msg_rx: Receiver<ToplevelMessage>) {
154        let event_queue = &mut self.event_queue;
155        let mut toplevel_state = &mut self.state;
156    
157        loop {
158            // This would be required if other threads were reading from the socket.
159            event_queue.dispatch_pending(&mut toplevel_state).unwrap();
160            let read_guard = event_queue.prepare_read().unwrap();
161            let fd = read_guard.connection_fd();
162            let async_fd = AsyncFd::new(fd).unwrap();
163    
164            tokio::select! {
165                async_guard = async_fd.readable() => {
166                    async_guard.unwrap().clear_ready();
167                    // Drop the async_fd since it's holding a reference to the read_guard,
168                    // which is dropped on read. We don't need to read from it anyways.
169                    std::mem::drop(async_fd);
170                    // This should not block because we already ensured readiness
171                    let event = read_guard.read();
172                    match event {
173                        // There are events but another thread processed them, we don't need to dispatch
174                        Ok(0) => {},
175                        // We have some events
176                        Ok(_) => {
177                            event_queue.dispatch_pending(&mut toplevel_state).unwrap();
178                        },
179                        // No events to receive
180                        Err(_) => {}
181                        // Err(e) => eprintln!("error reading event {}", e),
182                    }
183                },
184                msg = msg_rx.recv() => {
185                    if msg.is_none() {
186                        continue;
187                    }
188                    match msg.unwrap() {
189                        ToplevelMessage::GetToplevels { reply_to } => {
190                            let _ = reply_to.send(toplevel_state.toplevels.keys().collect());
191                        },
192                        ToplevelMessage::GetToplevelMeta { key, reply_to } => {
193                            let toplevel_meta = match toplevel_state.toplevels.get(key) {
194                                Some(t) => Some(ToplevelMeta {
195                                    app_id: t.app_id.clone(),
196                                    title: t.title.clone(),
197                                    state: t.state.clone(),
198                                }),
199                                None => None,
200                            };
201                            let _ = reply_to.send(toplevel_meta);
202                        },
203                        ToplevelMessage::Activate { key, reply_to } => {
204                            let toplevel = toplevel_state.toplevels.get_mut(key);
205                            let result = match toplevel {
206                                Some(t) => {
207                                    if toplevel_state.seat.is_some() {
208                                        let seat = toplevel_state.seat.as_ref().unwrap();
209                                        t._handle.activate(&seat);
210                                    }
211                                    Ok(true)
212                                },
213                                None => {
214                                    Err(ToplevelHandlerError::new(
215                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
216                                        format!("toplevel not found")
217                                    ))
218                                },
219                            };
220                            let _ = reply_to.send(result);
221                        },
222                        ToplevelMessage::SetFullscreen { key, reply_to } => {
223                            let toplevel = toplevel_state.toplevels.get_mut(key);
224                            let output = toplevel_state.output.clone();
225                            let result = match toplevel {
226                                Some(t) => {
227                                    t._handle.set_fullscreen(output.as_ref());
228                                    Ok(true)
229                                },
230                                None => {
231                                    Err(ToplevelHandlerError::new(
232                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
233                                        format!("toplevel not found")
234                                    ))
235                                },
236                            };
237                            let _ = reply_to.send(result);
238                        },
239                        ToplevelMessage::SetMaximize { key, reply_to } => {
240                            let toplevel = toplevel_state.toplevels.get_mut(key);
241                            let result = match toplevel {
242                                Some(t) => {
243                                    t._handle.set_maximized();
244                                    Ok(true)
245                                },
246                                None => {
247                                    Err(ToplevelHandlerError::new(
248                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
249                                        format!("toplevel not found")
250                                    ))
251                                },
252                            };
253                            let _ = reply_to.send(result);
254                        },
255                        ToplevelMessage::SetMinimize { key, reply_to } => {
256                            let toplevel = toplevel_state.toplevels.get_mut(key);
257                            let result = match toplevel {
258                                Some(t) => {
259                                    t._handle.set_minimized();
260                                    Ok(true)
261                                },
262                                None => {
263                                    Err(ToplevelHandlerError::new(
264                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
265                                        format!("toplevel not found")
266                                    ))
267                                },
268                            };
269                            let _ = reply_to.send(result);
270                        },
271                        ToplevelMessage::UnsetFullscreen { key, reply_to } => {
272                            let toplevel = toplevel_state.toplevels.get_mut(key);
273                            let result = match toplevel {
274                                Some(t) => {
275                                    t._handle.unset_fullscreen();
276                                    Ok(true)
277                                },
278                                None => {
279                                    Err(ToplevelHandlerError::new(
280                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
281                                        format!("toplevel not found")
282                                    ))
283                                },
284                            };
285                            let _ = reply_to.send(result);
286                        },
287                        ToplevelMessage::UnsetMaximize { key, reply_to } => {
288                            let toplevel = toplevel_state.toplevels.get_mut(key);
289                            let result = match toplevel {
290                                Some(t) => {
291                                    t._handle.unset_maximized();
292                                    Ok(true)
293                                },
294                                None => {
295                                    Err(ToplevelHandlerError::new(
296                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
297                                        format!("toplevel not found")
298                                    ))
299                                },
300                            };
301                            let _ = reply_to.send(result);
302                        },
303                        ToplevelMessage::UnsetMinimize { key, reply_to } => {
304                            let toplevel = toplevel_state.toplevels.get_mut(key);
305                            let result = match toplevel {
306                                Some(t) => {
307                                    t._handle.unset_minimized();
308                                    Ok(true)
309                                },
310                                None => {
311                                    Err(ToplevelHandlerError::new(
312                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
313                                        format!("toplevel not found")
314                                    ))
315                                },
316                            };
317                            let _ = reply_to.send(result);
318                        },
319                        ToplevelMessage::Close { key, reply_to } => {
320                            let toplevel = toplevel_state.toplevels.get_mut(key);
321                            let result = match toplevel {
322                                Some(t) => {
323                                    t._handle.close();
324                                    Ok(true)
325                                },
326                                None => {
327                                    Err(ToplevelHandlerError::new(
328                                        ToplevelHandlerErrorCodes::ToplevelNotFound,
329                                        format!("toplevel not found")
330                                    ))
331                                },
332                            };
333                            let _ = reply_to.send(result);
334                        },
335                    }
336                }
337            }
338    
339            // Send any new messages to the socket.
340            let _ = event_queue.flush().expect("wayland connection closed");
341        }
342    }
343}
344
345impl ToplevelState {
346    fn dispatch_event(&self, event: ToplevelEvent) {
347        let tx = self.event_tx.clone();
348        tokio::task::spawn(async move {
349            let _ = tx.send(event).await;
350        });
351    }
352}
353
354impl Dispatch<WlRegistry, GlobalListContents> for ToplevelState {
355    fn event(
356        _: &mut Self,
357        registry: &wl_registry::WlRegistry,
358        event: wl_registry::Event,
359        _: &GlobalListContents,
360        _: &Connection,
361        qh: &QueueHandle<ToplevelState>,
362    ) {
363        if let wl_registry::Event::Global {
364            name,
365            interface,
366            version,
367        } = event
368        {
369            if interface == "wl_seat" {
370                registry.bind::<WlSeat, (), ToplevelState>(name, version, qh, ());
371            }
372        }
373    }
374}
375
376impl Dispatch<WlSeat, ()> for ToplevelState {
377    fn event(
378        state: &mut Self,
379        seat: &WlSeat,
380        event: wl_seat::Event,
381        _: &(),
382        _: &Connection,
383        _: &QueueHandle<ToplevelState>,
384    ) {
385        if let wl_seat::Event::Name { .. } = event {
386            state.seat = Some(seat.to_owned());
387        }
388    }
389}
390
391impl Dispatch<WlOutput, ()> for ToplevelState {
392    fn event(
393        state: &mut Self,
394        output: &WlOutput,
395        event: wl_output::Event,
396        _: &(),
397        _: &Connection,
398        _: &QueueHandle<ToplevelState>,
399    ) {
400        if let wl_output::Event::Name { .. } = event {
401            state.output = Some(output.to_owned());
402        }
403    }
404}
405
406
407impl Dispatch<ZwlrForeignToplevelManagerV1, ()> for ToplevelState {
408    fn event(
409        state: &mut Self,
410        _: &ZwlrForeignToplevelManagerV1,
411        event: <ZwlrForeignToplevelManagerV1 as wayland_client::Proxy>::Event,
412        _: &(),
413        _: &Connection,
414        _: &QueueHandle<Self>,
415    ) {
416        match event {
417            zwlr_foreign_toplevel_manager_v1::Event::Toplevel { toplevel } => {
418                let toplevel_data = Toplevel::new(toplevel.clone());
419
420                // insert to slotmap and get toplevel key
421                let toplevel_key = state.toplevels.insert(toplevel_data);
422
423                // Add user data as mutex of the toplevel_key
424                let user_data: &Mutex<Option<ToplevelKey>> = toplevel.data().unwrap();
425                *user_data.lock().unwrap() = Some(toplevel_key);
426
427                // toplevel.set_fullscreen(None);
428
429                // send event
430                state.dispatch_event(ToplevelEvent::Created { key: toplevel_key });
431            },
432            zwlr_foreign_toplevel_manager_v1::Event::Finished => {
433                // TODO: clear the states for toplevel and manager and send event for Finished
434            }
435            _ => (),
436        }
437    }
438
439    event_created_child!(Self, ZwlrForeignToplevelHandleV1, [
440        zwlr_foreign_toplevel_manager_v1::EVT_TOPLEVEL_OPCODE => (ZwlrForeignToplevelHandleV1, Mutex::new(None))
441    ]);
442}
443
444impl Dispatch<ZwlrForeignToplevelHandleV1, Mutex<Option<ToplevelKey>>> for ToplevelState {
445    fn event(
446        state: &mut Self,
447        _: &ZwlrForeignToplevelHandleV1,
448        event: <ZwlrForeignToplevelHandleV1 as Proxy>::Event,
449        key: &Mutex<Option<ToplevelKey>>,
450        _: &Connection,
451        _: &QueueHandle<Self>,
452    ) {
453        match event {
454            zwlr_foreign_toplevel_handle_v1::Event::Title { title } => {
455                let toplevel_key = key.lock().unwrap().unwrap();
456
457                let toplevel = state
458                    .toplevels
459                    .get_mut(toplevel_key)
460                    .unwrap();
461                toplevel.title = title.clone();
462
463                state.dispatch_event(ToplevelEvent::Title { key: toplevel_key, title });
464            },
465            zwlr_foreign_toplevel_handle_v1::Event::AppId { app_id } => {
466                let toplevel_key = key.lock().unwrap().unwrap();
467                let toplevel = state
468                    .toplevels
469                    .get_mut(toplevel_key)
470                    .unwrap();
471                toplevel.app_id = app_id.clone();
472
473                state.dispatch_event(ToplevelEvent::AppId { key: toplevel_key, app_id });
474            },
475            zwlr_foreign_toplevel_handle_v1::Event::State { state: toplevel_state } => {
476                let toplevel_key = key.lock().unwrap().unwrap();
477                let toplevel = state
478                    .toplevels
479                    .get_mut(toplevel_key)
480                    .unwrap();
481                let toplevel_state = map_state_to_wstate(toplevel_state);
482                toplevel.state = Some(toplevel_state.clone());
483
484                state.dispatch_event(ToplevelEvent::State { key: toplevel_key, state: toplevel_state.clone() });
485            },
486            zwlr_foreign_toplevel_handle_v1::Event::Done => {
487                let toplevel_key = key.lock().unwrap().unwrap();
488                let toplevel = state
489                    .toplevels
490                    .get_mut(toplevel_key)
491                    .unwrap();
492                let title = toplevel.title.clone();
493                let app_id = toplevel.app_id.clone();
494                let toplevel_state = toplevel.state.clone();
495
496                state.dispatch_event(ToplevelEvent::Done { key: toplevel_key, title, app_id, state: toplevel_state });
497            },
498            zwlr_foreign_toplevel_handle_v1::Event::Closed => {
499                let toplevel_key = key.lock().unwrap().unwrap();
500                let toplevel = state
501                    .toplevels
502                    .get_mut(toplevel_key)
503                    .unwrap();
504
505                // removing from state, you cannot use the toplevel after that
506                state.toplevels.remove(toplevel_key);
507                
508                state.dispatch_event(ToplevelEvent::Closed { key: toplevel_key });
509            },
510            zwlr_foreign_toplevel_handle_v1::Event::OutputEnter { output } => {
511                let toplevel_key = key.lock().unwrap().unwrap();
512                state.dispatch_event(ToplevelEvent::OutputEnter { key: toplevel_key, output });
513            },
514            zwlr_foreign_toplevel_handle_v1::Event::OutputLeave { output } => {
515                let toplevel_key = key.lock().unwrap().unwrap();
516                state.dispatch_event(ToplevelEvent::OutputLeave { key: toplevel_key, output });
517            },
518            zwlr_foreign_toplevel_handle_v1::Event::Parent { parent } => {
519                let toplevel_key = key.lock().unwrap().unwrap();
520                state.dispatch_event(ToplevelEvent::Parent { key: toplevel_key, parent });
521            },
522            _ => todo!(),
523        }
524    }
525}