1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use std::collections::hash_map::Entry;
use smithay::backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state};
use smithay::desktop::find_popup_root_surface;
use smithay::reexports::wayland_server::protocol::wl_buffer;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::Client;
use smithay::wayland::buffer::BufferHandler;
use smithay::wayland::compositor::{
get_parent, is_sync_subsurface, CompositorClientState, CompositorHandler, CompositorState,
};
use smithay::wayland::shm::{ShmHandler, ShmState};
use smithay::{delegate_compositor, delegate_shm};
use super::xdg_shell;
use crate::niri::ClientState;
use crate::Niri;
impl CompositorHandler for Niri {
fn compositor_state(&mut self) -> &mut CompositorState {
&mut self.compositor_state
}
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
&client.get_data::<ClientState>().unwrap().compositor_state
}
fn commit(&mut self, surface: &WlSurface) {
let _span = tracy_client::span!("CompositorHandler::commit");
on_commit_buffer_handler::<Self>(surface);
if is_sync_subsurface(surface) {
return;
}
let mut root_surface = surface.clone();
while let Some(parent) = get_parent(&root_surface) {
root_surface = parent;
}
if surface == &root_surface {
// This is a root surface commit. It might have mapped a previously-unmapped toplevel.
if let Entry::Occupied(entry) = self.unmapped_windows.entry(surface.clone()) {
let is_mapped =
with_renderer_surface_state(surface, |state| state.buffer().is_some());
if is_mapped {
// The toplevel got mapped.
let window = entry.remove();
window.on_commit();
let output = self.monitor_set.active_output().unwrap().clone();
self.monitor_set.add_window_to_output(&output, window, true);
self.queue_redraw(output);
return;
}
// The toplevel remains unmapped.
let window = entry.get();
xdg_shell::send_initial_configure_if_needed(window);
return;
}
// This is a commit of a previously-mapped root or a non-toplevel root.
if let Some((window, output)) = self.monitor_set.find_window_and_output(surface) {
// This is a commit of a previously-mapped toplevel.
window.on_commit();
// This is a commit of a previously-mapped toplevel.
let is_mapped =
with_renderer_surface_state(surface, |state| state.buffer().is_some());
if !is_mapped {
// The toplevel got unmapped.
self.monitor_set.remove_window(&window);
self.unmapped_windows.insert(surface.clone(), window);
self.queue_redraw(output);
return;
}
// The toplevel remains mapped.
self.monitor_set.update_window(&window);
self.queue_redraw(output);
return;
}
// This is a commit of a non-toplevel root.
}
// This is a commit of a non-root or a non-toplevel root.
let root_window_output = self.monitor_set.find_window_and_output(&root_surface);
if let Some((window, output)) = root_window_output {
window.on_commit();
self.monitor_set.update_window(&window);
self.queue_redraw(output);
return;
}
// This might be a popup.
self.popups_handle_commit(surface);
if let Some(popup) = self.popups.find_popup(surface) {
if let Ok(root) = find_popup_root_surface(&popup) {
let root_window_output = self.monitor_set.find_window_and_output(&root);
if let Some((_window, output)) = root_window_output {
self.queue_redraw(output);
}
}
}
// This might be a layer-shell surface.
self.layer_shell_handle_commit(surface);
}
}
impl BufferHandler for Niri {
fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {}
}
impl ShmHandler for Niri {
fn shm_state(&self) -> &ShmState {
&self.shm_state
}
}
delegate_compositor!(Niri);
delegate_shm!(Niri);
|