git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

src/server/scene_node_data.rs (2.8K)

 1 // SPDX-FileCopyrightText: © 2023 The River Developers
 2 // SPDX-License-Identifier: GPL-3.0-only
 3 
 4 use crate::ffi;
 5 use crate::server::{WlListener, wl_signal_add, wl_listener_remove};
 6 use crate::window_manager::{Window, ShellSurface, XwaylandOverrideRedirect};
 7 use crate::layer_shell::LayerSurface;
 8 use crate::lock_manager::LockSurface;
 9 
10 #[derive(Clone, Copy)]
11 pub enum SceneNodeDataVal {
12     Window(*mut Window),
13     ShellSurface(*mut ShellSurface),
14     LockSurface(*mut LockSurface),
15     LayerSurface(*mut LayerSurface),
16     OverrideRedirect(*mut XwaylandOverrideRedirect),
17 }
18 
19 #[repr(C)]
20 pub struct SceneNodeData {
21     pub node: *mut ffi::wlr_scene_node,
22     pub data: SceneNodeDataVal,
23     pub destroy: ffi::wl_listener,
24 }
25 
26 impl SceneNodeData {
27     pub unsafe fn attach(node: *mut ffi::wlr_scene_node, data: SceneNodeDataVal) {
28         let scene_node_data = Box::new(SceneNodeData {
29             node,
30             data,
31             destroy: std::mem::zeroed(),
32         });
33 
34         let raw = Box::into_raw(scene_node_data);
35         ffi::river_scene_node_set_data(node, raw as *mut std::ffi::c_void);
36 
37         let destroy_listener = &mut (*raw).destroy as *mut ffi::wl_listener as *mut WlListener;
38         (*destroy_listener).notify = Some(handle_destroy);
39         wl_signal_add(ffi::river_scene_node_get_destroy_signal(node), &mut (*raw).destroy);
40     }
41 
42     pub unsafe fn from_node(node: *mut ffi::wlr_scene_node) -> Option<&'static SceneNodeData> {
43         let mut n = node;
44         while !n.is_null() {
45             let data_ptr = ffi::river_scene_node_get_data(n) as *mut SceneNodeData;
46             if !data_ptr.is_null() {
47                 return Some(&*data_ptr);
48             }
49             let parent_tree = ffi::river_scene_node_get_parent(n);
50             if !parent_tree.is_null() {
51                 n = parent_tree as *mut ffi::wlr_scene_node;
52             } else {
53                 break;
54             }
55         }
56         None
57     }
58 
59     pub unsafe fn from_surface(surface: *mut ffi::wlr_surface) -> Option<&'static SceneNodeData> {
60         if surface.is_null() {
61             return None;
62         }
63         let root_surface = ffi::wlr_surface_get_root_surface(surface);
64         if root_surface.is_null() {
65             return None;
66         }
67         let node_ptr = ffi::river_wlr_surface_get_data(root_surface) as *mut ffi::wlr_scene_node;
68         if !node_ptr.is_null() {
69             Self::from_node(node_ptr)
70         } else {
71             None
72         }
73     }
74 }
75 
76 unsafe extern "C" fn handle_destroy(listener: *mut ffi::wl_listener, _data: *mut std::ffi::c_void) {
77     let scene_node_data_ptr = crate::container_of!(listener, SceneNodeData, destroy);
78     let mut scene_node_data = Box::from_raw(scene_node_data_ptr);
79     wl_listener_remove(&mut scene_node_data.destroy);
80     if !scene_node_data.node.is_null() {
81         ffi::river_scene_node_set_data(scene_node_data.node, std::ptr::null_mut());
82     }
83 }