layer_shika_adapters/wayland/surfaces/
app_state.rs

1use super::event_context::SharedPointerSerial;
2use super::keyboard_state::KeyboardState;
3use super::surface_state::SurfaceState;
4use crate::errors::{LayerShikaError, RenderingError, Result};
5use crate::rendering::egl::context_factory::RenderContextFactory;
6use crate::rendering::femtovg::renderable_window::RenderableWindow;
7use crate::rendering::slint_integration::platform::CustomSlintPlatform;
8use crate::wayland::globals::context::GlobalContext;
9use crate::wayland::input::KeyboardInputState;
10use crate::wayland::managed_proxies::{ManagedWlKeyboard, ManagedWlPointer};
11use crate::wayland::outputs::{OutputManager, OutputMapping};
12use crate::wayland::rendering::RenderableSet;
13use crate::wayland::session_lock::lock_context::SessionLockContext;
14use crate::wayland::session_lock::manager::callbacks::{
15    create_lock_callback, create_lock_callback_with_output_filter,
16};
17use crate::wayland::session_lock::{
18    LockCallback, LockPropertyOperation, OutputFilter, SessionLockManager,
19};
20use layer_shika_domain::entities::output_registry::OutputRegistry;
21use layer_shika_domain::value_objects::handle::SurfaceHandle;
22use layer_shika_domain::value_objects::lock_config::LockConfig;
23use layer_shika_domain::value_objects::lock_state::LockState;
24use layer_shika_domain::value_objects::output_handle::OutputHandle;
25use layer_shika_domain::value_objects::output_info::OutputInfo;
26use slint_interpreter::{CompilationResult, ComponentDefinition, Value};
27use std::cell::RefCell;
28use std::collections::HashMap;
29use std::os::fd::BorrowedFd;
30use std::rc::Rc;
31use wayland_client::Proxy;
32use wayland_client::backend::ObjectId;
33use wayland_client::protocol::wl_keyboard;
34use wayland_client::protocol::{wl_output::WlOutput, wl_surface::WlSurface};
35use xkbcommon::xkb;
36
37pub type PerOutputSurface = SurfaceState;
38type SessionLockCallback = Rc<dyn Fn(&[Value]) -> Value>;
39
40#[derive(Debug, Clone, PartialEq, Eq, Hash)]
41pub struct ShellSurfaceKey {
42    pub output_handle: OutputHandle,
43    pub surface_handle: SurfaceHandle,
44}
45
46impl ShellSurfaceKey {
47    pub const fn new(output_handle: OutputHandle, surface_handle: SurfaceHandle) -> Self {
48        Self {
49            output_handle,
50            surface_handle,
51        }
52    }
53}
54
55pub struct AppState {
56    global_context: Option<Rc<GlobalContext>>,
57    known_outputs: Vec<WlOutput>,
58    slint_platform: Option<Rc<CustomSlintPlatform>>,
59    compilation_result: Option<Rc<CompilationResult>>,
60    output_registry: OutputRegistry,
61    output_mapping: OutputMapping,
62    surfaces: HashMap<ShellSurfaceKey, PerOutputSurface>,
63    surface_to_key: HashMap<ObjectId, ShellSurfaceKey>,
64    surface_handle_to_name: HashMap<SurfaceHandle, String>,
65    _pointer: ManagedWlPointer,
66    _keyboard: ManagedWlKeyboard,
67    shared_pointer_serial: Rc<SharedPointerSerial>,
68    output_manager: Option<Rc<RefCell<OutputManager>>>,
69    registry_name_to_output_id: HashMap<u32, ObjectId>,
70    active_surface_key: Option<ShellSurfaceKey>,
71    keyboard_focus_key: Option<ShellSurfaceKey>,
72    keyboard_input_state: KeyboardInputState,
73    keyboard_state: KeyboardState,
74    lock_manager: Option<SessionLockManager>,
75    lock_callbacks: Vec<LockCallback>,
76    lock_property_operations: Vec<LockPropertyOperation>,
77    queue_handle: Option<wayland_client::QueueHandle<AppState>>,
78}
79
80impl AppState {
81    pub fn new(
82        pointer: ManagedWlPointer,
83        keyboard: ManagedWlKeyboard,
84        shared_serial: Rc<SharedPointerSerial>,
85    ) -> Self {
86        Self {
87            global_context: None,
88            known_outputs: Vec::new(),
89            slint_platform: None,
90            compilation_result: None,
91            output_registry: OutputRegistry::new(),
92            output_mapping: OutputMapping::new(),
93            surfaces: HashMap::new(),
94            surface_to_key: HashMap::new(),
95            surface_handle_to_name: HashMap::new(),
96            _pointer: pointer,
97            _keyboard: keyboard,
98            shared_pointer_serial: shared_serial,
99            output_manager: None,
100            registry_name_to_output_id: HashMap::new(),
101            active_surface_key: None,
102            keyboard_focus_key: None,
103            keyboard_input_state: KeyboardInputState::new(),
104            keyboard_state: KeyboardState::new(),
105            lock_manager: None,
106            lock_callbacks: Vec::new(),
107            lock_property_operations: Vec::new(),
108            queue_handle: None,
109        }
110    }
111
112    pub fn set_global_context(&mut self, context: Rc<GlobalContext>) {
113        self.known_outputs.clone_from(&context.outputs);
114        self.global_context = Some(context);
115    }
116
117    pub fn set_slint_platform(&mut self, platform: Rc<CustomSlintPlatform>) {
118        self.slint_platform = Some(platform);
119    }
120
121    pub fn set_compilation_result(&mut self, compilation_result: Rc<CompilationResult>) {
122        self.compilation_result = Some(compilation_result);
123    }
124
125    pub fn set_queue_handle(&mut self, queue_handle: wayland_client::QueueHandle<AppState>) {
126        self.queue_handle = Some(queue_handle);
127    }
128
129    pub fn lock_manager(&self) -> Option<&SessionLockManager> {
130        self.lock_manager.as_ref()
131    }
132
133    pub fn lock_manager_mut(&mut self) -> Option<&mut SessionLockManager> {
134        self.lock_manager.as_mut()
135    }
136
137    pub fn clear_lock_manager(&mut self) {
138        self.lock_manager = None;
139    }
140
141    pub fn is_session_lock_available(&self) -> bool {
142        self.global_context
143            .as_ref()
144            .and_then(|ctx| ctx.session_lock_manager.as_ref())
145            .is_some()
146    }
147
148    pub fn current_lock_state(&self) -> Option<LockState> {
149        self.lock_manager.as_ref().map(SessionLockManager::state)
150    }
151
152    pub fn register_session_lock_callback(
153        &mut self,
154        callback_name: impl Into<String>,
155        handler: SessionLockCallback,
156    ) {
157        let callback = create_lock_callback(callback_name, handler);
158        if let Some(manager) = self.lock_manager.as_mut() {
159            manager.register_callback(callback.clone());
160        }
161        self.lock_callbacks.push(callback);
162    }
163
164    pub fn register_session_lock_callback_with_filter(
165        &mut self,
166        callback_name: impl Into<String>,
167        handler: SessionLockCallback,
168        filter: OutputFilter,
169    ) {
170        let callback = create_lock_callback_with_output_filter(
171            callback_name,
172            handler,
173            move |component_name, output_handle, output_info, primary, active| {
174                filter(component_name, output_handle, output_info, primary, active)
175            },
176        );
177        if let Some(manager) = self.lock_manager.as_mut() {
178            manager.register_callback(callback.clone());
179        }
180        self.lock_callbacks.push(callback);
181    }
182
183    pub fn register_session_lock_property_operation(
184        &mut self,
185        property_operation: LockPropertyOperation,
186    ) {
187        if let Some(manager) = self.lock_manager.as_mut() {
188            manager.register_property_operation(property_operation.clone());
189        }
190        self.lock_property_operations.push(property_operation);
191    }
192
193    pub fn activate_session_lock(
194        &mut self,
195        component_name: &str,
196        config: LockConfig,
197    ) -> Result<()> {
198        if self.lock_manager.is_some() {
199            return Err(LayerShikaError::InvalidInput {
200                message: "Session lock already active".to_string(),
201            });
202        }
203
204        let queue_handle =
205            self.queue_handle
206                .as_ref()
207                .ok_or_else(|| LayerShikaError::InvalidInput {
208                    message: "Queue handle not initialized".to_string(),
209                })?;
210
211        let context = self.create_lock_context()?;
212        let (definition, compilation_result) = self.resolve_lock_component(component_name)?;
213        let platform =
214            self.slint_platform
215                .as_ref()
216                .ok_or_else(|| LayerShikaError::InvalidInput {
217                    message: "Slint platform not initialized".to_string(),
218                })?;
219        let mut manager = SessionLockManager::new(
220            context,
221            definition,
222            compilation_result,
223            Rc::clone(platform),
224            config,
225        );
226        for callback in self.lock_callbacks.iter().cloned() {
227            manager.register_callback(callback);
228        }
229        for property_op in self.lock_property_operations.iter().cloned() {
230            manager.register_property_operation(property_op);
231        }
232
233        let outputs = self.collect_session_lock_outputs();
234        manager.activate(outputs, queue_handle)?;
235
236        self.lock_manager = Some(manager);
237        Ok(())
238    }
239
240    pub fn deactivate_session_lock(&mut self) -> Result<()> {
241        let Some(mut manager) = self.lock_manager.take() else {
242            return Err(LayerShikaError::InvalidInput {
243                message: "No session lock active".to_string(),
244            });
245        };
246
247        manager.deactivate()?;
248        Ok(())
249    }
250
251    pub fn session_lock_component_name(&self) -> Option<String> {
252        self.lock_manager
253            .as_ref()
254            .map(|manager| manager.component_name().name().to_string())
255    }
256
257    pub fn iter_lock_surfaces(
258        &self,
259        f: &mut dyn FnMut(OutputHandle, &slint_interpreter::ComponentInstance),
260    ) {
261        if let Some(manager) = self.lock_manager.as_ref() {
262            manager.iter_lock_surfaces(&mut |output_id, component| {
263                if let Some(handle) = self.output_mapping.get(output_id) {
264                    f(handle, component);
265                }
266            });
267        }
268    }
269
270    pub fn count_lock_surfaces(&self) -> usize {
271        self.lock_manager
272            .as_ref()
273            .map_or(0, SessionLockManager::count_lock_surfaces)
274    }
275
276    fn resolve_lock_component(
277        &self,
278        component_name: &str,
279    ) -> Result<(ComponentDefinition, Option<Rc<CompilationResult>>)> {
280        let compilation_result = self
281            .compilation_result
282            .clone()
283            .or_else(|| {
284                self.primary_output()
285                    .and_then(SurfaceState::compilation_result)
286            })
287            .ok_or_else(|| LayerShikaError::InvalidInput {
288                message: "No compilation result available for session lock".to_string(),
289            })?;
290
291        let definition = compilation_result
292            .component(component_name)
293            .ok_or_else(|| LayerShikaError::InvalidInput {
294                message: format!("Component '{component_name}' not found in compilation result"),
295            })?;
296
297        Ok((definition, Some(compilation_result)))
298    }
299
300    fn create_lock_context(&self) -> Result<Rc<SessionLockContext>> {
301        let Some(global_ctx) = self.global_context.as_ref() else {
302            return Err(LayerShikaError::InvalidInput {
303                message: "Global context not available for session lock".to_string(),
304            });
305        };
306
307        let Some(lock_manager) = global_ctx.session_lock_manager.as_ref() else {
308            return Err(LayerShikaError::InvalidInput {
309                message: "Session lock protocol not available".to_string(),
310            });
311        };
312
313        let render_factory =
314            RenderContextFactory::new(Rc::clone(&global_ctx.render_context_manager));
315
316        Ok(Rc::new(SessionLockContext::new(
317            global_ctx.compositor.clone(),
318            lock_manager.clone(),
319            global_ctx.seat.clone(),
320            global_ctx.fractional_scale_manager.clone(),
321            global_ctx.viewporter.clone(),
322            render_factory,
323        )))
324    }
325
326    fn collect_session_lock_outputs(&self) -> Vec<WlOutput> {
327        self.known_outputs.clone()
328    }
329
330    pub fn handle_output_added_for_lock(
331        &mut self,
332        output: &WlOutput,
333        queue_handle: &wayland_client::QueueHandle<AppState>,
334    ) -> Result<()> {
335        if !self
336            .known_outputs
337            .iter()
338            .any(|known| known.id() == output.id())
339        {
340            self.known_outputs.push(output.clone());
341        }
342
343        let Some(manager) = self.lock_manager.as_mut() else {
344            return Ok(());
345        };
346
347        if manager.state() == LockState::Locked {
348            manager.add_output(output, queue_handle)?;
349        }
350
351        Ok(())
352    }
353
354    pub fn handle_output_removed_for_lock(&mut self, output_id: &ObjectId) {
355        self.known_outputs
356            .retain(|output| output.id() != *output_id);
357        if let Some(manager) = self.lock_manager.as_mut() {
358            manager.remove_output(output_id);
359        }
360    }
361
362    pub fn set_output_manager(&mut self, manager: Rc<RefCell<OutputManager>>) {
363        self.output_manager = Some(manager);
364    }
365
366    pub fn output_manager(&self) -> Option<Rc<RefCell<OutputManager>>> {
367        self.output_manager.as_ref().map(Rc::clone)
368    }
369
370    pub fn register_registry_name(&mut self, name: u32, output_id: ObjectId) {
371        self.registry_name_to_output_id.insert(name, output_id);
372    }
373
374    pub fn find_output_id_by_registry_name(&self, name: u32) -> Option<ObjectId> {
375        self.registry_name_to_output_id.get(&name).cloned()
376    }
377
378    pub fn unregister_registry_name(&mut self, name: u32) -> Option<ObjectId> {
379        self.registry_name_to_output_id.remove(&name)
380    }
381
382    pub fn add_shell_surface(
383        &mut self,
384        output_id: &ObjectId,
385        surface_handle: SurfaceHandle,
386        surface_name: &str,
387        main_surface_id: ObjectId,
388        surface_state: PerOutputSurface,
389    ) {
390        let handle = self.output_mapping.get(output_id).unwrap_or_else(|| {
391            let h = self.output_mapping.insert(output_id.clone());
392            let is_primary = self.output_registry.is_empty();
393            let mut info = OutputInfo::new(h);
394            info.set_primary(is_primary);
395            self.output_registry.add(info);
396            h
397        });
398
399        let key = ShellSurfaceKey::new(handle, surface_handle);
400        self.surface_to_key.insert(main_surface_id, key.clone());
401        self.surfaces.insert(key, surface_state);
402        self.surface_handle_to_name
403            .insert(surface_handle, surface_name.to_string());
404    }
405
406    pub fn add_output(
407        &mut self,
408        output_id: &ObjectId,
409        surface_handle: SurfaceHandle,
410        surface_name: &str,
411        main_surface_id: ObjectId,
412        surface_state: PerOutputSurface,
413    ) {
414        self.add_shell_surface(
415            output_id,
416            surface_handle,
417            surface_name,
418            main_surface_id,
419            surface_state,
420        );
421    }
422
423    pub fn remove_output(&mut self, handle: OutputHandle) -> Vec<PerOutputSurface> {
424        self.output_registry.remove(handle);
425
426        let keys_to_remove: Vec<_> = self
427            .surfaces
428            .keys()
429            .filter(|k| k.output_handle == handle)
430            .cloned()
431            .collect();
432
433        let mut removed = Vec::new();
434        for key in keys_to_remove {
435            if let Some(surface) = self.surfaces.remove(&key) {
436                removed.push(surface);
437            }
438        }
439
440        self.surface_to_key.retain(|_, k| k.output_handle != handle);
441
442        removed
443    }
444
445    pub fn get_surface_by_key(&self, key: &ShellSurfaceKey) -> Option<&PerOutputSurface> {
446        self.surfaces.get(key)
447    }
448
449    pub fn get_surface_by_key_mut(
450        &mut self,
451        key: &ShellSurfaceKey,
452    ) -> Option<&mut PerOutputSurface> {
453        self.surfaces.get_mut(key)
454    }
455
456    pub fn get_surface_by_instance(
457        &self,
458        surface_handle: SurfaceHandle,
459        output_handle: OutputHandle,
460    ) -> Option<&PerOutputSurface> {
461        let key = ShellSurfaceKey::new(output_handle, surface_handle);
462        self.surfaces.get(&key)
463    }
464
465    pub fn get_surface_by_instance_mut(
466        &mut self,
467        surface_handle: SurfaceHandle,
468        output_handle: OutputHandle,
469    ) -> Option<&mut PerOutputSurface> {
470        let key = ShellSurfaceKey::new(output_handle, surface_handle);
471        self.surfaces.get_mut(&key)
472    }
473
474    pub fn get_output_by_output_id(&self, output_id: &ObjectId) -> Option<&PerOutputSurface> {
475        self.output_mapping
476            .get(output_id)
477            .and_then(|handle| self.get_first_surface_for_output(handle))
478    }
479
480    pub fn get_output_by_output_id_mut(
481        &mut self,
482        output_id: &ObjectId,
483    ) -> Option<&mut PerOutputSurface> {
484        self.output_mapping
485            .get(output_id)
486            .and_then(|handle| self.get_first_surface_for_output_mut(handle))
487    }
488
489    fn get_first_surface_for_output(&self, handle: OutputHandle) -> Option<&PerOutputSurface> {
490        self.surfaces
491            .iter()
492            .find(|(k, _)| k.output_handle == handle)
493            .map(|(_, v)| v)
494    }
495
496    fn get_first_surface_for_output_mut(
497        &mut self,
498        handle: OutputHandle,
499    ) -> Option<&mut PerOutputSurface> {
500        self.surfaces
501            .iter_mut()
502            .find(|(k, _)| k.output_handle == handle)
503            .map(|(_, v)| v)
504    }
505
506    pub fn get_output_by_surface(&self, surface_id: &ObjectId) -> Option<&PerOutputSurface> {
507        self.surface_to_key
508            .get(surface_id)
509            .and_then(|key| self.surfaces.get(key))
510    }
511
512    pub fn get_output_by_surface_mut(
513        &mut self,
514        surface_id: &ObjectId,
515    ) -> Option<&mut PerOutputSurface> {
516        self.surface_to_key
517            .get(surface_id)
518            .and_then(|key| self.surfaces.get_mut(key))
519    }
520
521    pub fn get_output_by_layer_surface_mut(
522        &mut self,
523        layer_surface_id: &ObjectId,
524    ) -> Option<&mut PerOutputSurface> {
525        self.surfaces
526            .values_mut()
527            .find(|surface| surface.layer_surface().as_ref().id() == *layer_surface_id)
528    }
529
530    pub fn get_surface_name(&self, surface_handle: SurfaceHandle) -> Option<&str> {
531        self.surface_handle_to_name
532            .get(&surface_handle)
533            .map(String::as_str)
534    }
535
536    pub fn get_key_by_surface(&self, surface_id: &ObjectId) -> Option<&ShellSurfaceKey> {
537        self.surface_to_key.get(surface_id)
538    }
539
540    pub fn get_handle_by_surface(&self, surface_id: &ObjectId) -> Option<OutputHandle> {
541        self.surface_to_key
542            .get(surface_id)
543            .map(|key| key.output_handle)
544    }
545
546    pub fn get_handle_by_output_id(&self, output_id: &ObjectId) -> Option<OutputHandle> {
547        self.output_mapping.get(output_id)
548    }
549
550    pub fn ensure_output_registered(&mut self, output_id: &ObjectId) -> OutputHandle {
551        self.output_mapping.get(output_id).unwrap_or_else(|| {
552            let h = self.output_mapping.insert(output_id.clone());
553            let is_primary = self.output_registry.is_empty();
554            let mut info = OutputInfo::new(h);
555            info.set_primary(is_primary);
556            self.output_registry.add(info);
557            h
558        })
559    }
560
561    pub fn set_active_output_handle(&mut self, handle: Option<OutputHandle>) {
562        self.output_registry.set_active(handle);
563    }
564
565    pub fn active_output_handle(&self) -> Option<OutputHandle> {
566        self.output_registry.active_handle()
567    }
568
569    pub fn set_active_surface_key(&mut self, key: Option<ShellSurfaceKey>) {
570        if let Some(ref k) = key {
571            self.output_registry.set_active(Some(k.output_handle));
572        } else {
573            self.output_registry.set_active(None);
574        }
575        self.active_surface_key = key;
576    }
577
578    pub fn active_surface_key(&self) -> Option<&ShellSurfaceKey> {
579        self.active_surface_key.as_ref()
580    }
581
582    pub fn active_surface_mut(&mut self) -> Option<&mut PerOutputSurface> {
583        let key = self.active_surface_key.clone()?;
584        self.surfaces.get_mut(&key)
585    }
586
587    pub fn primary_output(&self) -> Option<&PerOutputSurface> {
588        self.output_registry
589            .primary_handle()
590            .and_then(|handle| self.get_first_surface_for_output(handle))
591    }
592
593    pub fn primary_output_handle(&self) -> Option<OutputHandle> {
594        self.output_registry.primary_handle()
595    }
596
597    pub fn active_output(&self) -> Option<&PerOutputSurface> {
598        self.output_registry
599            .active_handle()
600            .and_then(|handle| self.get_first_surface_for_output(handle))
601    }
602
603    pub fn all_outputs(&self) -> impl Iterator<Item = &PerOutputSurface> {
604        self.surfaces.values()
605    }
606
607    pub fn all_outputs_mut(&mut self) -> impl Iterator<Item = &mut PerOutputSurface> {
608        self.surfaces.values_mut()
609    }
610
611    pub fn surfaces_for_output(
612        &self,
613        handle: OutputHandle,
614    ) -> impl Iterator<Item = (&str, &PerOutputSurface)> + '_ {
615        self.surfaces
616            .iter()
617            .filter(move |(k, _)| k.output_handle == handle)
618            .map(|(k, v)| {
619                let name = self
620                    .surface_handle_to_name
621                    .get(&k.surface_handle)
622                    .map_or("unknown", String::as_str);
623                (name, v)
624            })
625    }
626
627    pub fn surfaces_with_keys(
628        &self,
629    ) -> impl Iterator<Item = (&ShellSurfaceKey, &PerOutputSurface)> {
630        self.surfaces.iter()
631    }
632
633    pub const fn shared_pointer_serial(&self) -> &Rc<SharedPointerSerial> {
634        &self.shared_pointer_serial
635    }
636
637    pub fn handle_keymap(&mut self, fd: BorrowedFd<'_>, size: u32) {
638        let Ok(fd) = fd.try_clone_to_owned() else {
639            return;
640        };
641
642        let keymap = unsafe {
643            xkb::Keymap::new_from_fd(
644                &self.keyboard_state.xkb_context,
645                fd,
646                size as usize,
647                xkb::KEYMAP_FORMAT_TEXT_V1,
648                xkb::KEYMAP_COMPILE_NO_FLAGS,
649            )
650        };
651
652        if let Ok(Some(keymap)) = keymap {
653            self.keyboard_state.set_keymap(keymap);
654        }
655    }
656
657    pub fn handle_keyboard_enter(&mut self, _serial: u32, surface: &WlSurface, _keys: &[u8]) {
658        if let Some(manager) = self.lock_manager.as_mut() {
659            if manager.handle_keyboard_enter(surface) {
660                self.set_keyboard_focus(None);
661                return;
662            }
663        }
664
665        let surface_id = surface.id();
666        if let Some(key) = self.get_key_by_surface(&surface_id).cloned() {
667            self.keyboard_input_state
668                .set_focused_surface(Some(surface_id.clone()));
669            self.set_keyboard_focus(Some(key));
670            return;
671        }
672
673        if let Some(key) = self.get_key_by_popup(&surface_id).cloned() {
674            self.keyboard_input_state
675                .set_focused_surface(Some(surface_id));
676            self.set_keyboard_focus(Some(key));
677        }
678    }
679
680    pub fn handle_keyboard_leave(&mut self, _serial: u32, surface: &WlSurface) {
681        if let Some(manager) = self.lock_manager.as_mut() {
682            if manager.handle_keyboard_leave(surface) {
683                return;
684            }
685        }
686
687        let surface_id = surface.id();
688        if self.keyboard_input_state.focused_surface_id() == Some(&surface_id) {
689            self.keyboard_input_state.reset();
690            self.set_keyboard_focus(None);
691        }
692    }
693
694    pub fn handle_key(&mut self, _serial: u32, _time: u32, key: u32, state: wl_keyboard::KeyState) {
695        if let Some(manager) = self.lock_manager.as_mut() {
696            if manager.handle_keyboard_key(key, state, &mut self.keyboard_state) {
697                return;
698            }
699        }
700
701        let Some(focus_key) = self.keyboard_focus_key.clone() else {
702            return;
703        };
704        let Some(surface_id) = self.keyboard_input_state.focused_surface_id().cloned() else {
705            return;
706        };
707
708        if let Some(surface) = self.surfaces.get_mut(&focus_key) {
709            surface.handle_keyboard_key(&surface_id, key, state, &mut self.keyboard_state);
710        }
711    }
712
713    pub fn handle_modifiers(
714        &mut self,
715        _serial: u32,
716        mods_depressed: u32,
717        mods_latched: u32,
718        mods_locked: u32,
719        group: u32,
720    ) {
721        if let Some(state) = self.keyboard_state.xkb_state.as_mut() {
722            state.update_mask(mods_depressed, mods_latched, mods_locked, 0, 0, group);
723        }
724    }
725
726    pub fn handle_repeat_info(&mut self, rate: i32, delay: i32) {
727        self.keyboard_state.repeat_rate = rate;
728        self.keyboard_state.repeat_delay = delay;
729    }
730
731    fn set_keyboard_focus(&mut self, key: Option<ShellSurfaceKey>) {
732        if let Some(ref k) = key {
733            self.output_registry.set_active(Some(k.output_handle));
734        }
735        self.keyboard_focus_key = key;
736    }
737
738    pub fn find_output_by_popup(&self, popup_surface_id: &ObjectId) -> Option<&PerOutputSurface> {
739        self.surfaces.values().find(|surface| {
740            surface
741                .popup_manager()
742                .as_ref()
743                .and_then(|pm| pm.find_by_surface(popup_surface_id))
744                .is_some()
745        })
746    }
747
748    pub fn find_output_by_popup_mut(
749        &mut self,
750        popup_surface_id: &ObjectId,
751    ) -> Option<&mut PerOutputSurface> {
752        self.surfaces.values_mut().find(|surface| {
753            surface
754                .popup_manager()
755                .as_ref()
756                .and_then(|pm| pm.find_by_surface(popup_surface_id))
757                .is_some()
758        })
759    }
760
761    pub fn get_key_by_popup(&self, popup_surface_id: &ObjectId) -> Option<&ShellSurfaceKey> {
762        self.surfaces.iter().find_map(|(key, surface)| {
763            surface
764                .popup_manager()
765                .as_ref()
766                .and_then(|pm| pm.find_by_surface(popup_surface_id))
767                .map(|_| key)
768        })
769    }
770
771    pub fn get_handle_by_popup(&self, popup_surface_id: &ObjectId) -> Option<OutputHandle> {
772        self.get_key_by_popup(popup_surface_id)
773            .map(|key| key.output_handle)
774    }
775
776    pub fn get_output_by_handle_mut(
777        &mut self,
778        handle: OutputHandle,
779    ) -> Option<&mut PerOutputSurface> {
780        self.get_first_surface_for_output_mut(handle)
781    }
782
783    pub fn get_output_info(&self, handle: OutputHandle) -> Option<&OutputInfo> {
784        self.output_registry.get(handle)
785    }
786
787    pub fn get_output_info_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> {
788        self.output_registry.get_mut(handle)
789    }
790
791    pub fn all_output_info(&self) -> impl Iterator<Item = &OutputInfo> {
792        self.output_registry.all_info()
793    }
794
795    pub const fn output_registry(&self) -> &OutputRegistry {
796        &self.output_registry
797    }
798
799    pub fn shell_surface_names(&self) -> Vec<&str> {
800        let mut names: Vec<_> = self
801            .surface_handle_to_name
802            .values()
803            .map(String::as_str)
804            .collect();
805        names.sort_unstable();
806        names.dedup();
807        names
808    }
809
810    pub fn surfaces_by_name(&self, surface_name: &str) -> Vec<&PerOutputSurface> {
811        let matching_handles: Vec<SurfaceHandle> = self
812            .surface_handle_to_name
813            .iter()
814            .filter(|(_, n)| n.as_str() == surface_name)
815            .map(|(h, _)| *h)
816            .collect();
817
818        self.surfaces
819            .iter()
820            .filter(|(k, _)| matching_handles.contains(&k.surface_handle))
821            .map(|(_, v)| v)
822            .collect()
823    }
824
825    pub fn surfaces_by_name_mut(&mut self, surface_name: &str) -> Vec<&mut PerOutputSurface> {
826        let matching_handles: Vec<SurfaceHandle> = self
827            .surface_handle_to_name
828            .iter()
829            .filter(|(_, n)| n.as_str() == surface_name)
830            .map(|(h, _)| *h)
831            .collect();
832
833        self.surfaces
834            .iter_mut()
835            .filter(|(k, _)| matching_handles.contains(&k.surface_handle))
836            .map(|(_, v)| v)
837            .collect()
838    }
839
840    pub fn surfaces_by_handle(&self, handle: SurfaceHandle) -> Vec<&PerOutputSurface> {
841        self.surfaces
842            .iter()
843            .filter(|(k, _)| k.surface_handle == handle)
844            .map(|(_, v)| v)
845            .collect()
846    }
847
848    pub fn surfaces_by_handle_mut(&mut self, handle: SurfaceHandle) -> Vec<&mut PerOutputSurface> {
849        self.surfaces
850            .iter_mut()
851            .filter(|(k, _)| k.surface_handle == handle)
852            .map(|(_, v)| v)
853            .collect()
854    }
855
856    pub fn surfaces_by_name_and_output(
857        &self,
858        name: &str,
859        output: OutputHandle,
860    ) -> Vec<&PerOutputSurface> {
861        let matching_handles: Vec<SurfaceHandle> = self
862            .surface_handle_to_name
863            .iter()
864            .filter(|(_, n)| n.as_str() == name)
865            .map(|(h, _)| *h)
866            .collect();
867
868        self.surfaces
869            .iter()
870            .filter(|(k, _)| {
871                k.output_handle == output && matching_handles.contains(&k.surface_handle)
872            })
873            .map(|(_, v)| v)
874            .collect()
875    }
876
877    pub fn surfaces_by_name_and_output_mut(
878        &mut self,
879        name: &str,
880        output: OutputHandle,
881    ) -> Vec<&mut PerOutputSurface> {
882        let matching_handles: Vec<SurfaceHandle> = self
883            .surface_handle_to_name
884            .iter()
885            .filter(|(_, n)| n.as_str() == name)
886            .map(|(h, _)| *h)
887            .collect();
888
889        self.surfaces
890            .iter_mut()
891            .filter(|(k, _)| {
892                k.output_handle == output && matching_handles.contains(&k.surface_handle)
893            })
894            .map(|(_, v)| v)
895            .collect()
896    }
897
898    pub fn get_output_by_handle(&self, handle: OutputHandle) -> Option<&PerOutputSurface> {
899        self.get_first_surface_for_output(handle)
900    }
901
902    pub fn outputs_with_handles(&self) -> impl Iterator<Item = (OutputHandle, &PerOutputSurface)> {
903        self.surfaces
904            .iter()
905            .map(|(key, surface)| (key.output_handle, surface))
906    }
907
908    pub fn outputs_with_info(&self) -> impl Iterator<Item = (&OutputInfo, &PerOutputSurface)> {
909        self.output_registry.all_info().filter_map(|info| {
910            let handle = info.handle();
911            self.get_first_surface_for_output(handle)
912                .map(|surface| (info, surface))
913        })
914    }
915
916    pub fn all_surfaces_for_output_mut(
917        &mut self,
918        output_id: &ObjectId,
919    ) -> Vec<&mut PerOutputSurface> {
920        let Some(handle) = self.output_mapping.get(output_id) else {
921            return Vec::new();
922        };
923
924        self.surfaces
925            .iter_mut()
926            .filter(|(k, _)| k.output_handle == handle)
927            .map(|(_, v)| v)
928            .collect()
929    }
930
931    pub fn remove_surfaces_by_name(&mut self, surface_name: &str) -> Vec<PerOutputSurface> {
932        let matching_handles: Vec<SurfaceHandle> = self
933            .surface_handle_to_name
934            .iter()
935            .filter(|(_, n)| n.as_str() == surface_name)
936            .map(|(h, _)| *h)
937            .collect();
938
939        let keys_to_remove: Vec<_> = self
940            .surfaces
941            .keys()
942            .filter(|k| matching_handles.contains(&k.surface_handle))
943            .cloned()
944            .collect();
945
946        let mut removed = Vec::new();
947        for key in keys_to_remove {
948            if let Some(surface) = self.surfaces.remove(&key) {
949                removed.push(surface);
950            }
951        }
952
953        self.surface_to_key
954            .retain(|_, k| !matching_handles.contains(&k.surface_handle));
955
956        removed
957    }
958}
959
960impl RenderableSet for AppState {
961    fn render_all_dirty(&self) -> Result<()> {
962        for surface in self.all_outputs() {
963            surface
964                .window()
965                .render_frame_if_dirty()
966                .map_err(|e| RenderingError::Operation {
967                    message: e.to_string(),
968                })?;
969        }
970        Ok(())
971    }
972}