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}