Codebase list wlroots / 0ba142e
Merge tag '0.5.0' into debian/sid wlroots 0.5.0 Brian Ashworth (1): wlr_output_layout_get_box: handle empty layout Guido Günther (4): Unbreak build with '-Wstrict-prototypes' rootston/view: Remove redundant declaration in the same file wlr_xdg_shell: Remove redundant declaration in the same file Remove glEGLImageTargetTexture2DOES Ian Fan (1): seat: fix remaining wlr_button_state enum rename Ilia Bozhinov (2): xwm: use min size as base size hint if it is missing and vice versa xwm: fix typos in WM_NORMAL_HINTS handling Niklas Schulze (1): backend/session: Allow setting a custom tty via WLR_DIRECT_TTY Scott Anderson (1): backend/drm: Don't fail on failing to find overlay format emersion (15): seat: guard against button count corruption meson: enable more compiler warnings seat: use wlr_button_state enum instead of uint32_t seat: only store serial if pressing a button tinywl: send pointer frame events backend/session: add noop session rootston: refactor rendering rootston: fix rotated views rendering rootston: fix Xwayland children rendering when fullscreen rootston: split rendering code into render.c rootston: fix input events for rotated views xwayland: don't set DISPLAY seat: add debug logs when validating grab serials backend/session: open TTY with O_CLOEXEC for direct session xwayland: set CLOEXEC on /dev/null FD Guido Günther 5 years ago
36 changed file(s) with 870 addition(s) and 745 deletion(s). Raw diff Collapse all Expand all
132132 rgb_format = fmt;
133133 }
134134 }
135 if (rgb_format == DRM_FORMAT_INVALID) {
135 // Some overlays exist which don't support XRGB8888/ARGB8888
136 // We aren't even using overlay planes currently, so don't fail
137 // on something unnecessary.
138 if (type != DRM_PLANE_TYPE_OVERLAY && rgb_format == DRM_FORMAT_INVALID) {
136139 wlr_log(WLR_ERROR, "Failed to find an RGB format for plane %zu", i);
137140 drmModeFreePlane(plane);
138141 goto error_planes;
2222 'noop/backend.c',
2323 'noop/output.c',
2424 'session/direct-ipc.c',
25 'session/noop.c',
2526 'session/session.c',
2627 'wayland/backend.c',
2728 'wayland/output.c',
154154 }
155155
156156 static bool setup_tty(struct direct_session *session, struct wl_display *display) {
157 int fd = open("/dev/tty", O_RDWR);
157
158 bool default_tty = false;
159
160 const char *tty_path = getenv("WLR_DIRECT_TTY");
161
162 if (!tty_path) {
163 tty_path = "/dev/tty";
164 default_tty = true;
165 }
166
167 int fd = open(tty_path, O_RDWR | O_CLOEXEC);
158168 if (fd == -1) {
159 wlr_log_errno(WLR_ERROR, "Cannot open /dev/tty");
169 wlr_log_errno(WLR_ERROR, "Cannot open %s", tty_path);
160170 return false;
161171 }
162172
175185 goto error;
176186 }
177187
178 if (kd_mode != KD_TEXT) {
188 if (default_tty && kd_mode != KD_TEXT) {
179189 wlr_log(WLR_ERROR,
180190 "tty already in graphics mode; is another display server running?");
181191 goto error;
439439 int ret;
440440
441441 char str[256];
442 const char *fmt = "type='signal',"
442 const char fmt[] = "type='signal',"
443443 "sender='org.freedesktop.login1',"
444444 "interface='org.freedesktop.login1.%s',"
445445 "member='%s',"
0 #define _POSIX_C_SOURCE 200809L
1 #include <fcntl.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <wayland-server.h>
6 #include <wlr/backend/session/interface.h>
7 #include <wlr/util/log.h>
8 #include "util/signal.h"
9
10 const struct session_impl session_noop;
11
12 static int noop_session_open(struct wlr_session *base, const char *path) {
13 return open(path, O_RDWR | O_CLOEXEC);
14 }
15
16 static void noop_session_close(struct wlr_session *base, int fd) {
17 close(fd);
18 }
19
20 static bool noop_change_vt(struct wlr_session *base, unsigned vt) {
21 return false;
22 }
23
24 static void noop_session_destroy(struct wlr_session *base) {
25 free(base);
26 }
27
28 static struct wlr_session *noop_session_create(struct wl_display *disp) {
29 struct wlr_session *session = calloc(1, sizeof(*session));
30 if (!session) {
31 wlr_log_errno(WLR_ERROR, "Allocation failed");
32 return NULL;
33 }
34
35 session->impl = &session_noop;
36
37 wlr_log(WLR_INFO, "Successfully initialized noop session");
38 return session;
39 }
40
41 const struct session_impl session_noop = {
42 .create = noop_session_create,
43 .destroy = noop_session_destroy,
44 .open = noop_session_open,
45 .close = noop_session_close,
46 .change_vt = noop_change_vt,
47 };
1616
1717 extern const struct session_impl session_logind;
1818 extern const struct session_impl session_direct;
19 extern const struct session_impl session_noop;
1920
2021 static const struct session_impl *impls[] = {
2122 #if WLR_HAS_SYSTEMD || WLR_HAS_ELOGIND
6869
6970 const char *env_wlr_session = getenv("WLR_SESSION");
7071 if (env_wlr_session) {
71 if (!strcmp(env_wlr_session, "logind") || !strcmp(env_wlr_session, "systemd")) {
72 #if WLR_HAS_SYSTEMD || WLR_HAS_ELOGIND
72 if (strcmp(env_wlr_session, "logind") == 0 ||
73 strcmp(env_wlr_session, "systemd") == 0) {
74 #if WLR_HAS_SYSTEMD || WLR_HAS_ELOGIND
7375 session = session_logind.create(disp);
74 #else
76 #else
7577 wlr_log(WLR_ERROR, "wlroots is not compiled with logind support");
76 #endif
77 } else if (!strcmp(env_wlr_session, "direct")) {
78 #endif
79 } else if (strcmp(env_wlr_session, "direct") == 0) {
7880 session = session_direct.create(disp);
81 } else if (strcmp(env_wlr_session, "noop") == 0) {
82 session = session_noop.create(disp);
7983 } else {
80 wlr_log(WLR_ERROR, "WLR_SESSION has an invalid value: %s", env_wlr_session);
84 wlr_log(WLR_ERROR, "Unsupported WLR_SESSION: %s",
85 env_wlr_session);
8186 }
8287 } else {
8388 const struct session_impl **iter;
219224 /* Tests if 'path' is KMS compatible by trying to open it.
220225 * It leaves the open device in *fd_out it it succeeds.
221226 */
222 static int open_if_kms(struct wlr_session *restrict session, const char *restrict path) {
223 int fd;
224
227 static int open_if_kms(struct wlr_session *restrict session,
228 const char *restrict path) {
225229 if (!path) {
226230 return -1;
227231 }
228232
229 fd = wlr_session_open_file(session, path);
233 int fd = wlr_session_open_file(session, path);
230234 if (fd < 0) {
231235 return -1;
232236 }
233237
234 drmModeRes *res = drmModeGetResources(fd);
235 if (!res) {
238 drmVersion *ver = drmGetVersion(fd);
239 if (!ver) {
236240 goto out_fd;
237241 }
238242
239 drmModeFreeResources(res);
243 drmFreeVersion(ver);
240244 return fd;
241245
242246 out_fd:
193193 // TODO: set keymap
194194 }
195195
196 static uint32_t get_current_time_msec() {
196 static uint32_t get_current_time_msec(void) {
197197 struct timespec now;
198198 clock_gettime(CLOCK_MONOTONIC, &now);
199199 return now.tv_nsec / 1000;
1919 hardware cursors
2020 * *WLR_SESSION*: specifies the wlr\_session to be used (available sessions:
2121 logind/systemd, direct)
22 * *WLR_DIRECT_TTY*: specifies the tty to be used (instead of using /dev/tty)
2223
2324 rootston specific
2425 ------------------
175175 }
176176 }
177177
178 static void do_updates() {
178 static void do_updates(void) {
179179 printf("Update %d\n", update_stage);
180180 switch (update_stage) {
181181 case 0:
239239 };
240240 }
241241
242 static void handle_timer() {
242 static void handle_timer(void) {
243243 printf("Timer dispatched at %d\n", update_stage);
244244 do_updates();
245245 }
101101 }
102102
103103 // TODO: would be nicer to have this text display inside the window
104 static void show_status() {
104 static void show_status(void) {
105105 printf("State %d:", serial);
106106 if (!enabled) {
107107 printf(" disabled");
1414 #include <wlr/render/wlr_renderer.h>
1515 #include <wlr/render/wlr_texture.h>
1616 #include <wlr/util/log.h>
17
18 extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
1917
2018 struct wlr_gles2_pixel_format {
2119 enum wl_shm_format wl_format;
2828 struct wl_listener damage_destroy;
2929 };
3030
31 typedef void (*roots_surface_iterator_func_t)(struct roots_output *output,
32 struct wlr_surface *surface, struct wlr_box *box, float rotation,
33 void *user_data);
34
3135 void rotate_child_position(double *sx, double *sy, double sw, double sh,
3236 double pw, double ph, float rotation);
37
38 struct roots_input;
39
40 void output_surface_for_each_surface(struct roots_output *output,
41 struct wlr_surface *surface, double ox, double oy,
42 roots_surface_iterator_func_t iterator, void *user_data);
43 void output_view_for_each_surface(struct roots_output *output,
44 struct roots_view *view, roots_surface_iterator_func_t iterator,
45 void *user_data);
46 void output_drag_icons_for_each_surface(struct roots_output *output,
47 struct roots_input *input, roots_surface_iterator_func_t iterator,
48 void *user_data);
49 void output_layer_for_each_surface(struct roots_output *output,
50 struct wl_list *layer_surfaces, roots_surface_iterator_func_t iterator,
51 void *user_data);
52 #if WLR_HAS_XWAYLAND
53 struct wlr_xwayland_surface;
54 void output_xwayland_children_for_each_surface(
55 struct roots_output *output, struct wlr_xwayland_surface *surface,
56 roots_surface_iterator_func_t iterator, void *user_data);
57 #endif
58 void output_for_each_surface(struct roots_output *output,
59 roots_surface_iterator_func_t iterator, void *user_data);
3360
3461 void handle_new_output(struct wl_listener *listener, void *data);
3562
4471 void output_damage_whole_drag_icon(struct roots_output *output,
4572 struct roots_drag_icon *icon);
4673 void output_damage_from_local_surface(struct roots_output *output,
47 struct wlr_surface *surface, double ox, double oy, float rotation);
74 struct wlr_surface *surface, double ox, double oy);
4875 void output_damage_whole_local_surface(struct roots_output *output,
49 struct wlr_surface *surface, double ox, double oy, float rotation);
76 struct wlr_surface *surface, double ox, double oy);
77
78 void output_render(struct roots_output *output);
79
80 void scale_box(struct wlr_box *box, float scale);
81 void get_decoration_box(struct roots_view *view,
82 struct roots_output *output, struct wlr_box *box);
5083
5184 #endif
1919 void (*maximize)(struct roots_view *view, bool maximized);
2020 void (*set_fullscreen)(struct roots_view *view, bool fullscreen);
2121 void (*close)(struct roots_view *view);
22 void (*for_each_surface)(struct roots_view *view,
23 wlr_surface_iterator_func_t iterator, void *user_data);
2224 void (*destroy)(struct roots_view *view);
2325 };
2426
221223 void view_init(struct roots_view *view, const struct roots_view_interface *impl,
222224 enum roots_view_type type, struct roots_desktop *desktop);
223225 void view_destroy(struct roots_view *view);
224 void view_activate(struct roots_view *view, bool activate);
225226 void view_apply_damage(struct roots_view *view);
226227 void view_damage_whole(struct roots_view *view);
227228 void view_update_position(struct roots_view *view, int x, int y);
250251 void view_set_app_id(struct roots_view *view, const char *app_id);
251252 void view_create_foreign_toplevel_handle(struct roots_view *view);
252253 void view_get_deco_box(const struct roots_view *view, struct wlr_box *box);
254 void view_for_each_surface(struct roots_view *view,
255 wlr_surface_iterator_func_t iterator, void *user_data);
253256
254257 struct roots_wl_shell_surface *roots_wl_shell_surface_from_view(
255258 struct roots_view *view);
7272 void *data;
7373 };
7474
75 struct wlr_cursor *wlr_cursor_create();
75 struct wlr_cursor *wlr_cursor_create(void);
7676
7777 void wlr_cursor_destroy(struct wlr_cursor *cur);
7878
4646 * physical space relative to one another, and perform various useful operations
4747 * on that state.
4848 */
49 struct wlr_output_layout *wlr_output_layout_create();
49 struct wlr_output_layout *wlr_output_layout_create(void);
5050
5151 void wlr_output_layout_destroy(struct wlr_output_layout *layout);
5252
6060 struct wlr_pointer_grab_interface {
6161 void (*enter)(struct wlr_seat_pointer_grab *grab,
6262 struct wlr_surface *surface, double sx, double sy);
63 void (*motion)(struct wlr_seat_pointer_grab *grab, uint32_t time,
63 void (*motion)(struct wlr_seat_pointer_grab *grab, uint32_t time_msec,
6464 double sx, double sy);
65 uint32_t (*button)(struct wlr_seat_pointer_grab *grab, uint32_t time,
66 uint32_t button, uint32_t state);
67 void (*axis)(struct wlr_seat_pointer_grab *grab, uint32_t time,
65 uint32_t (*button)(struct wlr_seat_pointer_grab *grab, uint32_t time_msec,
66 uint32_t button, enum wlr_button_state state);
67 void (*axis)(struct wlr_seat_pointer_grab *grab, uint32_t time_msec,
6868 enum wlr_axis_orientation orientation, double value,
6969 int32_t value_discrete, enum wlr_axis_source source);
7070 void (*frame)(struct wlr_seat_pointer_grab *grab);
7777 void (*enter)(struct wlr_seat_keyboard_grab *grab,
7878 struct wlr_surface *surface, uint32_t keycodes[],
7979 size_t num_keycodes, struct wlr_keyboard_modifiers *modifiers);
80 void (*key)(struct wlr_seat_keyboard_grab *grab, uint32_t time,
80 void (*key)(struct wlr_seat_keyboard_grab *grab, uint32_t time_msec,
8181 uint32_t key, uint32_t state);
8282 void (*modifiers)(struct wlr_seat_keyboard_grab *grab,
8383 struct wlr_keyboard_modifiers *modifiers);
8787 struct wlr_seat_touch_grab;
8888
8989 struct wlr_touch_grab_interface {
90 uint32_t (*down)(struct wlr_seat_touch_grab *grab, uint32_t time,
90 uint32_t (*down)(struct wlr_seat_touch_grab *grab, uint32_t time_msec,
9191 struct wlr_touch_point *point);
92 void (*up)(struct wlr_seat_touch_grab *grab, uint32_t time,
92 void (*up)(struct wlr_seat_touch_grab *grab, uint32_t time_msec,
9393 struct wlr_touch_point *point);
94 void (*motion)(struct wlr_seat_touch_grab *grab, uint32_t time,
94 void (*motion)(struct wlr_seat_touch_grab *grab, uint32_t time_msec,
9595 struct wlr_touch_point *point);
96 void (*enter)(struct wlr_seat_touch_grab *grab, uint32_t time,
96 void (*enter)(struct wlr_seat_touch_grab *grab, uint32_t time_msec,
9797 struct wlr_touch_point *point);
9898 // XXX this will conflict with the actual touch cancel which is different so
9999 // we need to rename this
334334 * `wlr_seat_pointer_notify_motion()` to send motion events to respect pointer
335335 * grabs.
336336 */
337 void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time,
337 void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time_msec,
338338 double sx, double sy);
339339
340340 /**
343343 * `wlr_seat_pointer_notify_button()` to send button events to respect pointer
344344 * grabs.
345345 */
346 uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
347 uint32_t button, uint32_t state);
346 uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat,
347 uint32_t time_msec, uint32_t button, enum wlr_button_state state);
348348
349349 /**
350350 * Send an axis event to the surface with pointer focus. Compositors should use
351351 * `wlr_seat_pointer_notify_axis()` to send axis events to respect pointer
352352 * grabs.
353353 **/
354 void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time,
354 void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time_msec,
355355 enum wlr_axis_orientation orientation, double value,
356356 int32_t value_discrete, enum wlr_axis_source source);
357357
387387 * Notify the seat of motion over the given surface. Pass surface-local
388388 * coordinates where the pointer motion occurred.
389389 */
390 void wlr_seat_pointer_notify_motion(struct wlr_seat *wlr_seat, uint32_t time,
391 double sx, double sy);
390 void wlr_seat_pointer_notify_motion(struct wlr_seat *wlr_seat,
391 uint32_t time_msec, double sx, double sy);
392392
393393 /**
394394 * Notify the seat that a button has been pressed. Returns the serial of the
395395 * button press or zero if no button press was sent.
396396 */
397397 uint32_t wlr_seat_pointer_notify_button(struct wlr_seat *wlr_seat,
398 uint32_t time, uint32_t button, uint32_t state);
398 uint32_t time_msec, uint32_t button, enum wlr_button_state state);
399399
400400 /**
401401 * Notify the seat of an axis event.
402402 */
403 void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time,
403 void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time_msec,
404404 enum wlr_axis_orientation orientation, double value,
405405 int32_t value_discrete, enum wlr_axis_source source);
406406
443443 * Send the keyboard key to focused keyboard resources. Compositors should use
444444 * `wlr_seat_notify_key()` to respect keyboard grabs.
445445 */
446 void wlr_seat_keyboard_send_key(struct wlr_seat *seat, uint32_t time,
446 void wlr_seat_keyboard_send_key(struct wlr_seat *seat, uint32_t time_msec,
447447 uint32_t key, uint32_t state);
448448
449449 /**
450450 * Notify the seat that a key has been pressed on the keyboard. Defers to any
451451 * keyboard grabs.
452452 */
453 void wlr_seat_keyboard_notify_key(struct wlr_seat *seat, uint32_t time,
453 void wlr_seat_keyboard_notify_key(struct wlr_seat *seat, uint32_t time_msec,
454454 uint32_t key, uint32_t state);
455455
456456 /**
522522 * the touch device.
523523 */
524524 uint32_t wlr_seat_touch_notify_down(struct wlr_seat *seat,
525 struct wlr_surface *surface, uint32_t time, int32_t touch_id, double sx,
526 double sy);
525 struct wlr_surface *surface, uint32_t time_msec,
526 int32_t touch_id, double sx, double sy);
527527
528528 /**
529529 * Notify the seat that the touch point given by `touch_id` is up. Defers to any
530530 * grab of the touch device.
531531 */
532 void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time,
532 void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time_msec,
533533 int32_t touch_id);
534534
535535 /**
538538 * even if the surface is not the owner of the touch point for processing by
539539 * grabs.
540540 */
541 void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time,
541 void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time_msec,
542542 int32_t touch_id, double sx, double sy);
543543
544544 /**
547547 * `wlr_seat_touch_point_clear_focus()`.
548548 */
549549 void wlr_seat_touch_point_focus(struct wlr_seat *seat,
550 struct wlr_surface *surface, uint32_t time, int32_t touch_id, double sx,
551 double sy);
550 struct wlr_surface *surface, uint32_t time_msec,
551 int32_t touch_id, double sx, double sy);
552552
553553 /**
554554 * Clear the focused surface for the touch point given by `touch_id`.
555555 */
556 void wlr_seat_touch_point_clear_focus(struct wlr_seat *seat, uint32_t time,
556 void wlr_seat_touch_point_clear_focus(struct wlr_seat *seat, uint32_t time_msec,
557557 int32_t touch_id);
558558
559559 /**
565565 * `wlr_seat_touch_notify_down()` to respect any grabs of the touch device.
566566 */
567567 uint32_t wlr_seat_touch_send_down(struct wlr_seat *seat,
568 struct wlr_surface *surface, uint32_t time, int32_t touch_id, double sx,
569 double sy);
568 struct wlr_surface *surface, uint32_t time_msec,
569 int32_t touch_id, double sx, double sy);
570570
571571 /**
572572 * Send a touch up event for the touch point given by the `touch_id`. The event
574574 * event. This will remove the touch point. Compositors should use
575575 * `wlr_seat_touch_notify_up()` to respect any grabs of the touch device.
576576 */
577 void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time,
577 void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time_msec,
578578 int32_t touch_id);
579579
580580 /**
583583 * down event. Compositors should use `wlr_seat_touch_notify_motion()` to
584584 * respect any grabs of the touch device.
585585 */
586 void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time,
586 void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time_msec,
587587 int32_t touch_id, double sx, double sy);
588588
589589 /**
242242 struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource(
243243 struct wl_resource *resource);
244244
245 struct wlr_box wlr_xdg_positioner_get_geometry(
246 struct wlr_xdg_positioner *positioner);
247
248245 /**
249246 * Send a ping to the surface. If the surface does not respond in a reasonable
250247 * amount of time, the ping_timeout event will be emitted.
2323 pid_t pid;
2424 struct wl_client *client;
2525 struct wl_event_source *sigusr1_source;
26 struct wl_listener client_destroy;
2726 struct wlr_xwm *xwm;
2827 struct wlr_xwayland_cursor *cursor;
2928 int wm_fd[2], wl_fd[2];
3332 /* Anything above display is reset on Xwayland restart, rest is conserved */
3433
3534 int display;
35 char display_name[16];
3636 int x_fd[2];
3737 struct wl_event_source *x_fd_read_event[2];
38 struct wl_listener display_destroy;
39
4038 bool lazy;
4139
4240 struct wl_display *wl_display;
4745 struct wl_signal ready;
4846 struct wl_signal new_surface;
4947 } events;
50
51 struct wl_listener seat_destroy;
5248
5349 /**
5450 * Add a custom event handler to xwayland. Return 1 if the event was
5652 * free the event.
5753 */
5854 int (*user_event_handler)(struct wlr_xwm *xwm, xcb_generic_event_t *event);
55
56 struct wl_listener client_destroy;
57 struct wl_listener display_destroy;
58 struct wl_listener seat_destroy;
5959
6060 void *data;
6161 };
00 project(
11 'wlroots',
22 'c',
3 version: '0.4.1',
3 version: '0.5.0',
44 license: 'MIT',
55 meson_version: '>=0.48.0',
66 default_options: [
1313 # Format of so_version is CURRENT, REVISION, AGE.
1414 # See: https://autotools.io/libtool/version.html
1515 # for a reference about clean library versioning.
16 so_version = ['1', '2', '0']
17
18 add_project_arguments(
19 [
20 '-DWLR_SRC_DIR="@0@"'.format(meson.current_source_dir()),
21 '-DWLR_USE_UNSTABLE',
22
23 '-Wno-unused-parameter',
24 '-Wundef',
25 ],
26 language: 'c',
27 )
16 so_version = ['2', '3', '1']
17
18 add_project_arguments([
19 '-DWLR_SRC_DIR="@0@"'.format(meson.current_source_dir()),
20 '-DWLR_USE_UNSTABLE',
21 ], language: 'c')
22
23 cc = meson.get_compiler('c')
24
25 add_project_arguments(cc.get_supported_arguments([
26 '-Wundef',
27 '-Wlogical-op',
28 '-Wmissing-include-dirs',
29 '-Wold-style-definition',
30 '-Wpointer-arith',
31 '-Winit-self',
32 '-Wstrict-prototypes',
33 '-Wredundant-decls',
34 '-Wimplicit-fallthrough=2',
35 '-Wendif-labels',
36 '-Wstrict-aliasing=2',
37 '-Woverflow',
38
39 '-Wno-missing-braces',
40 '-Wno-missing-field-initializers',
41 '-Wno-unused-parameter',
42 ]), language: 'c')
2843
2944 conf_data = configuration_data()
3045 conf_data.set10('WLR_HAS_LIBCAP', false)
3651 conf_data.set10('WLR_HAS_XCB_ICCCM', false)
3752
3853 wlr_inc = include_directories('.', 'include')
39
40 cc = meson.get_compiler('c')
4154
4255 # Clang complains about some zeroed initializer lists (= {0}), even though they
4356 # are valid
311311
312312 glGetError(); // Clear the error flag
313313
314 unsigned char *p = data + dst_y * stride;
314 unsigned char *p = (unsigned char *)data + dst_y * stride;
315315 uint32_t pack_stride = width * fmt->bpp / 8;
316316 if (pack_stride == stride && dst_x == 0 && flags != NULL) {
317317 // Under these particular conditions, we can read the pixels with only
5050
5151 double view_sx = lx - view->box.x;
5252 double view_sy = ly - view->box.y;
53
54 struct wlr_surface_state *state = &view->wlr_surface->current;
55 struct wlr_box box = {
56 .x = 0, .y = 0,
57 .width = state->width, .height = state->height,
58 };
59 if (view->rotation != 0.0) {
60 // Coordinates relative to the center of the view
61 double ox = view_sx - (double)box.width/2,
62 oy = view_sy - (double)box.height/2;
63 // Rotated coordinates
64 double rx = cos(view->rotation)*ox + sin(view->rotation)*oy,
65 ry = cos(view->rotation)*oy - sin(view->rotation)*ox;
66 view_sx = rx + (double)box.width/2;
67 view_sy = ry + (double)box.height/2;
68 }
53 rotate_child_position(&view_sx, &view_sy, 0, 0,
54 view->box.width, view->box.height, -view->rotation);
6955
7056 double _sx, _sy;
7157 struct wlr_surface *_surface = NULL;
395381 &desktop->xwayland_surface);
396382 desktop->xwayland_surface.notify = handle_xwayland_surface;
397383
384 setenv("DISPLAY", desktop->xwayland->display_name, true);
385
398386 if (wlr_xcursor_manager_load(desktop->xcursor_manager, 1)) {
399387 wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme");
400388 }
297297
298298 if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
299299 output_damage_whole_local_surface(output, layer_surface->surface,
300 old_geo.x, old_geo.y, 0);
300 old_geo.x, old_geo.y);
301301 output_damage_whole_local_surface(output, layer_surface->surface,
302 layer->geo.x, layer->geo.y, 0);
302 layer->geo.x, layer->geo.y);
303303 } else {
304304 output_damage_from_local_surface(output, layer_surface->surface,
305 layer->geo.x, layer->geo.y, 0);
305 layer->geo.x, layer->geo.y);
306306 }
307307 }
308308 }
313313 if (wlr_output != NULL) {
314314 struct roots_output *output = wlr_output->data;
315315 output_damage_whole_local_surface(output, layer_surface->surface,
316 layer->geo.x, layer->geo.y, 0);
316 layer->geo.x, layer->geo.y);
317317 }
318318 }
319319
341341 struct wlr_output *wlr_output = layer_surface->output;
342342 struct roots_output *output = wlr_output->data;
343343 output_damage_whole_local_surface(output, layer_surface->surface,
344 layer->geo.x, layer->geo.y, 0);
344 layer->geo.x, layer->geo.y);
345345 wlr_surface_send_enter(layer_surface->surface, wlr_output);
346346 }
347347
362362 int ox = popup->wlr_popup->geometry.x + layer->geo.x;
363363 int oy = popup->wlr_popup->geometry.y + layer->geo.y;
364364 output_damage_whole_local_surface(output, popup->wlr_popup->base->surface,
365 ox, oy, 0);
365 ox, oy);
366366 input_update_cursor_focus(output->desktop->server->input);
367367 }
368368
374374 int ox = popup->wlr_popup->geometry.x + layer->geo.x;
375375 int oy = popup->wlr_popup->geometry.y + layer->geo.y;
376376 output_damage_whole_local_surface(output, popup->wlr_popup->base->surface,
377 ox, oy, 0);
377 ox, oy);
378378 }
379379
380380 static void popup_handle_commit(struct wl_listener *listener, void *data) {
385385 int ox = popup->wlr_popup->geometry.x + layer->geo.x;
386386 int oy = popup->wlr_popup->geometry.y + layer->geo.y;
387387 output_damage_from_local_surface(output, popup->wlr_popup->base->surface,
388 ox, oy, 0);
388 ox, oy);
389389 }
390390
391391 static void popup_handle_destroy(struct wl_listener *listener, void *data) {
88 'layer_shell.c',
99 'main.c',
1010 'output.c',
11 'render.c',
1112 'seat.c',
1213 'switch.c',
1314 'text_input.c',
55 #include <wlr/backend/drm.h>
66 #include <wlr/config.h>
77 #include <wlr/types/wlr_compositor.h>
8 #include <wlr/types/wlr_matrix.h>
98 #include <wlr/types/wlr_output_layout.h>
109 #include <wlr/types/wlr_presentation_time.h>
1110 #include <wlr/types/wlr_wl_shell.h>
1312 #include <wlr/types/wlr_xdg_shell.h>
1413 #include <wlr/util/log.h>
1514 #include <wlr/util/region.h>
15 #include <wlr/xwayland.h>
1616 #include "rootston/config.h"
1717 #include "rootston/layers.h"
1818 #include "rootston/output.h"
2424 */
2525 void rotate_child_position(double *sx, double *sy, double sw, double sh,
2626 double pw, double ph, float rotation) {
27 if (rotation != 0.0) {
28 // Coordinates relative to the center of the subsurface
29 double ox = *sx - pw/2 + sw/2,
30 oy = *sy - ph/2 + sh/2;
31 // Rotated coordinates
32 double rx = cos(rotation)*ox - sin(rotation)*oy,
33 ry = cos(rotation)*oy + sin(rotation)*ox;
34 *sx = rx + pw/2 - sw/2;
35 *sy = ry + ph/2 - sh/2;
36 }
37 }
38
39 struct layout_data {
40 double x, y;
27 if (rotation == 0.0) {
28 return;
29 }
30
31 // Coordinates relative to the center of the subsurface
32 double cx = *sx - pw/2 + sw/2,
33 cy = *sy - ph/2 + sh/2;
34 // Rotated coordinates
35 double rx = cos(rotation)*cx - sin(rotation)*cy,
36 ry = cos(rotation)*cy + sin(rotation)*cx;
37 *sx = rx + pw/2 - sw/2;
38 *sy = ry + ph/2 - sh/2;
39 }
40
41 struct surface_iterator_data {
42 roots_surface_iterator_func_t user_iterator;
43 void *user_data;
44
45 struct roots_output *output;
46 double ox, oy;
4147 int width, height;
4248 float rotation;
4349 };
4450
45 static void get_layout_position(struct layout_data *data,
46 double *lx, double *ly, const struct wlr_surface *surface,
47 int sx, int sy) {
48 double _sx = sx, _sy = sy;
49 rotate_child_position(&_sx, &_sy, surface->current.width,
50 surface->current.height, data->width, data->height, data->rotation);
51 *lx = data->x + _sx;
52 *ly = data->y + _sy;
53 }
54
55 static void surface_for_each_surface(struct wlr_surface *surface,
56 double lx, double ly, float rotation, struct layout_data *layout_data,
57 wlr_surface_iterator_func_t iterator, void *user_data) {
58 layout_data->x = lx;
59 layout_data->y = ly;
60 layout_data->width = surface->current.width;
61 layout_data->height = surface->current.height;
62 layout_data->rotation = rotation;
63
64 wlr_surface_for_each_surface(surface, iterator, user_data);
65 }
66
67 static void view_for_each_surface(struct roots_view *view,
68 struct layout_data *layout_data, wlr_surface_iterator_func_t iterator,
51 static bool get_surface_box(struct surface_iterator_data *data,
52 struct wlr_surface *surface, int sx, int sy,
53 struct wlr_box *surface_box) {
54 struct roots_output *output = data->output;
55
56 if (!wlr_surface_has_buffer(surface)) {
57 return false;
58 }
59
60 int sw = surface->current.width;
61 int sh = surface->current.height;
62
63 double _sx = sx + surface->sx;
64 double _sy = sy + surface->sy;
65 rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
66 data->rotation);
67
68 struct wlr_box box = {
69 .x = data->ox + _sx,
70 .y = data->oy + _sy,
71 .width = sw,
72 .height = sh,
73 };
74 if (surface_box != NULL) {
75 *surface_box = box;
76 }
77
78 struct wlr_box rotated_box;
79 wlr_box_rotated_bounds(&rotated_box, &box, data->rotation);
80
81 struct wlr_box output_box = {0};
82 wlr_output_effective_resolution(output->wlr_output,
83 &output_box.width, &output_box.height);
84
85 struct wlr_box intersection;
86 return wlr_box_intersection(&intersection, &output_box, &rotated_box);
87 }
88
89 static void output_for_each_surface_iterator(struct wlr_surface *surface,
90 int sx, int sy, void *_data) {
91 struct surface_iterator_data *data = _data;
92
93 struct wlr_box box;
94 bool intersects = get_surface_box(data, surface, sx, sy, &box);
95 if (!intersects) {
96 return;
97 }
98
99 data->user_iterator(data->output, surface, &box, data->rotation,
100 data->user_data);
101 }
102
103 void output_surface_for_each_surface(struct roots_output *output,
104 struct wlr_surface *surface, double ox, double oy,
105 roots_surface_iterator_func_t iterator, void *user_data) {
106 struct surface_iterator_data data = {
107 .user_iterator = iterator,
108 .user_data = user_data,
109 .output = output,
110 .ox = ox,
111 .oy = oy,
112 .width = surface->current.width,
113 .height = surface->current.height,
114 .rotation = 0,
115 };
116
117 wlr_surface_for_each_surface(surface,
118 output_for_each_surface_iterator, &data);
119 }
120
121 void output_view_for_each_surface(struct roots_output *output,
122 struct roots_view *view, roots_surface_iterator_func_t iterator,
69123 void *user_data) {
70 if (!view->wlr_surface) {
71 return;
72 }
73
74 layout_data->x = view->box.x;
75 layout_data->y = view->box.y;
76 layout_data->width = view->wlr_surface->current.width;
77 layout_data->height = view->wlr_surface->current.height;
78 layout_data->rotation = view->rotation;
79
80 switch (view->type) {
81 case ROOTS_XDG_SHELL_V6_VIEW:;
82 struct roots_xdg_surface_v6 *xdg_surface_v6 =
83 roots_xdg_surface_v6_from_view(view);
84 wlr_xdg_surface_v6_for_each_surface(xdg_surface_v6->xdg_surface_v6,
85 iterator, user_data);
86 break;
87 case ROOTS_XDG_SHELL_VIEW:;
88 struct roots_xdg_surface *xdg_surface =
89 roots_xdg_surface_from_view(view);
90 wlr_xdg_surface_for_each_surface(xdg_surface->xdg_surface, iterator,
91 user_data);
92 break;
93 case ROOTS_WL_SHELL_VIEW:;
94 struct roots_wl_shell_surface *wl_shell_surface =
95 roots_wl_shell_surface_from_view(view);
96 wlr_wl_shell_surface_for_each_surface(wl_shell_surface->wl_shell_surface,
97 iterator, user_data);
98 break;
124 struct surface_iterator_data data = {
125 .user_iterator = iterator,
126 .user_data = user_data,
127 .output = output,
128 .ox = view->box.x - output->wlr_output->lx,
129 .oy = view->box.y - output->wlr_output->ly,
130 .width = view->box.width,
131 .height = view->box.height,
132 .rotation = view->rotation,
133 };
134
135 view_for_each_surface(view, output_for_each_surface_iterator, &data);
136 }
137
99138 #if WLR_HAS_XWAYLAND
100 case ROOTS_XWAYLAND_VIEW:
101 wlr_surface_for_each_surface(view->wlr_surface, iterator, user_data);
102 break;
103 #endif
104 }
105 }
106
107 #if WLR_HAS_XWAYLAND
108 static void xwayland_children_for_each_surface(
109 struct wlr_xwayland_surface *surface,
110 wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
111 void *user_data) {
139 void output_xwayland_children_for_each_surface(
140 struct roots_output *output, struct wlr_xwayland_surface *surface,
141 roots_surface_iterator_func_t iterator, void *user_data) {
112142 struct wlr_xwayland_surface *child;
113143 wl_list_for_each(child, &surface->children, parent_link) {
114144 if (child->mapped) {
115 surface_for_each_surface(child->surface, child->x, child->y, 0,
116 layout_data, iterator, user_data);
117 }
118 xwayland_children_for_each_surface(child, iterator, layout_data,
145 double ox = child->x - output->wlr_output->lx;
146 double oy = child->y - output->wlr_output->ly;
147 output_surface_for_each_surface(output, child->surface,
148 ox, oy, iterator, user_data);
149 }
150 output_xwayland_children_for_each_surface(output, child,
151 iterator, user_data);
152 }
153 }
154 #endif
155
156 void output_layer_for_each_surface(struct roots_output *output,
157 struct wl_list *layer_surfaces, roots_surface_iterator_func_t iterator,
158 void *user_data) {
159 struct roots_layer_surface *layer_surface;
160 wl_list_for_each(layer_surface, layer_surfaces, link) {
161 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
162 layer_surface->layer_surface;
163 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
164 layer_surface->geo.x, layer_surface->geo.y, iterator,
119165 user_data);
120166 }
121167 }
122 #endif
123
124 static void drag_icons_for_each_surface(struct roots_input *input,
125 wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
168
169 void output_drag_icons_for_each_surface(struct roots_output *output,
170 struct roots_input *input, roots_surface_iterator_func_t iterator,
126171 void *user_data) {
127172 struct roots_seat *seat;
128173 wl_list_for_each(seat, &input->seats, link) {
129174 struct roots_drag_icon *drag_icon = seat->drag_icon;
130 if (drag_icon == NULL || !drag_icon->wlr_drag_icon->mapped) {
175 if (!drag_icon || !drag_icon->wlr_drag_icon->mapped) {
131176 continue;
132177 }
133178
134 surface_for_each_surface(drag_icon->wlr_drag_icon->surface,
135 drag_icon->x, drag_icon->y, 0, layout_data,
136 iterator, user_data);
137 }
138 }
139
140 static void layer_for_each_surface(struct wl_list *layer,
141 const struct wlr_box *output_layout_box,
142 wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
143 void *user_data) {
144 struct roots_layer_surface *roots_surface;
145 wl_list_for_each(roots_surface, layer, link) {
146 struct wlr_layer_surface_v1 *layer = roots_surface->layer_surface;
147
148 layout_data->x = roots_surface->geo.x + output_layout_box->x;
149 layout_data->y = roots_surface->geo.y + output_layout_box->y;
150 layout_data->width = roots_surface->geo.width;
151 layout_data->height = roots_surface->geo.height;
152 layout_data->rotation = 0;
153 wlr_layer_surface_v1_for_each_surface(layer, iterator, user_data);
154 }
155 }
156
157 static void output_for_each_surface(struct roots_output *output,
158 wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
159 void *user_data) {
160 struct wlr_output *wlr_output = output->wlr_output;
179 double ox = drag_icon->x - output->wlr_output->lx;
180 double oy = drag_icon->y - output->wlr_output->ly;
181 output_surface_for_each_surface(output,
182 drag_icon->wlr_drag_icon->surface, ox, oy, iterator, user_data);
183 }
184 }
185
186 void output_for_each_surface(struct roots_output *output,
187 roots_surface_iterator_func_t iterator, void *user_data) {
161188 struct roots_desktop *desktop = output->desktop;
162 struct roots_server *server = desktop->server;
163
164 const struct wlr_box *output_box =
165 wlr_output_layout_get_box(desktop->layout, wlr_output);
166189
167190 if (output->fullscreen_view != NULL) {
168191 struct roots_view *view = output->fullscreen_view;
169192
170 view_for_each_surface(view, layout_data, iterator, user_data);
193 output_view_for_each_surface(output, view, iterator, user_data);
171194
172195 #if WLR_HAS_XWAYLAND
173196 if (view->type == ROOTS_XWAYLAND_VIEW) {
174197 struct roots_xwayland_surface *xwayland_surface =
175198 roots_xwayland_surface_from_view(view);
176 xwayland_children_for_each_surface(
177 xwayland_surface->xwayland_surface,
178 iterator, layout_data, user_data);
199 output_xwayland_children_for_each_surface(output,
200 xwayland_surface->xwayland_surface, iterator, user_data);
179201 }
180202 #endif
181203 } else {
182204 struct roots_view *view;
183205 wl_list_for_each_reverse(view, &desktop->views, link) {
184 view_for_each_surface(view, layout_data, iterator, user_data);
185 }
186
187 drag_icons_for_each_surface(server->input, iterator,
188 layout_data, user_data);
189 }
206 output_view_for_each_surface(output, view, iterator, user_data);
207 }
208 }
209
210 output_drag_icons_for_each_surface(output, desktop->server->input,
211 iterator, user_data);
190212
191213 size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
192214 for (size_t i = 0; i < len; ++i) {
193 layer_for_each_surface(&output->layers[i], output_box,
194 iterator, layout_data, user_data);
195 }
196 }
197
198
199 struct render_data {
200 struct layout_data layout;
201 struct roots_output *output;
202 struct timespec *when;
203 pixman_region32_t *damage;
204 float alpha;
205 };
206
207 /**
208 * Checks whether a surface at (lx, ly) intersects an output. If `box` is not
209 * NULL, it populates it with the surface box in the output, in output-local
210 * coordinates.
211 */
212 static bool surface_intersect_output(struct wlr_surface *surface,
213 struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
214 double lx, double ly, float rotation, struct wlr_box *box) {
215 double ox = lx, oy = ly;
216 wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
217
218 ox += surface->sx;
219 oy += surface->sy;
220
221 if (box != NULL) {
222 box->x = ox * wlr_output->scale;
223 box->y = oy * wlr_output->scale;
224 box->width = surface->current.width * wlr_output->scale;
225 box->height = surface->current.height * wlr_output->scale;
226 }
227
228 struct wlr_box layout_box = {
229 .x = lx, .y = ly,
230 .width = surface->current.width, .height = surface->current.height,
231 };
232 wlr_box_rotated_bounds(&layout_box, &layout_box, rotation);
233 return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
234 }
235
236 static void scissor_output(struct roots_output *output, pixman_box32_t *rect) {
237 struct wlr_output *wlr_output = output->wlr_output;
238 struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend);
239 assert(renderer);
240
241 struct wlr_box box = {
242 .x = rect->x1,
243 .y = rect->y1,
244 .width = rect->x2 - rect->x1,
245 .height = rect->y2 - rect->y1,
246 };
247
248 int ow, oh;
249 wlr_output_transformed_resolution(wlr_output, &ow, &oh);
250
251 enum wl_output_transform transform =
252 wlr_output_transform_invert(wlr_output->transform);
253 wlr_box_transform(&box, &box, transform, ow, oh);
254
255 wlr_renderer_scissor(renderer, &box);
256 }
257
258 static void render_surface(struct wlr_surface *surface, int sx, int sy,
259 void *_data) {
260 struct render_data *data = _data;
261 struct roots_output *output = data->output;
262 float rotation = data->layout.rotation;
263
264 struct wlr_texture *texture = wlr_surface_get_texture(surface);
265 if (texture == NULL) {
266 return;
267 }
268
269 struct wlr_renderer *renderer =
270 wlr_backend_get_renderer(output->wlr_output->backend);
271 assert(renderer);
272
273 double lx, ly;
274 get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
275
276 struct wlr_box box;
277 bool intersects = surface_intersect_output(surface, output->desktop->layout,
278 output->wlr_output, lx, ly, rotation, &box);
279 if (!intersects) {
280 return;
281 }
282
283 struct wlr_box rotated;
284 wlr_box_rotated_bounds(&rotated, &box, rotation);
285
286 pixman_region32_t damage;
287 pixman_region32_init(&damage);
288 pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
289 rotated.width, rotated.height);
290 pixman_region32_intersect(&damage, &damage, data->damage);
291 bool damaged = pixman_region32_not_empty(&damage);
292 if (!damaged) {
293 goto damage_finish;
294 }
295
296 float matrix[9];
297 enum wl_output_transform transform =
298 wlr_output_transform_invert(surface->current.transform);
299 wlr_matrix_project_box(matrix, &box, transform, rotation,
300 output->wlr_output->transform_matrix);
301
302 int nrects;
303 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
304 for (int i = 0; i < nrects; ++i) {
305 scissor_output(output, &rects[i]);
306 wlr_render_texture_with_matrix(renderer, texture, matrix, data->alpha);
307 }
308
309 damage_finish:
310 pixman_region32_fini(&damage);
311 }
312
313 static void get_decoration_box(struct roots_view *view,
215 output_layer_for_each_surface(output, &output->layers[i],
216 iterator, user_data);
217 }
218 }
219
220 static int scale_length(int length, int offset, float scale) {
221 return round((offset + length) * scale) - round(offset * scale);
222 }
223
224 void scale_box(struct wlr_box *box, float scale) {
225 box->width = scale_length(box->width, box->x, scale);
226 box->height = scale_length(box->height, box->y, scale);
227 box->x = round(box->x * scale);
228 box->y = round(box->y * scale);
229 }
230
231 void get_decoration_box(struct roots_view *view,
314232 struct roots_output *output, struct wlr_box *box) {
315233 struct wlr_output *wlr_output = output->wlr_output;
316234
330248 box->y = y * wlr_output->scale;
331249 box->width = deco_box.width * wlr_output->scale;
332250 box->height = deco_box.height * wlr_output->scale;
333 }
334
335 static void render_decorations(struct roots_view *view,
336 struct render_data *data) {
337 if (!view->decorated || view->wlr_surface == NULL) {
338 return;
339 }
340
341 struct roots_output *output = data->output;
342 struct wlr_renderer *renderer =
343 wlr_backend_get_renderer(output->wlr_output->backend);
344 assert(renderer);
345
346 struct wlr_box box;
347 get_decoration_box(view, output, &box);
348
349 struct wlr_box rotated;
350 wlr_box_rotated_bounds(&rotated, &box, view->rotation);
351
352 pixman_region32_t damage;
353 pixman_region32_init(&damage);
354 pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
355 rotated.width, rotated.height);
356 pixman_region32_intersect(&damage, &damage, data->damage);
357 bool damaged = pixman_region32_not_empty(&damage);
358 if (!damaged) {
359 goto damage_finish;
360 }
361
362 float matrix[9];
363 wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,
364 view->rotation, output->wlr_output->transform_matrix);
365 float color[] = { 0.2, 0.2, 0.2, view->alpha };
366
367 int nrects;
368 pixman_box32_t *rects =
369 pixman_region32_rectangles(&damage, &nrects);
370 for (int i = 0; i < nrects; ++i) {
371 scissor_output(output, &rects[i]);
372 wlr_render_quad_with_matrix(renderer, color, matrix);
373 }
374
375 damage_finish:
376 pixman_region32_fini(&damage);
377 }
378
379 static void render_view(struct roots_view *view, struct render_data *data) {
380 // Do not render views fullscreened on other outputs
381 if (view->fullscreen_output != NULL &&
382 view->fullscreen_output != data->output) {
383 return;
384 }
385
386 data->alpha = view->alpha;
387 render_decorations(view, data);
388 view_for_each_surface(view, &data->layout, render_surface, data);
389 }
390
391 static void render_layer(struct roots_output *output,
392 const struct wlr_box *output_layout_box, struct render_data *data,
393 struct wl_list *layer) {
394 data->alpha = 1;
395 layer_for_each_surface(layer, output_layout_box, render_surface,
396 &data->layout, data);
397 }
398
399 static void surface_send_frame_done(struct wlr_surface *surface, int sx, int sy,
400 void *_data) {
401 struct render_data *data = _data;
402 struct roots_output *output = data->output;
403 struct timespec *when = data->when;
404 float rotation = data->layout.rotation;
405
406 double lx, ly;
407 get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
408
409 if (!surface_intersect_output(surface, output->desktop->layout,
410 output->wlr_output, lx, ly, rotation, NULL)) {
411 return;
412 }
413
414 wlr_surface_send_frame_done(surface, when);
415 }
416
417 static void render_output(struct roots_output *output) {
418 struct wlr_output *wlr_output = output->wlr_output;
419 struct roots_desktop *desktop = output->desktop;
420 struct roots_server *server = desktop->server;
421 struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend);
422 assert(renderer);
423
424 if (!wlr_output->enabled) {
425 return;
426 }
427
428 struct timespec now;
429 clock_gettime(CLOCK_MONOTONIC, &now);
430
431 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
432
433 const struct wlr_box *output_box =
434 wlr_output_layout_get_box(desktop->layout, wlr_output);
435
436 // Check if we can delegate the fullscreen surface to the output
437 if (output->fullscreen_view != NULL &&
438 output->fullscreen_view->wlr_surface != NULL) {
439 struct roots_view *view = output->fullscreen_view;
440
441 // Make sure the view is centered on screen
442 struct wlr_box view_box;
443 view_get_box(view, &view_box);
444 double view_x = (double)(output_box->width - view_box.width) / 2 +
445 output_box->x;
446 double view_y = (double)(output_box->height - view_box.height) / 2 +
447 output_box->y;
448 view_move(view, view_x, view_y);
449
450 // Fullscreen views are rendered on a black background
451 clear_color[0] = clear_color[1] = clear_color[2] = 0;
452 }
453
454 bool needs_swap;
455 pixman_region32_t damage;
456 pixman_region32_init(&damage);
457 if (!wlr_output_damage_make_current(output->damage, &needs_swap, &damage)) {
458 return;
459 }
460
461 struct render_data data = {
462 .output = output,
463 .when = &now,
464 .damage = &damage,
465 .alpha = 1.0,
466 };
467
468 if (!needs_swap) {
469 // Output doesn't need swap and isn't damaged, skip rendering completely
470 goto damage_finish;
471 }
472
473 wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
474
475 if (!pixman_region32_not_empty(&damage)) {
476 // Output isn't damaged but needs buffer swap
477 goto renderer_end;
478 }
479
480 if (server->config->debug_damage_tracking) {
481 wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
482 }
483
484 int nrects;
485 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
486 for (int i = 0; i < nrects; ++i) {
487 scissor_output(output, &rects[i]);
488 wlr_renderer_clear(renderer, clear_color);
489 }
490
491 render_layer(output, output_box, &data,
492 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
493 render_layer(output, output_box, &data,
494 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
495
496 // If a view is fullscreen on this output, render it
497 if (output->fullscreen_view != NULL) {
498 struct roots_view *view = output->fullscreen_view;
499
500 if (view->wlr_surface != NULL) {
501 view_for_each_surface(view, &data.layout, render_surface, &data);
502 }
503
504 // During normal rendering the xwayland window tree isn't traversed
505 // because all windows are rendered. Here we only want to render
506 // the fullscreen window's children so we have to traverse the tree.
507 #if WLR_HAS_XWAYLAND
508 if (view->type == ROOTS_XWAYLAND_VIEW) {
509 struct roots_xwayland_surface *xwayland_surface =
510 roots_xwayland_surface_from_view(view);
511 xwayland_children_for_each_surface(
512 xwayland_surface->xwayland_surface,
513 render_surface, &data.layout, &data);
514 }
515 #endif
516 } else {
517 // Render all views
518 struct roots_view *view;
519 wl_list_for_each_reverse(view, &desktop->views, link) {
520 render_view(view, &data);
521 }
522 // Render top layer above shell views
523 render_layer(output, output_box, &data,
524 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
525 }
526
527 // Render drag icons
528 data.alpha = 1.0;
529 drag_icons_for_each_surface(server->input, render_surface, &data.layout,
530 &data);
531
532 render_layer(output, output_box, &data,
533 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
534
535 renderer_end:
536 wlr_output_render_software_cursors(wlr_output, &damage);
537 wlr_renderer_scissor(renderer, NULL);
538 wlr_renderer_end(renderer);
539
540 int width, height;
541 wlr_output_transformed_resolution(wlr_output, &width, &height);
542
543 if (server->config->debug_damage_tracking) {
544 pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
545 }
546
547 enum wl_output_transform transform =
548 wlr_output_transform_invert(wlr_output->transform);
549 wlr_region_transform(&damage, &damage, transform, width, height);
550
551 if (!wlr_output_damage_swap_buffers(output->damage, &now, &damage)) {
552 goto damage_finish;
553 }
554 output->last_frame = desktop->last_frame = now;
555
556 damage_finish:
557 pixman_region32_fini(&damage);
558
559 // Send frame done events to all surfaces
560 output_for_each_surface(output, surface_send_frame_done,
561 &data.layout, &data);
562251 }
563252
564253 void output_damage_whole(struct roots_output *output) {
595284 return false;
596285 }
597286
598 struct damage_data {
599 struct layout_data layout;
600 struct roots_output *output;
601 };
602
603 static void damage_whole_surface(struct wlr_surface *surface, int sx, int sy,
604 void *_data) {
605 struct damage_data *data = _data;
606 struct roots_output *output = data->output;
607 float rotation = data->layout.rotation;
608
609 double lx, ly;
610 get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
611
612 if (!wlr_surface_has_buffer(surface)) {
613 return;
614 }
615
616 int ow, oh;
617 wlr_output_transformed_resolution(output->wlr_output, &ow, &oh);
618
619 struct wlr_box box;
620 bool intersects = surface_intersect_output(surface, output->desktop->layout,
621 output->wlr_output, lx, ly, rotation, &box);
622 if (!intersects) {
623 return;
624 }
625
626 wlr_box_rotated_bounds(&box, &box, rotation);
627
628 wlr_output_damage_add_box(output->damage, &box);
287 static void damage_surface_iterator(struct roots_output *output,
288 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
289 void *data) {
290 bool *whole = data;
291
292 struct wlr_box box = *_box;
293 scale_box(&box, output->wlr_output->scale);
294
295 int center_x = box.x + box.width/2;
296 int center_y = box.y + box.height/2;
297
298 if (pixman_region32_not_empty(&surface->buffer_damage)) {
299 pixman_region32_t damage;
300 pixman_region32_init(&damage);
301 wlr_surface_get_effective_damage(surface, &damage);
302 wlr_region_scale(&damage, &damage, output->wlr_output->scale);
303 if (ceil(output->wlr_output->scale) > surface->current.scale) {
304 // When scaling up a surface, it'll become blurry so we need to
305 // expand the damage region
306 wlr_region_expand(&damage, &damage,
307 ceil(output->wlr_output->scale) - surface->current.scale);
308 }
309 pixman_region32_translate(&damage, box.x, box.y);
310 wlr_region_rotated_bounds(&damage, &damage, rotation,
311 center_x, center_y);
312 wlr_output_damage_add(output->damage, &damage);
313 pixman_region32_fini(&damage);
314 }
315
316 if (*whole) {
317 wlr_box_rotated_bounds(&box, &box, rotation);
318 wlr_output_damage_add_box(output->damage, &box);
319 }
320
321 wlr_output_schedule_frame(output->wlr_output);
629322 }
630323
631324 void output_damage_whole_local_surface(struct roots_output *output,
632 struct wlr_surface *surface, double ox, double oy, float rotation) {
633 struct wlr_output_layout_output *layout = wlr_output_layout_get(
634 output->desktop->layout, output->wlr_output);
635 struct damage_data data = { .output = output };
636 surface_for_each_surface(surface, ox + layout->x, oy + layout->y, 0,
637 &data.layout, damage_whole_surface, &data);
325 struct wlr_surface *surface, double ox, double oy) {
326 bool whole = true;
327 output_surface_for_each_surface(output, surface, ox, oy,
328 damage_surface_iterator, &whole);
638329 }
639330
640331 static void damage_whole_decoration(struct roots_view *view,
659350
660351 damage_whole_decoration(view, output);
661352
662 struct damage_data data = { .output = output };
663 view_for_each_surface(view, &data.layout, damage_whole_surface, &data);
353 bool whole = true;
354 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
664355 }
665356
666357 void output_damage_whole_drag_icon(struct roots_output *output,
667358 struct roots_drag_icon *icon) {
668 struct damage_data data = { .output = output };
669 surface_for_each_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, 0,
670 &data.layout, damage_whole_surface, &data);
671 }
672
673 static void damage_from_surface(struct wlr_surface *surface, int sx, int sy,
674 void *_data) {
675 struct damage_data *data = _data;
676 struct roots_output *output = data->output;
677 struct wlr_output *wlr_output = output->wlr_output;
678 float rotation = data->layout.rotation;
679
680 double lx, ly;
681 get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
682
683 if (!wlr_surface_has_buffer(surface)) {
684 return;
685 }
686
687 int ow, oh;
688 wlr_output_transformed_resolution(wlr_output, &ow, &oh);
689
690 struct wlr_box box;
691 surface_intersect_output(surface, output->desktop->layout,
692 wlr_output, lx, ly, rotation, &box);
693
694 int center_x = box.x + box.width/2;
695 int center_y = box.y + box.height/2;
696
697 pixman_region32_t damage;
698 pixman_region32_init(&damage);
699 wlr_surface_get_effective_damage(surface, &damage);
700
701 wlr_region_scale(&damage, &damage, wlr_output->scale);
702 if (ceil(wlr_output->scale) > surface->current.scale) {
703 // When scaling up a surface, it'll become blurry so we need to
704 // expand the damage region
705 wlr_region_expand(&damage, &damage,
706 ceil(wlr_output->scale) - surface->current.scale);
707 }
708 pixman_region32_translate(&damage, box.x, box.y);
709 wlr_region_rotated_bounds(&damage, &damage, rotation, center_x, center_y);
710 wlr_output_damage_add(output->damage, &damage);
711 pixman_region32_fini(&damage);
359 bool whole = true;
360 output_surface_for_each_surface(output, icon->wlr_drag_icon->surface,
361 icon->x, icon->y, damage_surface_iterator, &whole);
712362 }
713363
714364 void output_damage_from_local_surface(struct roots_output *output,
715 struct wlr_surface *surface, double ox, double oy, float rotation) {
716 struct wlr_output_layout_output *layout = wlr_output_layout_get(
717 output->desktop->layout, output->wlr_output);
718 struct damage_data data = { .output = output };
719 surface_for_each_surface(surface, ox + layout->x, oy + layout->y, 0,
720 &data.layout, damage_from_surface, &data);
365 struct wlr_surface *surface, double ox, double oy) {
366 bool whole = false;
367 output_surface_for_each_surface(output, surface, ox, oy,
368 damage_surface_iterator, &whole);
721369 }
722370
723371 void output_damage_from_view(struct roots_output *output,
726374 return;
727375 }
728376
729 struct damage_data data = { .output = output };
730 view_for_each_surface(view, &data.layout, damage_from_surface, &data);
377 bool whole = false;
378 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
731379 }
732380
733381 static void set_mode(struct wlr_output *output,
782430 void *data) {
783431 struct roots_output *output =
784432 wl_container_of(listener, output, damage_frame);
785 render_output(output);
433 output_render(output);
786434 }
787435
788436 static void output_damage_handle_destroy(struct wl_listener *listener,
804452 arrange_layers(output);
805453 }
806454
807 struct presentation_data {
808 struct layout_data layout;
809 struct roots_output *output;
810 struct wlr_presentation_event *event;
811 };
812
813 static void surface_send_presented(struct wlr_surface *surface, int sx, int sy,
814 void *_data) {
815 struct presentation_data *data = _data;
816 struct roots_output *output = data->output;
817 float rotation = data->layout.rotation;
818
819 double lx, ly;
820 get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
821
822 if (!surface_intersect_output(surface, output->desktop->layout,
823 output->wlr_output, lx, ly, rotation, NULL)) {
824 return;
825 }
826
455 static void surface_send_presented_iterator(struct roots_output *output,
456 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
457 void *data) {
458 struct wlr_presentation_event *event = data;
827459 wlr_presentation_send_surface_presented(output->desktop->presentation,
828 surface, data->event);
460 surface, event);
829461 }
830462
831463 static void output_handle_present(struct wl_listener *listener, void *data) {
842474 .flags = output_event->flags,
843475 };
844476
845 struct presentation_data presentation_data = {
846 .output = output,
847 .event = &event,
848 };
849 output_for_each_surface(output, surface_send_presented,
850 &presentation_data.layout, &presentation_data);
477 output_for_each_surface(output,
478 surface_send_presented_iterator, &event);
851479 }
852480
853481 void handle_new_output(struct wl_listener *listener, void *data) {
0 #define _POSIX_C_SOURCE 200809L
1 #include <assert.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <time.h>
5 #include <wlr/config.h>
6 #include <wlr/types/wlr_compositor.h>
7 #include <wlr/types/wlr_matrix.h>
8 #include <wlr/util/log.h>
9 #include <wlr/util/region.h>
10 #include "rootston/layers.h"
11 #include "rootston/output.h"
12 #include "rootston/server.h"
13
14 struct render_data {
15 pixman_region32_t *damage;
16 float alpha;
17 };
18
19 static void scissor_output(struct wlr_output *wlr_output,
20 pixman_box32_t *rect) {
21 struct wlr_renderer *renderer =
22 wlr_backend_get_renderer(wlr_output->backend);
23 assert(renderer);
24
25 struct wlr_box box = {
26 .x = rect->x1,
27 .y = rect->y1,
28 .width = rect->x2 - rect->x1,
29 .height = rect->y2 - rect->y1,
30 };
31
32 int ow, oh;
33 wlr_output_transformed_resolution(wlr_output, &ow, &oh);
34
35 enum wl_output_transform transform =
36 wlr_output_transform_invert(wlr_output->transform);
37 wlr_box_transform(&box, &box, transform, ow, oh);
38
39 wlr_renderer_scissor(renderer, &box);
40 }
41
42 static void render_texture(struct wlr_output *wlr_output,
43 pixman_region32_t *output_damage, struct wlr_texture *texture,
44 const struct wlr_box *box, const float matrix[static 9],
45 float rotation, float alpha) {
46 struct wlr_renderer *renderer =
47 wlr_backend_get_renderer(wlr_output->backend);
48 assert(renderer);
49
50 struct wlr_box rotated;
51 wlr_box_rotated_bounds(&rotated, box, rotation);
52
53 pixman_region32_t damage;
54 pixman_region32_init(&damage);
55 pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
56 rotated.width, rotated.height);
57 pixman_region32_intersect(&damage, &damage, output_damage);
58 bool damaged = pixman_region32_not_empty(&damage);
59 if (!damaged) {
60 goto damage_finish;
61 }
62
63 int nrects;
64 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
65 for (int i = 0; i < nrects; ++i) {
66 scissor_output(wlr_output, &rects[i]);
67 wlr_render_texture_with_matrix(renderer, texture, matrix, alpha);
68 }
69
70 damage_finish:
71 pixman_region32_fini(&damage);
72 }
73
74 static void render_surface_iterator(struct roots_output *output,
75 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
76 void *_data) {
77 struct render_data *data = _data;
78 struct wlr_output *wlr_output = output->wlr_output;
79 pixman_region32_t *output_damage = data->damage;
80 float alpha = data->alpha;
81
82 struct wlr_texture *texture = wlr_surface_get_texture(surface);
83 if (!texture) {
84 return;
85 }
86
87 struct wlr_box box = *_box;
88 scale_box(&box, wlr_output->scale);
89
90 float matrix[9];
91 enum wl_output_transform transform =
92 wlr_output_transform_invert(surface->current.transform);
93 wlr_matrix_project_box(matrix, &box, transform, rotation,
94 wlr_output->transform_matrix);
95
96 render_texture(wlr_output, output_damage,
97 texture, &box, matrix, rotation, alpha);
98 }
99
100 static void render_decorations(struct roots_output *output,
101 struct roots_view *view, struct render_data *data) {
102 if (!view->decorated || view->wlr_surface == NULL) {
103 return;
104 }
105
106 struct wlr_renderer *renderer =
107 wlr_backend_get_renderer(output->wlr_output->backend);
108 assert(renderer);
109
110 struct wlr_box box;
111 get_decoration_box(view, output, &box);
112
113 struct wlr_box rotated;
114 wlr_box_rotated_bounds(&rotated, &box, view->rotation);
115
116 pixman_region32_t damage;
117 pixman_region32_init(&damage);
118 pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
119 rotated.width, rotated.height);
120 pixman_region32_intersect(&damage, &damage, data->damage);
121 bool damaged = pixman_region32_not_empty(&damage);
122 if (!damaged) {
123 goto damage_finish;
124 }
125
126 float matrix[9];
127 wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,
128 view->rotation, output->wlr_output->transform_matrix);
129 float color[] = { 0.2, 0.2, 0.2, view->alpha };
130
131 int nrects;
132 pixman_box32_t *rects =
133 pixman_region32_rectangles(&damage, &nrects);
134 for (int i = 0; i < nrects; ++i) {
135 scissor_output(output->wlr_output, &rects[i]);
136 wlr_render_quad_with_matrix(renderer, color, matrix);
137 }
138
139 damage_finish:
140 pixman_region32_fini(&damage);
141 }
142
143 static void render_view(struct roots_output *output, struct roots_view *view,
144 struct render_data *data) {
145 // Do not render views fullscreened on other outputs
146 if (view->fullscreen_output != NULL && view->fullscreen_output != output) {
147 return;
148 }
149
150 data->alpha = view->alpha;
151 if (view->fullscreen_output == NULL) {
152 render_decorations(output, view, data);
153 }
154 output_view_for_each_surface(output, view, render_surface_iterator, data);
155 }
156
157 static void render_layer(struct roots_output *output,
158 pixman_region32_t *damage, struct wl_list *layer_surfaces) {
159 struct render_data data = {
160 .damage = damage,
161 .alpha = 1.0f,
162 };
163 output_layer_for_each_surface(output, layer_surfaces,
164 render_surface_iterator, &data);
165 }
166
167 static void render_drag_icons(struct roots_output *output,
168 pixman_region32_t *damage, struct roots_input *input) {
169 struct render_data data = {
170 .damage = damage,
171 .alpha = 1.0f,
172 };
173 output_drag_icons_for_each_surface(output, input,
174 render_surface_iterator, &data);
175 }
176
177 static void surface_send_frame_done_iterator(struct roots_output *output,
178 struct wlr_surface *surface, struct wlr_box *box, float rotation,
179 void *data) {
180 struct timespec *when = data;
181 wlr_surface_send_frame_done(surface, when);
182 }
183
184 void output_render(struct roots_output *output) {
185 struct wlr_output *wlr_output = output->wlr_output;
186 struct roots_desktop *desktop = output->desktop;
187 struct roots_server *server = desktop->server;
188 struct wlr_renderer *renderer =
189 wlr_backend_get_renderer(wlr_output->backend);
190 assert(renderer);
191
192 if (!wlr_output->enabled) {
193 return;
194 }
195
196 struct timespec now;
197 clock_gettime(CLOCK_MONOTONIC, &now);
198
199 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
200
201 const struct wlr_box *output_box =
202 wlr_output_layout_get_box(desktop->layout, wlr_output);
203
204 // Check if we can delegate the fullscreen surface to the output
205 if (output->fullscreen_view != NULL &&
206 output->fullscreen_view->wlr_surface != NULL) {
207 struct roots_view *view = output->fullscreen_view;
208
209 // Make sure the view is centered on screen
210 struct wlr_box view_box;
211 view_get_box(view, &view_box);
212 double view_x = (double)(output_box->width - view_box.width) / 2 +
213 output_box->x;
214 double view_y = (double)(output_box->height - view_box.height) / 2 +
215 output_box->y;
216 view_move(view, view_x, view_y);
217
218 // Fullscreen views are rendered on a black background
219 clear_color[0] = clear_color[1] = clear_color[2] = 0;
220 }
221
222 bool needs_swap;
223 pixman_region32_t damage;
224 pixman_region32_init(&damage);
225 if (!wlr_output_damage_make_current(output->damage, &needs_swap, &damage)) {
226 return;
227 }
228
229 struct render_data data = {
230 .damage = &damage,
231 .alpha = 1.0,
232 };
233
234 if (!needs_swap) {
235 // Output doesn't need swap and isn't damaged, skip rendering completely
236 goto damage_finish;
237 }
238
239 wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
240
241 if (!pixman_region32_not_empty(&damage)) {
242 // Output isn't damaged but needs buffer swap
243 goto renderer_end;
244 }
245
246 if (server->config->debug_damage_tracking) {
247 wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
248 }
249
250 int nrects;
251 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
252 for (int i = 0; i < nrects; ++i) {
253 scissor_output(output->wlr_output, &rects[i]);
254 wlr_renderer_clear(renderer, clear_color);
255 }
256
257 render_layer(output, &damage,
258 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
259 render_layer(output, &damage,
260 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
261
262 // If a view is fullscreen on this output, render it
263 if (output->fullscreen_view != NULL) {
264 struct roots_view *view = output->fullscreen_view;
265
266 render_view(output, view, &data);
267
268 // During normal rendering the xwayland window tree isn't traversed
269 // because all windows are rendered. Here we only want to render
270 // the fullscreen window's children so we have to traverse the tree.
271 #if WLR_HAS_XWAYLAND
272 if (view->type == ROOTS_XWAYLAND_VIEW) {
273 struct roots_xwayland_surface *xwayland_surface =
274 roots_xwayland_surface_from_view(view);
275 output_xwayland_children_for_each_surface(output,
276 xwayland_surface->xwayland_surface,
277 render_surface_iterator, &data);
278 }
279 #endif
280 } else {
281 // Render all views
282 struct roots_view *view;
283 wl_list_for_each_reverse(view, &desktop->views, link) {
284 render_view(output, view, &data);
285 }
286 // Render top layer above shell views
287 render_layer(output, &damage,
288 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
289 }
290
291 render_drag_icons(output, &damage, server->input);
292
293 render_layer(output, &damage,
294 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
295
296 renderer_end:
297 wlr_output_render_software_cursors(wlr_output, &damage);
298 wlr_renderer_scissor(renderer, NULL);
299 wlr_renderer_end(renderer);
300
301 int width, height;
302 wlr_output_transformed_resolution(wlr_output, &width, &height);
303
304 if (server->config->debug_damage_tracking) {
305 pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
306 }
307
308 enum wl_output_transform transform =
309 wlr_output_transform_invert(wlr_output->transform);
310 wlr_region_transform(&damage, &damage, transform, width, height);
311
312 if (!wlr_output_damage_swap_buffers(output->damage, &now, &damage)) {
313 goto damage_finish;
314 }
315 output->last_frame = desktop->last_frame = now;
316
317 damage_finish:
318 pixman_region32_fini(&damage);
319
320 // Send frame done events to all surfaces
321 output_for_each_surface(output, surface_send_frame_done_iterator,
322 &now);
323 }
558558 }
559559 }
560560
561 void view_for_each_surface(struct roots_view *view,
562 wlr_surface_iterator_func_t iterator, void *user_data) {
563 if (view->impl->for_each_surface) {
564 view->impl->for_each_surface(view, iterator, user_data);
565 } else if (view->wlr_surface) {
566 wlr_surface_for_each_surface(view->wlr_surface, iterator, user_data);
567 }
568 }
569
561570 void view_update_position(struct roots_view *view, int x, int y) {
562571 if (view->box.x == x && view->box.y == y) {
563572 return;
7979 wl_client_destroy(surf->client);
8080 }
8181
82 static void for_each_surface(struct roots_view *view,
83 wlr_surface_iterator_func_t iterator, void *user_data) {
84 struct wlr_wl_shell_surface *surf =
85 roots_wl_shell_surface_from_view(view)->wl_shell_surface;
86 wlr_wl_shell_surface_for_each_surface(surf, iterator, user_data);
87 }
88
8289 static void destroy(struct roots_view *view) {
8390 struct roots_wl_shell_surface *roots_surface =
8491 roots_wl_shell_surface_from_view(view);
97104 static const struct roots_view_interface view_impl = {
98105 .resize = resize,
99106 .close = close,
107 .for_each_surface = for_each_surface,
100108 .destroy = destroy,
101109 };
102110
253253 wlr_xdg_popup_destroy(popup->base);
254254 }
255255 wlr_xdg_toplevel_send_close(xdg_surface);
256 }
257
258 static void for_each_surface(struct roots_view *view,
259 wlr_surface_iterator_func_t iterator, void *user_data) {
260 struct wlr_xdg_surface *xdg_surface =
261 roots_xdg_surface_from_view(view)->xdg_surface;
262 wlr_xdg_surface_for_each_surface(xdg_surface, iterator, user_data);
256263 }
257264
258265 static void destroy(struct roots_view *view) {
280287 .maximize = maximize,
281288 .set_fullscreen = set_fullscreen,
282289 .close = close,
290 .for_each_surface = for_each_surface,
283291 .destroy = destroy,
284292 };
285293
252252 wlr_xdg_surface_v6_send_close(popup->base);
253253 }
254254 wlr_xdg_surface_v6_send_close(surface);
255 }
256
257 static void for_each_surface(struct roots_view *view,
258 wlr_surface_iterator_func_t iterator, void *user_data) {
259 struct wlr_xdg_surface_v6 *surface =
260 roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
261 wlr_xdg_surface_v6_for_each_surface(surface, iterator, user_data);
255262 }
256263
257264 static void destroy(struct roots_view *view) {
278285 .maximize = maximize,
279286 .set_fullscreen = set_fullscreen,
280287 .close = close,
288 .for_each_surface = for_each_surface,
281289 .destroy = destroy,
282290 };
283291
4444 struct wl_listener cursor_motion_absolute;
4545 struct wl_listener cursor_button;
4646 struct wl_listener cursor_axis;
47 struct wl_listener cursor_frame;
4748
4849 struct wlr_seat *seat;
4950 struct wl_listener new_input;
498499 event->delta_discrete, event->source);
499500 }
500501
502 static void server_cursor_frame(struct wl_listener *listener, void *data) {
503 /* This event is forwarded by the cursor when a pointer emits an frame
504 * event. Frame events are sent after regular pointer events to group
505 * multiple events together. For instance, two axis events may happen at the
506 * same time, in which case a frame event won't be sent in between. */
507 struct tinywl_server *server =
508 wl_container_of(listener, server, cursor_frame);
509 /* Notify the client with pointer focus of the frame event. */
510 wlr_seat_pointer_notify_frame(server->seat);
511 }
512
501513 /* Used to move all of the data necessary to render a surface from the top-level
502514 * frame handler to the per-surface render function. */
503515 struct render_data {
875887 wl_signal_add(&server.cursor->events.button, &server.cursor_button);
876888 server.cursor_axis.notify = server_cursor_axis;
877889 wl_signal_add(&server.cursor->events.axis, &server.cursor_axis);
890 server.cursor_frame.notify = server_cursor_frame;
891 wl_signal_add(&server.cursor->events.frame, &server.cursor_frame);
878892
879893 /*
880894 * Configures a seat, which is a single "seat" at which a user sits and
1919 }
2020
2121 static uint32_t default_pointer_button(struct wlr_seat_pointer_grab *grab,
22 uint32_t time, uint32_t button, uint32_t state) {
22 uint32_t time, uint32_t button, enum wlr_button_state state) {
2323 return wlr_seat_pointer_send_button(grab->seat, time, button, state);
2424 }
2525
234234 }
235235
236236 uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
237 uint32_t button, uint32_t state) {
237 uint32_t button, enum wlr_button_state state) {
238238 struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client;
239239 if (client == NULL) {
240240 return 0;
336336 }
337337
338338 uint32_t wlr_seat_pointer_notify_button(struct wlr_seat *wlr_seat,
339 uint32_t time, uint32_t button, uint32_t state) {
339 uint32_t time, uint32_t button, enum wlr_button_state state) {
340340 clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
341 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
341 if (state == WLR_BUTTON_PRESSED) {
342342 if (wlr_seat->pointer_state.button_count == 0) {
343343 wlr_seat->pointer_state.grab_button = button;
344344 wlr_seat->pointer_state.grab_time = time;
345345 }
346346 wlr_seat->pointer_state.button_count++;
347347 } else {
348 wlr_seat->pointer_state.button_count--;
348 if (wlr_seat->pointer_state.button_count == 0) {
349 wlr_log(WLR_ERROR, "Corrupted seat button count");
350 } else {
351 wlr_seat->pointer_state.button_count--;
352 }
349353 }
350354
351355 struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
352356 uint32_t serial = grab->interface->button(grab, time, button, state);
353357
354 if (serial && wlr_seat->pointer_state.button_count == 1) {
358 if (serial && wlr_seat->pointer_state.button_count == 1 &&
359 state == WLR_BUTTON_PRESSED) {
355360 wlr_seat->pointer_state.grab_serial = serial;
356361 }
357362
406411 struct wlr_surface *origin, uint32_t serial) {
407412 if (seat->pointer_state.button_count != 1 ||
408413 seat->pointer_state.grab_serial != serial) {
414 wlr_log(WLR_DEBUG, "Pointer grab serial validation failed: "
415 "button_count=%"PRIu32" grab_serial=%"PRIu32" (got %"PRIu32")",
416 seat->pointer_state.button_count,
417 seat->pointer_state.grab_serial, serial);
409418 return false;
410419 }
411420
412421 if (origin != NULL && seat->pointer_state.focused_surface != origin) {
422 wlr_log(WLR_DEBUG, "Pointer grab serial validation failed: "
423 "invalid origin surface");
413424 return false;
414425 }
415426
364364 struct wlr_touch_point **point_ptr) {
365365 if (wlr_seat_touch_num_points(seat) != 1 ||
366366 seat->touch_state.grab_serial != serial) {
367 wlr_log(WLR_DEBUG, "Touch grab serial validation failed: "
368 "num_points=%d grab_serial=%"PRIu32" (got %"PRIu32")",
369 wlr_seat_touch_num_points(seat),
370 seat->touch_state.grab_serial, serial);
367371 return false;
368372 }
369373
377381 }
378382 }
379383
384 wlr_log(WLR_DEBUG, "Touch grab serial validation failed: "
385 "invalid origin surface");
380386 return false;
381387 }
379379 }
380380 } else {
381381 // layout extents
382 int min_x = INT_MAX, min_y = INT_MAX;
383 int max_x = INT_MIN, max_y = INT_MIN;
384 wl_list_for_each(l_output, &layout->outputs, link) {
385 struct wlr_box *box = output_layout_output_get_box(l_output);
386
387 if (box->x < min_x) {
388 min_x = box->x;
389 }
390 if (box->y < min_y) {
391 min_y = box->y;
392 }
393 if (box->x + box->width > max_x) {
394 max_x = box->x + box->width;
395 }
396 if (box->y + box->height > max_y) {
397 max_y = box->y + box->height;
382 int min_x = 0, max_x = 0, min_y = 0, max_y = 0;
383 if (!wl_list_empty(&layout->outputs)) {
384 min_x = min_y = INT_MAX;
385 max_x = max_y = INT_MIN;
386 wl_list_for_each(l_output, &layout->outputs, link) {
387 struct wlr_box *box = output_layout_output_get_box(l_output);
388 if (box->x < min_x) {
389 min_x = box->x;
390 }
391 if (box->y < min_y) {
392 min_y = box->y;
393 }
394 if (box->x + box->width > max_x) {
395 max_x = box->x + box->width;
396 }
397 if (box->y + box->height > max_y) {
398 max_y = box->y + box->height;
399 }
398400 }
399401 }
400402
1313 #include <wlr/util/log.h>
1414 #include "sockets.h"
1515
16 static const char *lock_fmt = "/tmp/.X%d-lock";
17 static const char *socket_dir = "/tmp/.X11-unix";
18 static const char *socket_fmt = "/tmp/.X11-unix/X%d";
16 static const char lock_fmt[] = "/tmp/.X%d-lock";
17 static const char socket_dir[] = "/tmp/.X11-unix";
18 static const char socket_fmt[] = "/tmp/.X11-unix/X%d";
1919 #ifndef __linux__
20 static const char *socket_fmt2 = "/tmp/.X11-unix/X%d_";
20 static const char socket_fmt2[] = "/tmp/.X11-unix/X%d_";
2121 #endif
2222
2323 bool set_cloexec(int fd, bool cloexec) {
0 #define _POSIX_C_SOURCE 200112L
0 #define _POSIX_C_SOURCE 200809L
11 #include <errno.h>
22 #include <fcntl.h>
33 #include <signal.h>
9191
9292 // Closes stdout/stderr depending on log verbosity
9393 enum wlr_log_importance verbosity = wlr_log_get_verbosity();
94 int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666);
94 int devnull = open("/dev/null", O_WRONLY | O_CREAT | O_CLOEXEC, 0666);
9595 if (devnull < 0) {
9696 wlr_log_errno(WLR_ERROR, "XWayland: failed to open /dev/null");
9797 _exit(EXIT_FAILURE);
164164
165165 unlink_display_sockets(wlr_xwayland->display);
166166 wlr_xwayland->display = -1;
167 unsetenv("DISPLAY");
168 }
169
170 static bool xwayland_start_display(struct wlr_xwayland *wlr_xwayland,
171 struct wl_display *wl_display);
167 wlr_xwayland->display_name[0] = '\0';
168 }
172169
173170 static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland);
174171 static bool xwayland_start_server_lazy(struct wlr_xwayland *wlr_xwayland);
283280 return false;
284281 }
285282
286 char display_name[16];
287 snprintf(display_name, sizeof(display_name), ":%d", wlr_xwayland->display);
288 setenv("DISPLAY", display_name, true);
289
283 snprintf(wlr_xwayland->display_name, sizeof(wlr_xwayland->display_name),
284 ":%d", wlr_xwayland->display);
290285 return true;
291286 }
292287
582582 memcpy(xsurface->size_hints, &size_hints,
583583 sizeof(struct wlr_xwayland_surface_size_hints));
584584
585 if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) == 0) {
585 bool has_min_size_hints = (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) != 0;
586 bool has_base_size_hints = (size_hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) != 0;
587 /* ICCCM says that if absent, min size is equal to base size and vice versa */
588 if (!has_min_size_hints && !has_base_size_hints) {
586589 xsurface->size_hints->min_width = -1;
587590 xsurface->size_hints->min_height = -1;
588 }
591 xsurface->size_hints->base_width = -1;
592 xsurface->size_hints->base_height = -1;
593 } else if (!has_base_size_hints) {
594 xsurface->size_hints->base_width = xsurface->size_hints->min_width;
595 xsurface->size_hints->base_height = xsurface->size_hints->min_height;
596 } else if (!has_min_size_hints) {
597 xsurface->size_hints->min_width = xsurface->size_hints->base_width;
598 xsurface->size_hints->min_height = xsurface->size_hints->base_height;
599 }
600
589601 if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) == 0) {
590602 xsurface->size_hints->max_width = -1;
591603 xsurface->size_hints->max_height = -1;