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

src/server/wlroots_log_wrapper.c (40.2K)

   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 void river_wlr_seat_touch_cancel_all(struct wlr_seat *wlr_seat) {
 649 	struct wlr_touch_point *point, *tmp;
 650 	wl_list_for_each_safe(point, tmp, &wlr_seat->touch_state.touch_points, link) {
 651 		wlr_seat_touch_notify_cancel(wlr_seat, point->client);
 652 	}
 653 }
 654 
 655 struct wlr_surface *river_wlr_seat_get_keyboard_focused_surface(struct wlr_seat *seat) {
 656 	return seat->keyboard_state.focused_surface;
 657 }
 658 
 659 int river_wlr_surface_get_width(struct wlr_surface *surface) {
 660 	return surface->current.width;
 661 }
 662 
 663 int river_wlr_surface_get_height(struct wlr_surface *surface) {
 664 	return surface->current.height;
 665 }
 666 
 667 // Commit sequence of a surface's current state. Cheap "has this drawn
 668 // anything new?" key for the status-bar backdrop sampler, which is trying
 669 // hard NOT to read back a texture it has already read.
 670 uint32_t river_wlr_surface_current_seq(struct wlr_surface *surface) {
 671 	return surface->current.seq;
 672 }
 673 
 674 void river_wlr_surface_get_buffer_size(struct wlr_surface *surface, int *width, int *height) {
 675 	*width = surface->current.buffer_width;
 676 	*height = surface->current.buffer_height;
 677 }
 678 
 679 struct wlr_keyboard *river_wlr_input_method_keyboard_grab_v2_get_keyboard(struct wlr_input_method_keyboard_grab_v2 *grab) {
 680 	return grab->keyboard;
 681 }
 682 
 683 struct wl_signal *river_wlr_input_method_keyboard_grab_v2_get_destroy_signal(struct wlr_input_method_keyboard_grab_v2 *grab) {
 684 	return &grab->events.destroy;
 685 }
 686 
 687 struct wlr_drag_icon *river_wlr_drag_get_icon(struct wlr_drag *drag) {
 688 	return drag->icon;
 689 }
 690 
 691 struct wlr_seat *river_wlr_drag_get_seat(struct wlr_drag *drag) {
 692 	return drag->seat;
 693 }
 694 
 695 enum wlr_drag_grab_type river_wlr_drag_get_grab_type(struct wlr_drag *drag) {
 696 	return drag->grab_type;
 697 }
 698 
 699 int32_t river_wlr_drag_get_touch_id(struct wlr_drag *drag) {
 700 	return drag->touch_id;
 701 }
 702 
 703 struct wlr_data_source *river_wlr_drag_get_source(struct wlr_drag *drag) {
 704 	return drag->source;
 705 }
 706 
 707 struct wl_signal *river_wlr_drag_get_destroy_signal(struct wlr_drag *drag) {
 708 	return &drag->events.destroy;
 709 }
 710 
 711 struct wlr_seat_client *river_wlr_drag_get_seat_client(struct wlr_drag *drag) {
 712 	return drag->seat_client;
 713 }
 714 
 715 void river_wlr_keyboard_init(struct wlr_keyboard *keyboard,
 716 		void (*led_update)(struct wlr_keyboard *keyboard, uint32_t leds),
 717 		const char *name) {
 718 	static struct wlr_keyboard_impl impl;
 719 	static bool impl_initialized = false;
 720 	if (!impl_initialized) {
 721 		impl.name = name;
 722 		impl.led_update = led_update;
 723 		impl_initialized = true;
 724 	}
 725 	wlr_keyboard_init(keyboard, &impl, name);
 726 }
 727 
 728 static struct wlr_scene_node *find_blur_node(struct wlr_scene_tree *tree) {
 729 	struct wlr_scene_node *child;
 730 	wl_list_for_each(child, &tree->children, link) {
 731 		if (child->type == WLR_SCENE_NODE_BLUR) {
 732 			return child;
 733 		}
 734 	}
 735 	return NULL;
 736 }
 737 
 738 static struct wlr_scene_node *find_optimized_blur_node(struct wlr_scene_tree *tree) {
 739 	struct wlr_scene_node *child;
 740 	wl_list_for_each(child, &tree->children, link) {
 741 		if (child->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
 742 			return child;
 743 		}
 744 	}
 745 	return NULL;
 746 }
 747 
 748 static void get_size_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 749 	(void)sx;
 750 	(void)sy;
 751 	int *size = (int *)user_data;
 752 	if (buffer->dst_width > size[0]) size[0] = buffer->dst_width;
 753 	if (buffer->dst_height > size[1]) size[1] = buffer->dst_height;
 754 }
 755 
 756 static void find_buffer_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 757 	(void)sx;
 758 	(void)sy;
 759 	struct wlr_scene_buffer **result = (struct wlr_scene_buffer **)user_data;
 760 	if (*result == NULL) {
 761 		*result = buffer;
 762 	}
 763 }
 764 
 765 // `corner_radius` is in the same (scaled, device) pixels as width/height. It is applied
 766 // here rather than through river_scene_node_set_corner_radius so that a blur node can
 767 // never exist without it: that helper looks the blur up by scanning a tree's direct
 768 // children, so aiming it at the wrong tree silently no-ops, and it was never called at
 769 // all on the viewport-update path. Note the optimized blur node cannot be rounded --
 770 // wlr_scene_optimized_blur has no radius field -- so callers that need rounded corners
 771 // must pass optimized = false.
 772 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) {
 773 	if (node->type != WLR_SCENE_NODE_TREE) {
 774 		return;
 775 	}
 776 	struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
 777 	struct wlr_scene_node *opt_blur_node = find_optimized_blur_node(tree);
 778 	struct wlr_scene_node *std_blur_node = find_blur_node(tree);
 779 
 780 	if (!enabled) {
 781 		if (opt_blur_node) {
 782 			wlr_scene_node_destroy(opt_blur_node);
 783 		}
 784 		if (std_blur_node) {
 785 			wlr_scene_node_destroy(std_blur_node);
 786 		}
 787 		return;
 788 	}
 789 
 790 	if (width <= 0 || height <= 0) {
 791 		int size[2] = {0, 0};
 792 		wlr_scene_node_for_each_buffer(node, get_size_iterator, size);
 793 		width = size[0];
 794 		height = size[1];
 795 		x = 0;
 796 		y = 0;
 797 	}
 798 
 799 	if (width <= 0 || height <= 0) {
 800 		if (opt_blur_node) {
 801 			wlr_scene_node_destroy(opt_blur_node);
 802 		}
 803 		if (std_blur_node) {
 804 			wlr_scene_node_destroy(std_blur_node);
 805 		}
 806 		return;
 807 	}
 808 
 809 	if (optimized) {
 810 		if (!opt_blur_node) {
 811 			struct wlr_scene_optimized_blur *opt_blur = wlr_scene_optimized_blur_create(tree, width, height);
 812 			if (opt_blur) {
 813 				opt_blur_node = &opt_blur->node;
 814 			}
 815 		} else {
 816 			wlr_scene_optimized_blur_set_size((struct wlr_scene_optimized_blur *)opt_blur_node, width, height);
 817 		}
 818 		if (opt_blur_node) {
 819 			wlr_scene_node_set_position(opt_blur_node, x, y);
 820 		}
 821 	} else {
 822 		if (opt_blur_node) {
 823 			wlr_scene_node_destroy(opt_blur_node);
 824 			opt_blur_node = NULL;
 825 		}
 826 	}
 827 
 828 	if (!std_blur_node) {
 829 		struct wlr_scene_blur *std_blur = wlr_scene_blur_create(tree, width, height);
 830 		if (std_blur) {
 831 			std_blur_node = &std_blur->node;
 832 			wlr_scene_blur_set_should_only_blur_bottom_layer(std_blur, optimized);
 833 		}
 834 	} else {
 835 		wlr_scene_blur_set_should_only_blur_bottom_layer((struct wlr_scene_blur *)std_blur_node, optimized);
 836 		wlr_scene_blur_set_size((struct wlr_scene_blur *)std_blur_node, width, height);
 837 	}
 838 
 839 	// Set on both the create and the reuse path: a node reused across a resize keeps its
 840 	// radius, but one recreated after a blur toggle would otherwise come back square.
 841 	if (std_blur_node) {
 842 		wlr_scene_blur_set_corner_radius((struct wlr_scene_blur *)std_blur_node, corner_radius);
 843 	}
 844 
 845 	if (std_blur_node) {
 846 		wlr_scene_node_set_position(std_blur_node, x, y);
 847 		struct wlr_scene_buffer *source_buffer = NULL;
 848 		if (ignore_transparent) {
 849 			wlr_scene_node_for_each_buffer(node, find_buffer_iterator, &source_buffer);
 850 		}
 851 		wlr_scene_blur_set_transparency_mask_source((struct wlr_scene_blur *)std_blur_node, source_buffer);
 852 	}
 853 
 854 	// Ensure correct stack order (from back to front): opt_blur_node -> std_blur_node -> window content.
 855 	// Only reorder when out of order: the lower_to_bottom pair is not idempotent
 856 	// (on an already-ordered tree each call swaps the two nodes, and every swap
 857 	// damages the node's whole window-sized region — this runs per commit and
 858 	// per render_finish, so the no-op path must not touch the scene graph).
 859 	struct wlr_scene_node *want_bottom = opt_blur_node ? opt_blur_node : std_blur_node;
 860 	struct wlr_scene_node *want_second = opt_blur_node ? std_blur_node : NULL;
 861 	bool ordered = want_bottom != NULL
 862 		&& tree->children.next == &want_bottom->link
 863 		&& (want_second == NULL || want_bottom->link.next == &want_second->link);
 864 	if (!ordered) {
 865 		if (std_blur_node) {
 866 			wlr_scene_node_lower_to_bottom(std_blur_node);
 867 		}
 868 		if (opt_blur_node) {
 869 			wlr_scene_node_lower_to_bottom(opt_blur_node);
 870 		}
 871 	}
 872 }
 873 
 874 static void set_opacity_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 875 	(void)sx;
 876 	(void)sy;
 877 	float opacity = *(float *)user_data;
 878 	if (buffer->opacity != opacity) {
 879 		wlr_scene_buffer_set_opacity(buffer, opacity);
 880 	}
 881 }
 882 
 883 void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity) {
 884 	wlr_scene_node_for_each_buffer(node, set_opacity_iterator, &opacity);
 885 	if (node->type == WLR_SCENE_NODE_TREE) {
 886 		struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
 887 		struct wlr_scene_node *blur_node = find_blur_node(tree);
 888 		if (blur_node && blur_node->type == WLR_SCENE_NODE_BLUR) {
 889 			wlr_scene_blur_set_alpha((struct wlr_scene_blur *)blur_node, opacity);
 890 		}
 891 	}
 892 }
 893 
 894 static void set_corner_radius_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 895 	(void)sx;
 896 	(void)sy;
 897 	int radius = *(int *)user_data;
 898 	wlr_scene_buffer_set_corner_radius(buffer, radius);
 899 }
 900 
 901 void river_scene_node_set_corner_radius(struct wlr_scene_node *node, int radius) {
 902 	wlr_scene_node_for_each_buffer(node, set_corner_radius_iterator, &radius);
 903 	if (node->type == WLR_SCENE_NODE_TREE) {
 904 		struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
 905 		struct wlr_scene_node *blur_node = find_blur_node(tree);
 906 		if (blur_node && blur_node->type == WLR_SCENE_NODE_BLUR) {
 907 			wlr_scene_blur_set_corner_radius((struct wlr_scene_blur *)blur_node, radius);
 908 		}
 909 	}
 910 }
 911 
 912 void river_scene_buffer_set_dest_size_if_changed(struct wlr_scene_buffer *scene_buffer, int width, int height) {
 913 	if (scene_buffer->dst_width != width || scene_buffer->dst_height != height) {
 914 		wlr_scene_buffer_set_dest_size(scene_buffer, width, height);
 915 	}
 916 }
 917 
 918 void river_scene_node_set_position_if_changed(struct wlr_scene_node *node, int x, int y) {
 919 	if (node->x != x || node->y != y) {
 920 		wlr_scene_node_set_position(node, x, y);
 921 	}
 922 }
 923 
 924 void river_scene_rect_set_size_if_changed(struct wlr_scene_rect *rect, int width, int height) {
 925 	if (rect->width != width || rect->height != height) {
 926 		wlr_scene_rect_set_size(rect, width, height);
 927 	}
 928 }
 929 
 930 void river_scene_rect_set_corner_radius(struct wlr_scene_rect *rect, int radius) {
 931 	wlr_scene_rect_set_corner_radius(rect, radius);
 932 }
 933 
 934 int river_scene_buffer_get_width(struct wlr_scene_buffer *scene_buffer) {
 935 	if (scene_buffer->buffer) {
 936 		return scene_buffer->buffer->width;
 937 	}
 938 	return scene_buffer->dst_width;
 939 }
 940 
 941 int river_scene_buffer_get_height(struct wlr_scene_buffer *scene_buffer) {
 942 	if (scene_buffer->buffer) {
 943 		return scene_buffer->buffer->height;
 944 	}
 945 	return scene_buffer->dst_height;
 946 }
 947 
 948 /* Scale a surface's opaque region to match a custom buffer dest size and
 949  * apply it to the scene buffer. The scene keeps opaque regions in SURFACE
 950  * coordinates and scenefx's occlusion culling only intersects them with the
 951  * node box — so a zoomed-down window's unscaled opaque rect still covered
 952  * (almost) the whole scaled node, INCLUDING its translucent CSD shadow
 953  * margins. Culling then skipped repainting behind the shadow ring: stale
 954  * pixels showed through the translucent shadow around focused windows when
 955  * zoomed (worst at the bottom, where Chromium's ring is tallest). */
 956 /* The subsurface clip on a surface buffer (wlr_scene_subsurface_tree_set_clip,
 957  * applied by the window's apply_surface_clip as the xdg geometry): the part of
 958  * the surface this buffer shows, in surface coordinates. wlroots crops the
 959  * buffer's source box to it and sizes/positions the node from it on every
 960  * commit, so every pass that rewrites a buffer's dest size or position must
 961  * work from this extent rather than the surface's full size — or it stretches
 962  * the cropped source back out to the whole surface. False (and an empty box)
 963  * when the buffer is not a surface's or nothing is clipped. */
 964 bool river_scene_buffer_get_surface_clip(struct wlr_scene_buffer *scene_buffer,
 965 		struct wlr_box *out) {
 966 	*out = (struct wlr_box){0};
 967 	struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer);
 968 	if (!scene_surface) {
 969 		return false;
 970 	}
 971 	*out = scene_surface->WLR_PRIVATE.clip;
 972 	return !wlr_box_empty(out);
 973 }
 974 
 975 void river_scene_buffer_set_scaled_opaque_region(struct wlr_scene_buffer *scene_buffer,
 976 		struct wlr_surface *surface, double scale) {
 977 	pixman_region32_t scaled;
 978 	pixman_region32_init(&scaled);
 979 	pixman_region32_copy(&scaled, &surface->opaque_region);
 980 	/* A clipped buffer shows only `clip` of the surface, at its own origin:
 981 	 * bring the region into buffer space before scaling, or the part of it
 982 	 * that lies in the cropped-away margin claims pixels the node never
 983 	 * paints. */
 984 	struct wlr_box clip;
 985 	if (river_scene_buffer_get_surface_clip(scene_buffer, &clip)) {
 986 		pixman_region32_translate(&scaled, -clip.x, -clip.y);
 987 		pixman_region32_intersect_rect(&scaled, &scaled, 0, 0, clip.width, clip.height);
 988 	}
 989 	wlr_region_scale(&scaled, &scaled, (float)scale);
 990 	wlr_scene_buffer_set_opaque_region(scene_buffer, &scaled);
 991 	pixman_region32_fini(&scaled);
 992 }
 993 
 994 int river_scene_buffer_get_dest_width(struct wlr_scene_buffer *scene_buffer) {
 995 	return scene_buffer->dst_width;
 996 }
 997 
 998 int river_scene_buffer_get_dest_height(struct wlr_scene_buffer *scene_buffer) {
 999 	return scene_buffer->dst_height;
1000 }
1001 
1002 bool river_scene_node_get_enabled(struct wlr_scene_node *node) {
1003 	return node->enabled;
1004 }
1005 
1006 /* Overview-delay debugging: dump the true scene-side state of every buffer
1007  * under a node — enabled flags, absolute position, dest size, whether a
1008  * wlr_buffer/texture is attached, the primary output, and the computed
1009  * visibility region. The visibility extents are the ground truth for "will
1010  * this buffer be drawn": an empty region means the scene considers it
1011  * invisible regardless of what the window-manager state says. */
1012 static void river_ovdbg_buffer_iter(struct wlr_scene_buffer *buffer,
1013 		int sx, int sy, void *data) {
1014 	const char *tag = data;
1015 	struct wlr_scene_node *node = &buffer->node;
1016 	int lx = 0, ly = 0;
1017 	bool coords_en = wlr_scene_node_coords(node, &lx, &ly);
1018 	pixman_box32_t *ext = pixman_region32_extents(&node->WLR_PRIVATE.visible);
1019 	struct timespec ts;
1020 	clock_gettime(CLOCK_REALTIME, &ts);
1021 	fprintf(stderr,
1022 		"[ovdbg] t=%ld.%03ld %s buf=%p en=%d coords_en=%d abs=(%d,%d) "
1023 		"dst=%dx%d bufwh=%dx%d wlrbuf=%p tex=%p primary=%p vis=(%d,%d %dx%d)\n",
1024 		(long)ts.tv_sec, ts.tv_nsec / 1000000, tag, (void *)buffer,
1025 		node->enabled, coords_en, lx, ly,
1026 		buffer->dst_width, buffer->dst_height,
1027 		buffer->WLR_PRIVATE.buffer_width, buffer->WLR_PRIVATE.buffer_height,
1028 		(void *)buffer->buffer, (void *)buffer->WLR_PRIVATE.texture,
1029 		(void *)buffer->primary_output,
1030 		ext->x1, ext->y1, ext->x2 - ext->x1, ext->y2 - ext->y1);
1031 }
1032 
1033 void river_scene_ovdbg_dump(struct wlr_scene_node *node, const char *tag) {
1034 	wlr_scene_node_for_each_buffer(node, river_ovdbg_buffer_iter, (void *)tag);
1035 }
1036 
1037 /* Overview-delay/shadow debugging: report a window's drop-shadow node state so
1038  * it can be compared against the window's current zoom scale. Everything here
1039  * is device px, as update_shadow writes it. */
1040 void river_scene_shadow_dbg(struct wlr_scene_shadow *shadow, const char *tag) {
1041 	if (!shadow) {
1042 		fprintf(stderr, "[ovdbg] %s shadow=NULL\n", tag);
1043 		return;
1044 	}
1045 	struct wlr_scene_node *node = &shadow->node;
1046 	fprintf(stderr,
1047 		"[ovdbg] %s shadow en=%d pos=(%d,%d) size=%dx%d sigma=%.1f radius=%d "
1048 		"clip=(%d,%d %dx%d)\n",
1049 		tag, node->enabled, node->x, node->y, shadow->width, shadow->height,
1050 		shadow->blur_sigma, shadow->corner_radius,
1051 		shadow->clipped_region.area.x, shadow->clipped_region.area.y,
1052 		shadow->clipped_region.area.width, shadow->clipped_region.area.height);
1053 }
1054 
1055 /* ------------------------------------------------------------------
1056  * CPU-backed buffer: lets the compositor hand the renderer pixels it
1057  * rasterized itself (the desktop-grid square labels). wlroots has no public
1058  * constructor for this, so implement the minimal wlr_buffer: the renderer
1059  * reaches the pixels through data-ptr access and uploads them like any shm
1060  * buffer. The data is copied in, so the caller's Rust Vec can be dropped.
1061  * ------------------------------------------------------------------ */
1062 struct cce_data_buffer {
1063 	struct wlr_buffer base;
1064 	void *data;
1065 	uint32_t format;
1066 	size_t stride;
1067 };
1068 
1069 static void cce_data_buffer_destroy(struct wlr_buffer *wlr_buffer) {
1070 	struct cce_data_buffer *buf = (struct cce_data_buffer *)wlr_buffer;
1071 	free(buf->data);
1072 	free(buf);
1073 }
1074 
1075 static bool cce_data_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
1076 		uint32_t flags, void **data, uint32_t *format, size_t *stride) {
1077 	struct cce_data_buffer *buf = (struct cce_data_buffer *)wlr_buffer;
1078 	if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) {
1079 		return false; /* immutable once built */
1080 	}
1081 	*data = buf->data;
1082 	*format = buf->format;
1083 	*stride = buf->stride;
1084 	return true;
1085 }
1086 
1087 static void cce_data_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
1088 	/* nothing to unmap */
1089 }
1090 
1091 static const struct wlr_buffer_impl cce_data_buffer_impl = {
1092 	.destroy = cce_data_buffer_destroy,
1093 	.begin_data_ptr_access = cce_data_buffer_begin_data_ptr_access,
1094 	.end_data_ptr_access = cce_data_buffer_end_data_ptr_access,
1095 };
1096 
1097 /* Copy `data` (ARGB8888, premultiplied, `stride` bytes per row) into a new
1098  * buffer. Returns NULL on allocation failure. The buffer starts with one
1099  * reference, as wlr_buffer_init leaves it: pass it to a scene buffer and then
1100  * drop this reference with wlr_buffer_drop(). */
1101 struct wlr_buffer *river_data_buffer_create(int width, int height,
1102 		size_t stride, const void *data) {
1103 	if (width <= 0 || height <= 0 || stride == 0) {
1104 		return NULL;
1105 	}
1106 	struct cce_data_buffer *buf = calloc(1, sizeof(*buf));
1107 	if (!buf) {
1108 		return NULL;
1109 	}
1110 	size_t size = stride * (size_t)height;
1111 	buf->data = malloc(size);
1112 	if (!buf->data) {
1113 		free(buf);
1114 		return NULL;
1115 	}
1116 	memcpy(buf->data, data, size);
1117 	buf->format = DRM_FORMAT_ARGB8888;
1118 	buf->stride = stride;
1119 	wlr_buffer_init(&buf->base, &cce_data_buffer_impl, width, height);
1120 	return &buf->base;
1121 }
1122 
1123 /* Mark every optimized-blur node in the scene dirty, forcing a re-bake of the
1124  * shared blurred-backdrop cache on the next frame. The cache is otherwise
1125  * invalidated only by blur-parameter setters and window blur RESIZES
1126  * (optimized_blur_set_size marks dirty; a same-size re-enable does not), so
1127  * backdrop CONTENT that changes without either — the grid client latching a
1128  * new patch after the viewport has settled, or the client<->fallback grid
1129  * swap — leaves every translucent window showing a stale bake. */
1130 static void mark_optimized_blur_dirty_rec(struct wlr_scene_node *node) {
1131 	if (node->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
1132 		wlr_scene_optimized_blur_mark_dirty(wlr_scene_optimized_blur_from_node(node));
1133 		return;
1134 	}
1135 	if (node->type == WLR_SCENE_NODE_TREE) {
1136 		struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
1137 		struct wlr_scene_node *child;
1138 		wl_list_for_each(child, &tree->children, link) {
1139 			mark_optimized_blur_dirty_rec(child);
1140 		}
1141 	}
1142 }
1143 
1144 void river_scene_mark_optimized_blur_dirty(struct wlr_scene *scene) {
1145 	mark_optimized_blur_dirty_rec(&scene->tree.node);
1146 }
1147 
1148 /* See wlr_scene.blur_frozen: suspend the moved-node-below blur
1149  * invalidation for the duration of a camera pan. Thawing marks every
1150  * optimized blur dirty once so the settled frame re-bakes against the
1151  * final backdrop. */
1152 /* See wlr_scene.blur_frozen. Blurs sample the shared cache where their own
1153  * bake lives, frozen or not, and bake the strips they newly expose as they
1154  * travel, so a pan needs no re-bake at either end: the thaw is just the
1155  * flag. */
1156 void river_scene_set_blur_frozen(struct wlr_scene *scene, bool frozen) {
1157 	scene->blur_frozen = frozen;
1158 }
1159 
1160 /* See wlr_scene.desk_trees: this subtree renders with the desk's
1161  * sub-pixel offset. Idempotent; silently ignores a ninth tree. */
1162 struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
1163 
1164 void river_scene_tree_set_desk_offset(struct wlr_scene_tree *tree, bool on) {
1165 	struct wlr_scene *scene = scene_node_get_root(&tree->node);
1166 	if (scene == NULL) {
1167 		return;
1168 	}
1169 	int free_slot = -1;
1170 	for (int i = 0; i < WLR_SCENE_DESK_TREES; i++) {
1171 		if (scene->desk_trees[i] == tree) {
1172 			if (!on) {
1173 				scene->desk_trees[i] = NULL;
1174 			}
1175 			return;
1176 		}
1177 		if (scene->desk_trees[i] == NULL && free_slot < 0) {
1178 			free_slot = i;
1179 		}
1180 	}
1181 	if (on && free_slot >= 0) {
1182 		scene->desk_trees[free_slot] = tree;
1183 	}
1184 }
1185 
1186 /* See wlr_scene.desk_sub_x/y: the camera pan's remainder below one
1187  * layout pixel, each in (-1, 0]. Changing it moves every desk node on
1188  * screen, which the caller damages (it is a camera move). */
1189 void river_scene_set_desk_subpixel(struct wlr_scene *scene, double sub_x, double sub_y) {
1190 	scene->desk_sub_x = sub_x;
1191 	scene->desk_sub_y = sub_y;
1192 }
1193 
1194 struct wl_signal *river_wlr_session_get_active_signal(struct wlr_session *session) {
1195 	return &session->events.active;
1196 }
1197 
1198 bool river_wlr_session_get_active(struct wlr_session *session) {
1199 	return session->active;
1200 }