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 }