Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
src/server/wlroots_log_wrapper.c (41.4K)
1 // SPDX-FileCopyrightText: © 2021 The River Developers
2 // SPDX-License-Identifier: GPL-3.0-only
3
4 #define _POSIX_C_SOURCE 199309L
5 #include <assert.h>
6 #include <math.h>
7 #include <stdarg.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 #include <wlr/util/log.h>
12 #include <wlr/backend/session.h>
13
14 #define BUFFER_SIZE 1024
15
16 void river_wlroots_log_callback(enum wlr_log_importance importance, const char *ptr, size_t len);
17
18 static void callback(enum wlr_log_importance importance, const char *fmt, va_list args) {
19 char buffer[BUFFER_SIZE];
20
21 // Need to make a copy of the args in case our buffer isn't big
22 // enough and we need to use them again.
23 va_list args_copy;
24 va_copy(args_copy, args);
25
26 const int length = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
27 // Need to add one for the terminating 0 byte
28 if (length + 1 <= BUFFER_SIZE) {
29 // The formatted string fit within our buffer, pass it on to river
30 river_wlroots_log_callback(importance, buffer, length);
31 } else {
32 // The formatted string did not fit in our buffer, we need
33 // to allocate enough memory to hold it.
34 char *allocated_buffer = malloc(length + 1);
35 if (allocated_buffer != NULL) {
36 const int length2 = vsnprintf(allocated_buffer, length + 1, fmt, args_copy);
37 assert(length2 == length);
38 river_wlroots_log_callback(importance, allocated_buffer, length);
39 free(allocated_buffer);
40 }
41 }
42
43 va_end(args_copy);
44 }
45
46 void river_init_wlroots_log(enum wlr_log_importance importance) {
47 wlr_log_init(importance, callback);
48 }
49
50 #include <time.h>
51 #include <scenefx/types/wlr_scene.h>
52 #include <wlr/types/wlr_buffer.h>
53 #include <wlr/interfaces/wlr_buffer.h>
54 #include <drm_fourcc.h>
55 #include <wlr/types/wlr_output.h>
56 #include <wlr/util/region.h>
57 #include <wlr/types/wlr_compositor.h>
58 #include <wlr/types/wlr_input_device.h>
59 #include <wlr/types/wlr_keyboard.h>
60 #include <wlr/interfaces/wlr_keyboard.h>
61 #include <wlr/types/wlr_cursor.h>
62 #include <wlr/types/wlr_seat.h>
63 #include <wlr/types/wlr_pointer.h>
64 #include <wlr/types/wlr_tablet_v2.h>
65 #include <wlr/backend.h>
66 #include <wlr/types/wlr_xdg_shell.h>
67 #include <wlr/types/wlr_input_method_v2.h>
68 #include <wlr/types/wlr_data_device.h>
69
70 struct wlr_surface *river_scene_node_get_surface(struct wlr_scene_node *node) {
71 if (node->type == WLR_SCENE_NODE_BUFFER) {
72 struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
73 struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer);
74 if (scene_surface) {
75 return scene_surface->surface;
76 }
77 }
78 return NULL;
79 }
80
81 enum wlr_scene_node_type river_scene_node_get_type(struct wlr_scene_node *node) {
82 return node->type;
83 }
84
85 struct wlr_scene_tree *river_scene_node_get_parent(struct wlr_scene_node *node) {
86 return node->parent;
87 }
88
89 int river_scene_node_get_x(struct wlr_scene_node *node) {
90 return node->x;
91 }
92
93 int river_scene_node_get_y(struct wlr_scene_node *node) {
94 return node->y;
95 }
96
97 void *river_scene_node_get_data(struct wlr_scene_node *node) {
98 return node->data;
99 }
100
101 void river_scene_node_set_data(struct wlr_scene_node *node, void *data) {
102 node->data = data;
103 }
104
105 struct wl_signal *river_scene_node_get_destroy_signal(struct wlr_scene_node *node) {
106 return &node->events.destroy;
107 }
108
109 static void save_surface_tree_iter(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
110 struct wlr_scene_tree *saved_tree = user_data;
111 struct wlr_scene_tree *buffer_tree = wlr_scene_tree_create(saved_tree);
112 if (!buffer_tree) {
113 return;
114 }
115 wlr_scene_node_set_position(&buffer_tree->node, sx, sy);
116 struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(buffer_tree, buffer->buffer);
117 if (!scene_buffer) {
118 wlr_scene_node_destroy(&buffer_tree->node);
119 return;
120 }
121 wlr_scene_node_set_position(&scene_buffer->node, 0, 0);
122 wlr_scene_buffer_set_dest_size(scene_buffer, buffer->dst_width, buffer->dst_height);
123 wlr_scene_buffer_set_source_box(scene_buffer, &buffer->src_box);
124 wlr_scene_buffer_set_transform(scene_buffer, buffer->transform);
125 }
126
127 void river_scene_tree_save_buffers(struct wlr_scene_tree *tree, struct wlr_scene_tree *saved_tree) {
128 wlr_scene_node_for_each_buffer(&tree->node, save_surface_tree_iter, saved_tree);
129 }
130
131 void river_scene_tree_clear_children(struct wlr_scene_tree *tree) {
132 struct wlr_scene_node *child, *tmp;
133 wl_list_for_each_safe(child, tmp, &tree->children, link) {
134 wlr_scene_node_destroy(child);
135 }
136 }
137
138 struct wlr_scene_node *river_scene_node_from_children_link(struct wl_list *link) {
139 return wl_container_of(link, (struct wlr_scene_node *)NULL, link);
140 }
141
142 struct wl_signal *river_wlr_output_get_destroy_signal(struct wlr_output *output) {
143 return &output->events.destroy;
144 }
145
146 struct wl_signal *river_wlr_output_get_request_state_signal(struct wlr_output *output) {
147 return &output->events.request_state;
148 }
149
150 struct wl_signal *river_wlr_output_get_frame_signal(struct wlr_output *output) {
151 return &output->events.frame;
152 }
153
154 struct wl_signal *river_wlr_output_get_present_signal(struct wlr_output *output) {
155 return &output->events.present;
156 }
157
158 void *river_wlr_output_get_data(struct wlr_output *output) {
159 return output->data;
160 }
161
162 void river_wlr_output_set_data(struct wlr_output *output, void *data) {
163 output->data = data;
164 }
165
166 const char *river_wlr_output_get_name(struct wlr_output *output) {
167 return output->name;
168 }
169
170 enum wlr_output_adaptive_sync_status river_wlr_output_get_adaptive_sync_status(struct wlr_output *output) {
171 return output->adaptive_sync_status;
172 }
173
174 bool river_wlr_output_get_enabled(struct wlr_output *output) {
175 return output->enabled;
176 }
177
178 struct wlr_output_mode *river_wlr_output_get_current_mode(struct wlr_output *output) {
179 return output->current_mode;
180 }
181
182 void river_wlr_output_get_phys_size(struct wlr_output *output, int32_t *width_mm, int32_t *height_mm) {
183 *width_mm = output->phys_width;
184 *height_mm = output->phys_height;
185 }
186
187 void river_wlr_output_set_phys_size(struct wlr_output *output, int32_t width_mm, int32_t height_mm) {
188 output->phys_width = width_mm;
189 output->phys_height = height_mm;
190 }
191
192 int32_t river_wlr_output_get_width(struct wlr_output *output) {
193 return output->width;
194 }
195
196 int32_t river_wlr_output_get_height(struct wlr_output *output) {
197 return output->height;
198 }
199
200 int32_t river_wlr_output_get_refresh(struct wlr_output *output) {
201 return output->refresh;
202 }
203
204 struct wl_global *river_wlr_output_get_global(struct wlr_output *output) {
205 return output->global;
206 }
207
208 void *river_wlr_surface_get_data(struct wlr_surface *surface) {
209 return surface->data;
210 }
211
212 void river_wlr_surface_set_data(struct wlr_surface *surface, void *data) {
213 surface->data = data;
214 }
215
216 struct wl_signal *river_wlr_surface_get_commit_signal(struct wlr_surface *surface) {
217 return &surface->events.commit;
218 }
219
220 struct wl_signal *river_wlr_surface_get_destroy_signal(struct wlr_surface *surface) {
221 return &surface->events.destroy;
222 }
223
224 // Show a surface at 1/scale of the size it committed itself at.
225 //
226 // For the cursor surface of an X11 client. Xwayland always commits its cursor
227 // at buffer scale 1, and wlr_cursor sizes the pointer from `current.width` --
228 // the surface's LOGICAL size -- so an N-pixel X cursor comes out N logical
229 // pixels, twice as big as everything else on a scale-2 panel. Under
230 // `xwayland_hidpi` X11 is a physical-pixel world and an X11 window's own
231 // buffer is already drawn at 1/scale (Window::x11_buffer_scale); this puts its
232 // cursor in the same world. Derived from the buffer, so applying it twice to
233 // one committed state is a no-op.
234 void river_wlr_surface_scale_logical_size(struct wlr_surface *surface, float scale) {
235 if (surface == NULL || scale <= 0.0f || scale == 1.0f) {
236 return;
237 }
238 float total = (float)surface->current.scale * scale;
239 surface->current.width = (int)roundf((float)surface->current.buffer_width / total);
240 surface->current.height = (int)roundf((float)surface->current.buffer_height / total);
241 }
242
243 enum wlr_input_device_type river_wlr_input_device_get_type(struct wlr_input_device *dev) {
244 return dev->type;
245 }
246
247 const char *river_wlr_input_device_get_name(struct wlr_input_device *dev) {
248 return dev->name;
249 }
250
251 struct wl_signal *river_wlr_input_device_get_destroy_signal(struct wlr_input_device *dev) {
252 return &dev->events.destroy;
253 }
254
255 void *river_wlr_input_device_get_data(struct wlr_input_device *dev) {
256 return dev->data;
257 }
258
259 void river_wlr_input_device_set_data(struct wlr_input_device *dev, void *data) {
260 dev->data = data;
261 }
262
263 struct wl_signal *river_wlr_keyboard_get_key_signal(struct wlr_keyboard *kbd) {
264 return &kbd->events.key;
265 }
266
267 struct wl_signal *river_wlr_keyboard_get_modifiers_signal(struct wlr_keyboard *kbd) {
268 return &kbd->events.modifiers;
269 }
270
271 struct wl_signal *river_wlr_keyboard_get_keymap_signal(struct wlr_keyboard *kbd) {
272 return &kbd->events.keymap;
273 }
274
275 struct xkb_keymap *river_wlr_keyboard_get_keymap(struct wlr_keyboard *kbd) {
276 return kbd->keymap;
277 }
278
279 struct wlr_keyboard_modifiers *river_wlr_keyboard_get_modifiers(struct wlr_keyboard *kbd) {
280 return &kbd->modifiers;
281 }
282
283 void *river_wlr_keyboard_get_data(struct wlr_keyboard *kbd) {
284 return kbd->data;
285 }
286
287 void river_wlr_keyboard_set_data(struct wlr_keyboard *kbd, void *data) {
288 kbd->data = data;
289 }
290
291 double river_wlr_cursor_get_x(struct wlr_cursor *cursor) {
292 return cursor->x;
293 }
294
295 double river_wlr_cursor_get_y(struct wlr_cursor *cursor) {
296 return cursor->y;
297 }
298
299 struct wl_signal *river_wlr_cursor_get_motion_signal(struct wlr_cursor *cursor) {
300 return &cursor->events.motion;
301 }
302
303 struct wl_signal *river_wlr_cursor_get_motion_absolute_signal(struct wlr_cursor *cursor) {
304 return &cursor->events.motion_absolute;
305 }
306
307 struct wl_signal *river_wlr_cursor_get_button_signal(struct wlr_cursor *cursor) {
308 return &cursor->events.button;
309 }
310
311 struct wl_signal *river_wlr_cursor_get_axis_signal(struct wlr_cursor *cursor) {
312 return &cursor->events.axis;
313 }
314
315 struct wl_signal *river_wlr_cursor_get_frame_signal(struct wlr_cursor *cursor) {
316 return &cursor->events.frame;
317 }
318
319 struct wl_signal *river_wlr_cursor_get_swipe_begin_signal(struct wlr_cursor *cursor) {
320 return &cursor->events.swipe_begin;
321 }
322
323 struct wl_signal *river_wlr_cursor_get_swipe_update_signal(struct wlr_cursor *cursor) {
324 return &cursor->events.swipe_update;
325 }
326
327 struct wl_signal *river_wlr_cursor_get_swipe_end_signal(struct wlr_cursor *cursor) {
328 return &cursor->events.swipe_end;
329 }
330
331 struct wl_signal *river_wlr_cursor_get_pinch_begin_signal(struct wlr_cursor *cursor) {
332 return &cursor->events.pinch_begin;
333 }
334
335 struct wl_signal *river_wlr_cursor_get_pinch_update_signal(struct wlr_cursor *cursor) {
336 return &cursor->events.pinch_update;
337 }
338
339 struct wl_signal *river_wlr_cursor_get_pinch_end_signal(struct wlr_cursor *cursor) {
340 return &cursor->events.pinch_end;
341 }
342
343 struct wl_signal *river_wlr_cursor_get_hold_begin_signal(struct wlr_cursor *cursor) {
344 return &cursor->events.hold_begin;
345 }
346
347 struct wl_signal *river_wlr_cursor_get_hold_end_signal(struct wlr_cursor *cursor) {
348 return &cursor->events.hold_end;
349 }
350
351 struct wl_signal *river_wlr_cursor_get_touch_down_signal(struct wlr_cursor *cursor) {
352 return &cursor->events.touch_down;
353 }
354
355 struct wl_signal *river_wlr_cursor_get_touch_motion_signal(struct wlr_cursor *cursor) {
356 return &cursor->events.touch_motion;
357 }
358
359 struct wl_signal *river_wlr_cursor_get_touch_up_signal(struct wlr_cursor *cursor) {
360 return &cursor->events.touch_up;
361 }
362
363 struct wl_signal *river_wlr_cursor_get_touch_cancel_signal(struct wlr_cursor *cursor) {
364 return &cursor->events.touch_cancel;
365 }
366
367 struct wl_signal *river_wlr_cursor_get_touch_frame_signal(struct wlr_cursor *cursor) {
368 return &cursor->events.touch_frame;
369 }
370
371 struct wl_signal *river_wlr_cursor_get_tablet_tool_axis_signal(struct wlr_cursor *cursor) {
372 return &cursor->events.tablet_tool_axis;
373 }
374
375 struct wl_signal *river_wlr_cursor_get_tablet_tool_proximity_signal(struct wlr_cursor *cursor) {
376 return &cursor->events.tablet_tool_proximity;
377 }
378
379 struct wl_signal *river_wlr_cursor_get_tablet_tool_tip_signal(struct wlr_cursor *cursor) {
380 return &cursor->events.tablet_tool_tip;
381 }
382
383 struct wl_signal *river_wlr_cursor_get_tablet_tool_button_signal(struct wlr_cursor *cursor) {
384 return &cursor->events.tablet_tool_button;
385 }
386
387 const char *river_wlr_seat_get_name(struct wlr_seat *seat) {
388 return seat->name;
389 }
390
391 void *river_wlr_seat_get_data(struct wlr_seat *seat) {
392 return seat->data;
393 }
394
395 void river_wlr_seat_set_data(struct wlr_seat *seat, void *data) {
396 seat->data = data;
397 }
398
399 struct wl_signal *river_wlr_seat_get_request_set_cursor_signal(struct wlr_seat *seat) {
400 return &seat->events.request_set_cursor;
401 }
402
403 struct wl_signal *river_wlr_seat_get_request_set_selection_signal(struct wlr_seat *seat) {
404 return &seat->events.request_set_selection;
405 }
406
407 struct wl_signal *river_wlr_seat_get_request_start_drag_signal(struct wlr_seat *seat) {
408 return &seat->events.request_start_drag;
409 }
410
411 struct wl_signal *river_wlr_seat_get_start_drag_signal(struct wlr_seat *seat) {
412 return &seat->events.start_drag;
413 }
414
415 struct wl_signal *river_wlr_seat_get_request_set_primary_selection_signal(struct wlr_seat *seat) {
416 return &seat->events.request_set_primary_selection;
417 }
418
419 struct wlr_seat_client *river_wlr_seat_get_pointer_focused_client(struct wlr_seat *seat) {
420 return seat->pointer_state.focused_client;
421 }
422
423 struct wlr_surface *river_wlr_seat_get_pointer_focused_surface(struct wlr_seat *seat) {
424 return seat->pointer_state.focused_surface;
425 }
426
427 /* Damage the whole output and schedule a frame — the public-field replica of
428 * scenefx's internal scene_output_damage_whole(). Viewport zoom re-lays-out
429 * the entire screen, but per-node damage under-reports at the seams (stale
430 * slivers of the previous zoom level survive), so camera motion forces a
431 * full repaint. */
432 void river_scene_output_damage_whole(struct wlr_scene_output *scene_output) {
433 struct wlr_output *output = scene_output->output;
434 pixman_region32_t damage;
435 pixman_region32_init_rect(&damage, 0, 0, output->width, output->height);
436 wlr_output_schedule_frame(output);
437 wlr_damage_ring_add(&scene_output->damage_ring, &damage);
438 /* pending_commit_damage lives in the WLR_PRIVATE member — reaching in is
439 * the same deal as the pointer_state accesses elsewhere in this file. */
440 pixman_region32_union(&scene_output->WLR_PRIVATE.pending_commit_damage,
441 &scene_output->WLR_PRIVATE.pending_commit_damage, &damage);
442 pixman_region32_fini(&damage);
443 }
444
445 struct wl_client *river_wlr_seat_client_get_client(struct wlr_seat_client *client) {
446 return client->client;
447 }
448
449 struct wlr_keyboard *river_wlr_seat_get_keyboard(struct wlr_seat *seat) {
450 return seat->keyboard_state.keyboard;
451 }
452
453 struct wl_global *river_wlr_seat_get_global(struct wlr_seat *seat) {
454 return seat->global;
455 }
456
457 struct wl_signal *river_wlr_backend_get_new_input_signal(struct wlr_backend *backend) {
458 return &backend->events.new_input;
459 }
460
461 const struct wlr_surface_role *river_wlr_surface_get_role(struct wlr_surface *surface) {
462 return surface->role;
463 }
464
465 struct wl_resource *river_wlr_surface_get_role_resource(struct wlr_surface *surface) {
466 return surface->role_resource;
467 }
468
469 void river_wlr_surface_set_role_object(struct wlr_surface *surface, struct wl_resource *role_resource) {
470 surface->role_resource = role_resource;
471 }
472
473 struct wlr_surface *river_wlr_xdg_surface_get_surface(struct wlr_xdg_surface *xdg_surface) {
474 return xdg_surface->surface;
475 }
476
477 struct wl_signal *river_wlr_xdg_surface_get_ack_configure_signal(struct wlr_xdg_surface *xdg_surface) {
478 return &xdg_surface->events.ack_configure;
479 }
480
481 struct wl_signal *river_wlr_xdg_surface_get_new_popup_signal(struct wlr_xdg_surface *xdg_surface) {
482 return &xdg_surface->events.new_popup;
483 }
484
485 void river_wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *xdg_surface, struct wlr_box *box) {
486 *box = xdg_surface->geometry;
487 }
488
489 bool river_wlr_xdg_surface_get_initial_commit(struct wlr_xdg_surface *xdg_surface) {
490 return xdg_surface->initial_commit;
491 }
492
493 bool river_wlr_xdg_surface_get_initialized(struct wlr_xdg_surface *xdg_surface) {
494 return xdg_surface->initialized;
495 }
496
497 struct wlr_xdg_surface *river_wlr_xdg_toplevel_get_base(struct wlr_xdg_toplevel *toplevel) {
498 return toplevel->base;
499 }
500
501 struct wl_signal *river_wlr_xdg_toplevel_get_destroy_signal(struct wlr_xdg_toplevel *toplevel) {
502 return &toplevel->events.destroy;
503 }
504
505 struct wl_signal *river_wlr_xdg_toplevel_get_request_show_window_menu_signal(struct wlr_xdg_toplevel *toplevel) {
506 return &toplevel->events.request_show_window_menu;
507 }
508
509 struct wl_signal *river_wlr_xdg_toplevel_get_request_fullscreen_signal(struct wlr_xdg_toplevel *toplevel) {
510 return &toplevel->events.request_fullscreen;
511 }
512
513 struct wl_signal *river_wlr_xdg_toplevel_get_request_maximize_signal(struct wlr_xdg_toplevel *toplevel) {
514 return &toplevel->events.request_maximize;
515 }
516
517 struct wl_signal *river_wlr_xdg_toplevel_get_request_minimize_signal(struct wlr_xdg_toplevel *toplevel) {
518 return &toplevel->events.request_minimize;
519 }
520
521 struct wl_signal *river_wlr_xdg_toplevel_get_request_move_signal(struct wlr_xdg_toplevel *toplevel) {
522 return &toplevel->events.request_move;
523 }
524
525 struct wl_signal *river_wlr_xdg_toplevel_get_request_resize_signal(struct wlr_xdg_toplevel *toplevel) {
526 return &toplevel->events.request_resize;
527 }
528
529 struct wl_signal *river_wlr_xdg_toplevel_get_set_parent_signal(struct wlr_xdg_toplevel *toplevel) {
530 return &toplevel->events.set_parent;
531 }
532
533 struct wl_signal *river_wlr_xdg_toplevel_get_set_title_signal(struct wlr_xdg_toplevel *toplevel) {
534 return &toplevel->events.set_title;
535 }
536
537 struct wl_signal *river_wlr_xdg_toplevel_get_set_app_id_signal(struct wlr_xdg_toplevel *toplevel) {
538 return &toplevel->events.set_app_id;
539 }
540
541 const char *river_wlr_xdg_toplevel_get_title(struct wlr_xdg_toplevel *toplevel) {
542 return toplevel->title;
543 }
544
545 const char *river_wlr_xdg_toplevel_get_app_id(struct wlr_xdg_toplevel *toplevel) {
546 return toplevel->app_id;
547 }
548
549 struct wlr_xdg_toplevel *river_wlr_xdg_toplevel_get_parent(struct wlr_xdg_toplevel *toplevel) {
550 return toplevel->parent;
551 }
552
553 bool river_wlr_xdg_toplevel_get_requested_fullscreen(struct wlr_xdg_toplevel *toplevel) {
554 return toplevel->requested.fullscreen;
555 }
556
557 struct wlr_output *river_wlr_xdg_toplevel_get_requested_fullscreen_output(struct wlr_xdg_toplevel *toplevel) {
558 return toplevel->requested.fullscreen_output;
559 }
560
561 bool river_wlr_xdg_toplevel_get_requested_maximized(struct wlr_xdg_toplevel *toplevel) {
562 return toplevel->requested.maximized;
563 }
564
565 void river_wlr_xdg_toplevel_get_requested_min_max_size(struct wlr_xdg_toplevel *toplevel, int *min_w, int *min_h, int *max_w, int *max_h) {
566 *min_w = toplevel->current.min_width;
567 *min_h = toplevel->current.min_height;
568 *max_w = toplevel->current.max_width;
569 *max_h = toplevel->current.max_height;
570 }
571
572 struct wlr_xdg_surface *river_wlr_xdg_popup_get_base(struct wlr_xdg_popup *popup) {
573 return popup->base;
574 }
575
576 struct wl_signal *river_wlr_xdg_popup_get_destroy_signal(struct wlr_xdg_popup *popup) {
577 return &popup->events.destroy;
578 }
579
580 struct wl_signal *river_wlr_xdg_popup_get_reposition_signal(struct wlr_xdg_popup *popup) {
581 return &popup->events.reposition;
582 }
583
584 void river_wlr_xdg_popup_get_anchor_rect(struct wlr_xdg_popup *popup, struct wlr_box *box) {
585 *box = popup->scheduled.rules.anchor_rect;
586 }
587
588 void *river_wlr_xdg_surface_get_data(struct wlr_xdg_surface *xdg_surface) {
589 return xdg_surface->data;
590 }
591
592 void river_wlr_xdg_surface_set_data(struct wlr_xdg_surface *xdg_surface, void *data) {
593 xdg_surface->data = data;
594 }
595
596 struct wl_list *river_wlr_xdg_surface_get_popups(struct wlr_xdg_surface *xdg_surface) {
597 return &xdg_surface->popups;
598 }
599
600 struct wlr_scene_tree *river_wlr_scene_tree_get_parent(struct wlr_scene_tree *tree) {
601 return tree->node.parent;
602 }
603
604 struct wl_list *river_scene_tree_get_children(struct wlr_scene_tree *tree) {
605 return &tree->children;
606 }
607
608 struct wl_signal *river_wlr_surface_get_map_signal(struct wlr_surface *surface) {
609 return &surface->events.map;
610 }
611
612 struct wl_signal *river_wlr_surface_get_unmap_signal(struct wlr_surface *surface) {
613 return &surface->events.unmap;
614 }
615
616 struct wl_resource *river_wlr_surface_get_resource(struct wlr_surface *surface) {
617 return surface->resource;
618 }
619
620 bool river_wlr_surface_is_mapped(struct wlr_surface *surface) {
621 return surface->mapped;
622 }
623
624 struct wl_signal *river_wlr_tablet_v2_tablet_tool_get_set_cursor_signal(struct wlr_tablet_v2_tablet_tool *tool) {
625 return &tool->events.set_cursor;
626 }
627
628 struct wlr_surface *river_wlr_tablet_v2_tablet_tool_get_focused_surface(struct wlr_tablet_v2_tablet_tool *tool) {
629 return tool->focused_surface;
630 }
631
632 uint32_t river_wlr_tablet_v2_tablet_tool_get_proximity_serial(struct wlr_tablet_v2_tablet_tool *tool) {
633 return tool->proximity_serial;
634 }
635
636 bool river_wlr_tablet_v2_tablet_tool_get_is_down(struct wlr_tablet_v2_tablet_tool *tool) {
637 return tool->is_down;
638 }
639
640 size_t river_wlr_tablet_v2_tablet_tool_get_num_buttons(struct wlr_tablet_v2_tablet_tool *tool) {
641 return tool->num_buttons;
642 }
643
644 struct wlr_tablet_tool *river_wlr_tablet_v2_tablet_tool_get_wlr_tool(struct wlr_tablet_v2_tablet_tool *tool) {
645 return tool->wlr_tool;
646 }
647
648 // wl_touch.cancel is per client: it voids every point that client holds,
649 // and wlr_seat_touch_notify_cancel destroys them all. So cancelling one
650 // finger cancels its client's whole sequence — the protocol's unit.
651 void river_wlr_seat_touch_cancel_point(struct wlr_seat *wlr_seat, int32_t touch_id) {
652 struct wlr_touch_point *point = wlr_seat_touch_get_point(wlr_seat, touch_id);
653 if (point != NULL && point->client != NULL) {
654 wlr_seat_touch_notify_cancel(wlr_seat, point->client);
655 }
656 }
657
658 struct wlr_surface *river_wlr_seat_get_keyboard_focused_surface(struct wlr_seat *seat) {
659 return seat->keyboard_state.focused_surface;
660 }
661
662 int river_wlr_surface_get_width(struct wlr_surface *surface) {
663 return surface->current.width;
664 }
665
666 int river_wlr_surface_get_height(struct wlr_surface *surface) {
667 return surface->current.height;
668 }
669
670 // Commit sequence of a surface's current state. Cheap "has this drawn
671 // anything new?" key for the status-bar backdrop sampler, which is trying
672 // hard NOT to read back a texture it has already read.
673 uint32_t river_wlr_surface_current_seq(struct wlr_surface *surface) {
674 return surface->current.seq;
675 }
676
677 void river_wlr_surface_get_buffer_size(struct wlr_surface *surface, int *width, int *height) {
678 *width = surface->current.buffer_width;
679 *height = surface->current.buffer_height;
680 }
681
682 struct wlr_keyboard *river_wlr_input_method_keyboard_grab_v2_get_keyboard(struct wlr_input_method_keyboard_grab_v2 *grab) {
683 return grab->keyboard;
684 }
685
686 struct wl_signal *river_wlr_input_method_keyboard_grab_v2_get_destroy_signal(struct wlr_input_method_keyboard_grab_v2 *grab) {
687 return &grab->events.destroy;
688 }
689
690 struct wlr_drag_icon *river_wlr_drag_get_icon(struct wlr_drag *drag) {
691 return drag->icon;
692 }
693
694 struct wlr_seat *river_wlr_drag_get_seat(struct wlr_drag *drag) {
695 return drag->seat;
696 }
697
698 enum wlr_drag_grab_type river_wlr_drag_get_grab_type(struct wlr_drag *drag) {
699 return drag->grab_type;
700 }
701
702 int32_t river_wlr_drag_get_touch_id(struct wlr_drag *drag) {
703 return drag->touch_id;
704 }
705
706 struct wlr_data_source *river_wlr_drag_get_source(struct wlr_drag *drag) {
707 return drag->source;
708 }
709
710 struct wl_signal *river_wlr_drag_get_destroy_signal(struct wlr_drag *drag) {
711 return &drag->events.destroy;
712 }
713
714 struct wlr_seat_client *river_wlr_drag_get_seat_client(struct wlr_drag *drag) {
715 return drag->seat_client;
716 }
717
718 void river_wlr_keyboard_init(struct wlr_keyboard *keyboard,
719 void (*led_update)(struct wlr_keyboard *keyboard, uint32_t leds),
720 const char *name) {
721 static struct wlr_keyboard_impl impl;
722 static bool impl_initialized = false;
723 if (!impl_initialized) {
724 impl.name = name;
725 impl.led_update = led_update;
726 impl_initialized = true;
727 }
728 wlr_keyboard_init(keyboard, &impl, name);
729 }
730
731 static struct wlr_scene_node *find_blur_node(struct wlr_scene_tree *tree) {
732 struct wlr_scene_node *child;
733 wl_list_for_each(child, &tree->children, link) {
734 if (child->type == WLR_SCENE_NODE_BLUR) {
735 return child;
736 }
737 }
738 return NULL;
739 }
740
741 static struct wlr_scene_node *find_optimized_blur_node(struct wlr_scene_tree *tree) {
742 struct wlr_scene_node *child;
743 wl_list_for_each(child, &tree->children, link) {
744 if (child->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
745 return child;
746 }
747 }
748 return NULL;
749 }
750
751 static void get_size_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
752 (void)sx;
753 (void)sy;
754 int *size = (int *)user_data;
755 if (buffer->dst_width > size[0]) size[0] = buffer->dst_width;
756 if (buffer->dst_height > size[1]) size[1] = buffer->dst_height;
757 }
758
759 static void find_buffer_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
760 (void)sx;
761 (void)sy;
762 struct wlr_scene_buffer **result = (struct wlr_scene_buffer **)user_data;
763 if (*result == NULL) {
764 *result = buffer;
765 }
766 }
767
768 // `corner_radius` is in the same (scaled, device) pixels as width/height. It is applied
769 // here rather than through river_scene_node_set_corner_radius so that a blur node can
770 // never exist without it: that helper looks the blur up by scanning a tree's direct
771 // children, so aiming it at the wrong tree silently no-ops, and it was never called at
772 // all on the viewport-update path. Note the optimized blur node cannot be rounded --
773 // wlr_scene_optimized_blur has no radius field -- so callers that need rounded corners
774 // must pass optimized = false.
775 void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled, bool optimized, bool ignore_transparent, int x, int y, int width, int height, int corner_radius) {
776 if (node->type != WLR_SCENE_NODE_TREE) {
777 return;
778 }
779 struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
780 struct wlr_scene_node *opt_blur_node = find_optimized_blur_node(tree);
781 struct wlr_scene_node *std_blur_node = find_blur_node(tree);
782
783 if (!enabled) {
784 if (opt_blur_node) {
785 wlr_scene_node_destroy(opt_blur_node);
786 }
787 if (std_blur_node) {
788 wlr_scene_node_destroy(std_blur_node);
789 }
790 return;
791 }
792
793 if (width <= 0 || height <= 0) {
794 int size[2] = {0, 0};
795 wlr_scene_node_for_each_buffer(node, get_size_iterator, size);
796 width = size[0];
797 height = size[1];
798 x = 0;
799 y = 0;
800 }
801
802 if (width <= 0 || height <= 0) {
803 if (opt_blur_node) {
804 wlr_scene_node_destroy(opt_blur_node);
805 }
806 if (std_blur_node) {
807 wlr_scene_node_destroy(std_blur_node);
808 }
809 return;
810 }
811
812 if (optimized) {
813 if (!opt_blur_node) {
814 struct wlr_scene_optimized_blur *opt_blur = wlr_scene_optimized_blur_create(tree, width, height);
815 if (opt_blur) {
816 opt_blur_node = &opt_blur->node;
817 }
818 } else {
819 wlr_scene_optimized_blur_set_size((struct wlr_scene_optimized_blur *)opt_blur_node, width, height);
820 }
821 if (opt_blur_node) {
822 wlr_scene_node_set_position(opt_blur_node, x, y);
823 }
824 } else {
825 if (opt_blur_node) {
826 wlr_scene_node_destroy(opt_blur_node);
827 opt_blur_node = NULL;
828 }
829 }
830
831 if (!std_blur_node) {
832 struct wlr_scene_blur *std_blur = wlr_scene_blur_create(tree, width, height);
833 if (std_blur) {
834 std_blur_node = &std_blur->node;
835 wlr_scene_blur_set_should_only_blur_bottom_layer(std_blur, optimized);
836 }
837 } else {
838 wlr_scene_blur_set_should_only_blur_bottom_layer((struct wlr_scene_blur *)std_blur_node, optimized);
839 wlr_scene_blur_set_size((struct wlr_scene_blur *)std_blur_node, width, height);
840 }
841
842 // Set on both the create and the reuse path: a node reused across a resize keeps its
843 // radius, but one recreated after a blur toggle would otherwise come back square.
844 if (std_blur_node) {
845 wlr_scene_blur_set_corner_radius((struct wlr_scene_blur *)std_blur_node, corner_radius);
846 }
847
848 if (std_blur_node) {
849 wlr_scene_node_set_position(std_blur_node, x, y);
850 struct wlr_scene_buffer *source_buffer = NULL;
851 if (ignore_transparent) {
852 wlr_scene_node_for_each_buffer(node, find_buffer_iterator, &source_buffer);
853 }
854 wlr_scene_blur_set_transparency_mask_source((struct wlr_scene_blur *)std_blur_node, source_buffer);
855 }
856
857 // Ensure correct stack order (from back to front): opt_blur_node -> std_blur_node -> window content.
858 // Only reorder when out of order: the lower_to_bottom pair is not idempotent
859 // (on an already-ordered tree each call swaps the two nodes, and every swap
860 // damages the node's whole window-sized region — this runs per commit and
861 // per render_finish, so the no-op path must not touch the scene graph).
862 struct wlr_scene_node *want_bottom = opt_blur_node ? opt_blur_node : std_blur_node;
863 struct wlr_scene_node *want_second = opt_blur_node ? std_blur_node : NULL;
864 bool ordered = want_bottom != NULL
865 && tree->children.next == &want_bottom->link
866 && (want_second == NULL || want_bottom->link.next == &want_second->link);
867 if (!ordered) {
868 if (std_blur_node) {
869 wlr_scene_node_lower_to_bottom(std_blur_node);
870 }
871 if (opt_blur_node) {
872 wlr_scene_node_lower_to_bottom(opt_blur_node);
873 }
874 }
875 }
876
877 // Backdrop compression on the tree's standard blur node (see
878 // wlr_scene_blur_set_compress). Separate from river_scene_node_enable_blur so
879 // its many callers need not all carry it: call it after enable_blur, which may
880 // have just recreated the node with compression off.
881 void river_scene_node_set_blur_compress(struct wlr_scene_node *node, float ceil, float knee, bool invert) {
882 if (node->type != WLR_SCENE_NODE_TREE) {
883 return;
884 }
885 struct wlr_scene_node *std_blur_node = find_blur_node(wlr_scene_tree_from_node(node));
886 if (std_blur_node) {
887 wlr_scene_blur_set_compress((struct wlr_scene_blur *)std_blur_node, ceil, knee, invert);
888 }
889 }
890
891 static void set_opacity_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
892 (void)sx;
893 (void)sy;
894 float opacity = *(float *)user_data;
895 if (buffer->opacity != opacity) {
896 wlr_scene_buffer_set_opacity(buffer, opacity);
897 }
898 }
899
900 void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity) {
901 wlr_scene_node_for_each_buffer(node, set_opacity_iterator, &opacity);
902 if (node->type == WLR_SCENE_NODE_TREE) {
903 struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
904 struct wlr_scene_node *blur_node = find_blur_node(tree);
905 if (blur_node && blur_node->type == WLR_SCENE_NODE_BLUR) {
906 wlr_scene_blur_set_alpha((struct wlr_scene_blur *)blur_node, opacity);
907 }
908 }
909 }
910
911 static void set_corner_radius_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
912 (void)sx;
913 (void)sy;
914 int radius = *(int *)user_data;
915 wlr_scene_buffer_set_corner_radius(buffer, radius);
916 }
917
918 void river_scene_node_set_corner_radius(struct wlr_scene_node *node, int radius) {
919 wlr_scene_node_for_each_buffer(node, set_corner_radius_iterator, &radius);
920 if (node->type == WLR_SCENE_NODE_TREE) {
921 struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
922 struct wlr_scene_node *blur_node = find_blur_node(tree);
923 if (blur_node && blur_node->type == WLR_SCENE_NODE_BLUR) {
924 wlr_scene_blur_set_corner_radius((struct wlr_scene_blur *)blur_node, radius);
925 }
926 }
927 }
928
929 /* See wlr_scene_buffer_set_geometry_pinned(). The two setters below write
930 * through the pin, so every caller of theirs keeps working on a pinned
931 * buffer. */
932 void river_scene_buffer_set_geometry_pinned(struct wlr_scene_buffer *scene_buffer, bool pinned) {
933 wlr_scene_buffer_set_geometry_pinned(scene_buffer, pinned);
934 }
935
936 void river_scene_buffer_set_dest_size_if_changed(struct wlr_scene_buffer *scene_buffer, int width, int height) {
937 if (scene_buffer->dst_width != width || scene_buffer->dst_height != height) {
938 wlr_scene_buffer_set_dest_size_pinned(scene_buffer, width, height);
939 }
940 }
941
942 void river_scene_node_set_position_if_changed(struct wlr_scene_node *node, int x, int y) {
943 if (node->x != x || node->y != y) {
944 wlr_scene_node_set_position(node, x, y);
945 }
946 }
947
948 void river_scene_rect_set_size_if_changed(struct wlr_scene_rect *rect, int width, int height) {
949 if (rect->width != width || rect->height != height) {
950 wlr_scene_rect_set_size(rect, width, height);
951 }
952 }
953
954 void river_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int radius) {
955 wlr_scene_rect_set_corner_radius(rect, radius);
956 }
957
958 int river_scene_buffer_get_width(struct wlr_scene_buffer *scene_buffer) {
959 if (scene_buffer->buffer) {
960 return scene_buffer->buffer->width;
961 }
962 return scene_buffer->dst_width;
963 }
964
965 int river_scene_buffer_get_height(struct wlr_scene_buffer *scene_buffer) {
966 if (scene_buffer->buffer) {
967 return scene_buffer->buffer->height;
968 }
969 return scene_buffer->dst_height;
970 }
971
972 /* Scale a surface's opaque region to match a custom buffer dest size and
973 * apply it to the scene buffer. The scene keeps opaque regions in SURFACE
974 * coordinates and scenefx's occlusion culling only intersects them with the
975 * node box — so a zoomed-down window's unscaled opaque rect still covered
976 * (almost) the whole scaled node, INCLUDING its translucent CSD shadow
977 * margins. Culling then skipped repainting behind the shadow ring: stale
978 * pixels showed through the translucent shadow around focused windows when
979 * zoomed (worst at the bottom, where Chromium's ring is tallest). */
980 /* The subsurface clip on a surface buffer (wlr_scene_subsurface_tree_set_clip,
981 * applied by the window's apply_surface_clip as the xdg geometry): the part of
982 * the surface this buffer shows, in surface coordinates. wlroots crops the
983 * buffer's source box to it and sizes/positions the node from it on every
984 * commit, so every pass that rewrites a buffer's dest size or position must
985 * work from this extent rather than the surface's full size — or it stretches
986 * the cropped source back out to the whole surface. False (and an empty box)
987 * when the buffer is not a surface's or nothing is clipped. */
988 bool river_scene_buffer_get_surface_clip(struct wlr_scene_buffer *scene_buffer,
989 struct wlr_box *out) {
990 *out = (struct wlr_box){0};
991 struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer);
992 if (!scene_surface) {
993 return false;
994 }
995 *out = scene_surface->WLR_PRIVATE.clip;
996 return !wlr_box_empty(out);
997 }
998
999 void river_scene_buffer_set_scaled_opaque_region(struct wlr_scene_buffer *scene_buffer,
1000 struct wlr_surface *surface, double scale) {
1001 pixman_region32_t scaled;
1002 pixman_region32_init(&scaled);
1003 pixman_region32_copy(&scaled, &surface->opaque_region);
1004 /* A clipped buffer shows only `clip` of the surface, at its own origin:
1005 * bring the region into buffer space before scaling, or the part of it
1006 * that lies in the cropped-away margin claims pixels the node never
1007 * paints. */
1008 struct wlr_box clip;
1009 if (river_scene_buffer_get_surface_clip(scene_buffer, &clip)) {
1010 pixman_region32_translate(&scaled, -clip.x, -clip.y);
1011 pixman_region32_intersect_rect(&scaled, &scaled, 0, 0, clip.width, clip.height);
1012 }
1013 wlr_region_scale(&scaled, &scaled, (float)scale);
1014 wlr_scene_buffer_set_opaque_region_pinned(scene_buffer, &scaled);
1015 pixman_region32_fini(&scaled);
1016 }
1017
1018 int river_scene_buffer_get_dest_width(struct wlr_scene_buffer *scene_buffer) {
1019 return scene_buffer->dst_width;
1020 }
1021
1022 int river_scene_buffer_get_dest_height(struct wlr_scene_buffer *scene_buffer) {
1023 return scene_buffer->dst_height;
1024 }
1025
1026 bool river_scene_node_get_enabled(struct wlr_scene_node *node) {
1027 return node->enabled;
1028 }
1029
1030 /* Overview-delay debugging: dump the true scene-side state of every buffer
1031 * under a node — enabled flags, absolute position, dest size, whether a
1032 * wlr_buffer/texture is attached, the primary output, and the computed
1033 * visibility region. The visibility extents are the ground truth for "will
1034 * this buffer be drawn": an empty region means the scene considers it
1035 * invisible regardless of what the window-manager state says. */
1036 static void river_ovdbg_buffer_iter(struct wlr_scene_buffer *buffer,
1037 int sx, int sy, void *data) {
1038 const char *tag = data;
1039 struct wlr_scene_node *node = &buffer->node;
1040 int lx = 0, ly = 0;
1041 bool coords_en = wlr_scene_node_coords(node, &lx, &ly);
1042 pixman_box32_t *ext = pixman_region32_extents(&node->WLR_PRIVATE.visible);
1043 struct timespec ts;
1044 clock_gettime(CLOCK_REALTIME, &ts);
1045 fprintf(stderr,
1046 "[ovdbg] t=%ld.%03ld %s buf=%p en=%d coords_en=%d abs=(%d,%d) "
1047 "dst=%dx%d bufwh=%dx%d wlrbuf=%p tex=%p primary=%p vis=(%d,%d %dx%d)\n",
1048 (long)ts.tv_sec, ts.tv_nsec / 1000000, tag, (void *)buffer,
1049 node->enabled, coords_en, lx, ly,
1050 buffer->dst_width, buffer->dst_height,
1051 buffer->WLR_PRIVATE.buffer_width, buffer->WLR_PRIVATE.buffer_height,
1052 (void *)buffer->buffer, (void *)buffer->WLR_PRIVATE.texture,
1053 (void *)buffer->primary_output,
1054 ext->x1, ext->y1, ext->x2 - ext->x1, ext->y2 - ext->y1);
1055 }
1056
1057 void river_scene_ovdbg_dump(struct wlr_scene_node *node, const char *tag) {
1058 wlr_scene_node_for_each_buffer(node, river_ovdbg_buffer_iter, (void *)tag);
1059 }
1060
1061 /* Overview-delay/shadow debugging: report a window's drop-shadow node state so
1062 * it can be compared against the window's current zoom scale. Everything here
1063 * is device px, as update_shadow writes it. */
1064 void river_scene_shadow_dbg(struct wlr_scene_shadow *shadow, const char *tag) {
1065 if (!shadow) {
1066 fprintf(stderr, "[ovdbg] %s shadow=NULL\n", tag);
1067 return;
1068 }
1069 struct wlr_scene_node *node = &shadow->node;
1070 fprintf(stderr,
1071 "[ovdbg] %s shadow en=%d pos=(%d,%d) size=%dx%d sigma=%.1f radius=%d "
1072 "clip=(%d,%d %dx%d)\n",
1073 tag, node->enabled, node->x, node->y, shadow->width, shadow->height,
1074 shadow->blur_sigma, shadow->corner_radius,
1075 shadow->clipped_region.area.x, shadow->clipped_region.area.y,
1076 shadow->clipped_region.area.width, shadow->clipped_region.area.height);
1077 }
1078
1079 /* ------------------------------------------------------------------
1080 * CPU-backed buffer: lets the compositor hand the renderer pixels it
1081 * rasterized itself (the desktop-grid square labels). wlroots has no public
1082 * constructor for this, so implement the minimal wlr_buffer: the renderer
1083 * reaches the pixels through data-ptr access and uploads them like any shm
1084 * buffer. The data is copied in, so the caller's Rust Vec can be dropped.
1085 * ------------------------------------------------------------------ */
1086 struct cce_data_buffer {
1087 struct wlr_buffer base;
1088 void *data;
1089 uint32_t format;
1090 size_t stride;
1091 };
1092
1093 static void cce_data_buffer_destroy(struct wlr_buffer *wlr_buffer) {
1094 struct cce_data_buffer *buf = (struct cce_data_buffer *)wlr_buffer;
1095 free(buf->data);
1096 free(buf);
1097 }
1098
1099 static bool cce_data_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
1100 uint32_t flags, void **data, uint32_t *format, size_t *stride) {
1101 struct cce_data_buffer *buf = (struct cce_data_buffer *)wlr_buffer;
1102 if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) {
1103 return false; /* immutable once built */
1104 }
1105 *data = buf->data;
1106 *format = buf->format;
1107 *stride = buf->stride;
1108 return true;
1109 }
1110
1111 static void cce_data_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
1112 /* nothing to unmap */
1113 }
1114
1115 static const struct wlr_buffer_impl cce_data_buffer_impl = {
1116 .destroy = cce_data_buffer_destroy,
1117 .begin_data_ptr_access = cce_data_buffer_begin_data_ptr_access,
1118 .end_data_ptr_access = cce_data_buffer_end_data_ptr_access,
1119 };
1120
1121 /* Copy `data` (ARGB8888, premultiplied, `stride` bytes per row) into a new
1122 * buffer. Returns NULL on allocation failure. The buffer starts with one
1123 * reference, as wlr_buffer_init leaves it: pass it to a scene buffer and then
1124 * drop this reference with wlr_buffer_drop(). */
1125 struct wlr_buffer *river_data_buffer_create(int width, int height,
1126 size_t stride, const void *data) {
1127 if (width <= 0 || height <= 0 || stride == 0) {
1128 return NULL;
1129 }
1130 struct cce_data_buffer *buf = calloc(1, sizeof(*buf));
1131 if (!buf) {
1132 return NULL;
1133 }
1134 size_t size = stride * (size_t)height;
1135 buf->data = malloc(size);
1136 if (!buf->data) {
1137 free(buf);
1138 return NULL;
1139 }
1140 memcpy(buf->data, data, size);
1141 buf->format = DRM_FORMAT_ARGB8888;
1142 buf->stride = stride;
1143 wlr_buffer_init(&buf->base, &cce_data_buffer_impl, width, height);
1144 return &buf->base;
1145 }
1146
1147 /* Mark every optimized-blur node in the scene dirty, forcing a re-bake of the
1148 * shared blurred-backdrop cache on the next frame. The cache is otherwise
1149 * invalidated only by blur-parameter setters and window blur RESIZES
1150 * (optimized_blur_set_size marks dirty; a same-size re-enable does not), so
1151 * backdrop CONTENT that changes without either — the grid client latching a
1152 * new patch after the viewport has settled, or the client<->fallback grid
1153 * swap — leaves every translucent window showing a stale bake. */
1154 static void mark_optimized_blur_dirty_rec(struct wlr_scene_node *node) {
1155 if (node->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
1156 wlr_scene_optimized_blur_mark_dirty(wlr_scene_optimized_blur_from_node(node));
1157 return;
1158 }
1159 if (node->type == WLR_SCENE_NODE_TREE) {
1160 struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
1161 struct wlr_scene_node *child;
1162 wl_list_for_each(child, &tree->children, link) {
1163 mark_optimized_blur_dirty_rec(child);
1164 }
1165 }
1166 }
1167
1168 void river_scene_mark_optimized_blur_dirty(struct wlr_scene *scene) {
1169 mark_optimized_blur_dirty_rec(&scene->tree.node);
1170 }
1171
1172 /* See wlr_scene.blur_frozen: suspend the moved-node-below blur
1173 * invalidation for the duration of a camera pan. Thawing marks every
1174 * optimized blur dirty once so the settled frame re-bakes against the
1175 * final backdrop. */
1176 /* See wlr_scene.blur_frozen. Blurs sample the shared cache where their own
1177 * bake lives, frozen or not, and bake the strips they newly expose as they
1178 * travel, so a pan needs no re-bake at either end: the thaw is just the
1179 * flag. */
1180 void river_scene_set_blur_frozen(struct wlr_scene *scene, bool frozen) {
1181 scene->blur_frozen = frozen;
1182 }
1183
1184 /* See wlr_scene.desk_trees: this subtree renders with the desk's
1185 * sub-pixel offset. Idempotent; silently ignores a ninth tree. */
1186 struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
1187
1188 void river_scene_tree_set_desk_offset(struct wlr_scene_tree *tree, bool on) {
1189 struct wlr_scene *scene = scene_node_get_root(&tree->node);
1190 if (scene == NULL) {
1191 return;
1192 }
1193 int free_slot = -1;
1194 for (int i = 0; i < WLR_SCENE_DESK_TREES; i++) {
1195 if (scene->desk_trees[i] == tree) {
1196 if (!on) {
1197 scene->desk_trees[i] = NULL;
1198 }
1199 return;
1200 }
1201 if (scene->desk_trees[i] == NULL && free_slot < 0) {
1202 free_slot = i;
1203 }
1204 }
1205 if (on && free_slot >= 0) {
1206 scene->desk_trees[free_slot] = tree;
1207 }
1208 }
1209
1210 /* See wlr_scene.desk_sub_x/y: the camera pan's remainder below one
1211 * layout pixel, each in (-1, 0]. Changing it moves every desk node on
1212 * screen, which the caller damages (it is a camera move). */
1213 void river_scene_set_desk_subpixel(struct wlr_scene *scene, double sub_x, double sub_y) {
1214 scene->desk_sub_x = sub_x;
1215 scene->desk_sub_y = sub_y;
1216 }
1217
1218 struct wl_signal *river_wlr_session_get_active_signal(struct wlr_session *session) {
1219 return &session->events.active;
1220 }
1221
1222 bool river_wlr_session_get_active(struct wlr_session *session) {
1223 return session->active;
1224 }