aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/xwayland.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/xwayland.c')
-rw-r--r--sway/desktop/xwayland.c340
1 files changed, 226 insertions, 114 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index e1a2e463..270cf08f 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -1,20 +1,23 @@
1#define _POSIX_C_SOURCE 199309L
2#include <float.h> 1#include <float.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
5#include <wayland-server-core.h> 4#include <wayland-server-core.h>
6#include <wlr/types/wlr_output_layout.h> 5#include <wlr/types/wlr_output_layout.h>
7#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_xdg_activation_v1.h>
8#include <wlr/types/wlr_scene.h>
8#include <wlr/xwayland.h> 9#include <wlr/xwayland.h>
10#include <xcb/xcb_icccm.h>
9#include "log.h" 11#include "log.h"
10#include "sway/desktop.h"
11#include "sway/desktop/transaction.h" 12#include "sway/desktop/transaction.h"
12#include "sway/input/cursor.h" 13#include "sway/input/cursor.h"
13#include "sway/input/input-manager.h" 14#include "sway/input/input-manager.h"
14#include "sway/input/seat.h" 15#include "sway/input/seat.h"
15#include "sway/output.h" 16#include "sway/output.h"
17#include "sway/scene_descriptor.h"
16#include "sway/tree/arrange.h" 18#include "sway/tree/arrange.h"
17#include "sway/tree/container.h" 19#include "sway/tree/container.h"
20#include "sway/server.h"
18#include "sway/tree/view.h" 21#include "sway/tree/view.h"
19#include "sway/tree/workspace.h" 22#include "sway/tree/workspace.h"
20 23
@@ -42,29 +45,12 @@ static void unmanaged_handle_request_configure(struct wl_listener *listener,
42 ev->width, ev->height); 45 ev->width, ev->height);
43} 46}
44 47
45static void unmanaged_handle_commit(struct wl_listener *listener, void *data) {
46 struct sway_xwayland_unmanaged *surface =
47 wl_container_of(listener, surface, commit);
48 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
49
50 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
51 false);
52}
53
54static void unmanaged_handle_set_geometry(struct wl_listener *listener, void *data) { 48static void unmanaged_handle_set_geometry(struct wl_listener *listener, void *data) {
55 struct sway_xwayland_unmanaged *surface = 49 struct sway_xwayland_unmanaged *surface =
56 wl_container_of(listener, surface, set_geometry); 50 wl_container_of(listener, surface, set_geometry);
57 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 51 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
58 52
59 if (xsurface->x != surface->lx || xsurface->y != surface->ly) { 53 wlr_scene_node_set_position(&surface->surface_scene->buffer->node, xsurface->x, xsurface->y);
60 // Surface has moved
61 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
62 true);
63 surface->lx = xsurface->x;
64 surface->ly = xsurface->y;
65 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
66 true);
67 }
68} 54}
69 55
70static void unmanaged_handle_map(struct wl_listener *listener, void *data) { 56static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
@@ -72,17 +58,18 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
72 wl_container_of(listener, surface, map); 58 wl_container_of(listener, surface, map);
73 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 59 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
74 60
75 wl_list_insert(root->xwayland_unmanaged.prev, &surface->link); 61 surface->surface_scene = wlr_scene_surface_create(root->layers.unmanaged,
76 62 xsurface->surface);
77 wl_signal_add(&xsurface->events.set_geometry, &surface->set_geometry);
78 surface->set_geometry.notify = unmanaged_handle_set_geometry;
79 63
80 wl_signal_add(&xsurface->surface->events.commit, &surface->commit); 64 if (surface->surface_scene) {
81 surface->commit.notify = unmanaged_handle_commit; 65 scene_descriptor_assign(&surface->surface_scene->buffer->node,
66 SWAY_SCENE_DESC_XWAYLAND_UNMANAGED, surface);
67 wlr_scene_node_set_position(&surface->surface_scene->buffer->node,
68 xsurface->x, xsurface->y);
82 69
83 surface->lx = xsurface->x; 70 wl_signal_add(&xsurface->events.set_geometry, &surface->set_geometry);
84 surface->ly = xsurface->y; 71 surface->set_geometry.notify = unmanaged_handle_set_geometry;
85 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true); 72 }
86 73
87 if (wlr_xwayland_or_surface_wants_focus(xsurface)) { 74 if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
88 struct sway_seat *seat = input_manager_current_seat(); 75 struct sway_seat *seat = input_manager_current_seat();
@@ -96,23 +83,22 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
96 struct sway_xwayland_unmanaged *surface = 83 struct sway_xwayland_unmanaged *surface =
97 wl_container_of(listener, surface, unmap); 84 wl_container_of(listener, surface, unmap);
98 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 85 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
99 desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, true); 86
100 wl_list_remove(&surface->link); 87 if (surface->surface_scene) {
101 wl_list_remove(&surface->set_geometry.link); 88 wl_list_remove(&surface->set_geometry.link);
102 wl_list_remove(&surface->commit.link); 89
90 wlr_scene_node_destroy(&surface->surface_scene->buffer->node);
91 surface->surface_scene = NULL;
92 }
103 93
104 struct sway_seat *seat = input_manager_current_seat(); 94 struct sway_seat *seat = input_manager_current_seat();
105 if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { 95 if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) {
106 // This simply returns focus to the parent surface if there's one available. 96 // This simply returns focus to the parent surface if there's one available.
107 // This seems to handle JetBrains issues. 97 // This seems to handle JetBrains issues.
108 if (xsurface->parent && xsurface->parent->surface && 98 if (xsurface->parent && xsurface->parent->surface
109 wlr_surface_is_xwayland_surface(xsurface->parent->surface)) { 99 && wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
110 struct wlr_xwayland_surface *next_surface = 100 seat_set_focus_surface(seat, xsurface->parent->surface, false);
111 wlr_xwayland_surface_from_wlr_surface(xsurface->parent->surface); 101 return;
112 if (wlr_xwayland_or_surface_wants_focus(next_surface)) {
113 seat_set_focus_surface(seat, xsurface->parent->surface, false);
114 return;
115 }
116 } 102 }
117 103
118 // Restore focus 104 // Restore focus
@@ -125,18 +111,53 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
125 } 111 }
126} 112}
127 113
114static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) {
115 struct sway_xwayland_unmanaged *surface =
116 wl_container_of(listener, surface, request_activate);
117 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
118 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
119 return;
120 }
121 struct sway_seat *seat = input_manager_current_seat();
122 struct sway_container *focus = seat_get_focused_container(seat);
123 if (focus && focus->view && focus->view->pid != xsurface->pid) {
124 return;
125 }
126
127 seat_set_focus_surface(seat, xsurface->surface, false);
128}
129
130static void unmanaged_handle_associate(struct wl_listener *listener, void *data) {
131 struct sway_xwayland_unmanaged *surface =
132 wl_container_of(listener, surface, associate);
133 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
134 wl_signal_add(&xsurface->surface->events.map, &surface->map);
135 surface->map.notify = unmanaged_handle_map;
136 wl_signal_add(&xsurface->surface->events.unmap, &surface->unmap);
137 surface->unmap.notify = unmanaged_handle_unmap;
138}
139
140static void unmanaged_handle_dissociate(struct wl_listener *listener, void *data) {
141 struct sway_xwayland_unmanaged *surface =
142 wl_container_of(listener, surface, dissociate);
143 wl_list_remove(&surface->map.link);
144 wl_list_remove(&surface->unmap.link);
145}
146
128static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { 147static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
129 struct sway_xwayland_unmanaged *surface = 148 struct sway_xwayland_unmanaged *surface =
130 wl_container_of(listener, surface, destroy); 149 wl_container_of(listener, surface, destroy);
131 wl_list_remove(&surface->request_configure.link); 150 wl_list_remove(&surface->request_configure.link);
132 wl_list_remove(&surface->map.link); 151 wl_list_remove(&surface->associate.link);
133 wl_list_remove(&surface->unmap.link); 152 wl_list_remove(&surface->dissociate.link);
134 wl_list_remove(&surface->destroy.link); 153 wl_list_remove(&surface->destroy.link);
135 wl_list_remove(&surface->override_redirect.link); 154 wl_list_remove(&surface->override_redirect.link);
155 wl_list_remove(&surface->request_activate.link);
136 free(surface); 156 free(surface);
137} 157}
138 158
139static void handle_map(struct wl_listener *listener, void *data); 159static void handle_map(struct wl_listener *listener, void *data);
160static void handle_associate(struct wl_listener *listener, void *data);
140 161
141struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); 162struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);
142 163
@@ -145,14 +166,22 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
145 wl_container_of(listener, surface, override_redirect); 166 wl_container_of(listener, surface, override_redirect);
146 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 167 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
147 168
148 bool mapped = xsurface->mapped; 169 bool associated = xsurface->surface != NULL;
170 bool mapped = associated && xsurface->surface->mapped;
149 if (mapped) { 171 if (mapped) {
150 unmanaged_handle_unmap(&surface->unmap, NULL); 172 unmanaged_handle_unmap(&surface->unmap, NULL);
151 } 173 }
174 if (associated) {
175 unmanaged_handle_dissociate(&surface->dissociate, NULL);
176 }
152 177
153 unmanaged_handle_destroy(&surface->destroy, NULL); 178 unmanaged_handle_destroy(&surface->destroy, NULL);
154 xsurface->data = NULL; 179 xsurface->data = NULL;
180
155 struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface); 181 struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface);
182 if (associated) {
183 handle_associate(&xwayland_view->associate, NULL);
184 }
156 if (mapped) { 185 if (mapped) {
157 handle_map(&xwayland_view->map, xsurface); 186 handle_map(&xwayland_view->map, xsurface);
158 } 187 }
@@ -172,14 +201,16 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
172 wl_signal_add(&xsurface->events.request_configure, 201 wl_signal_add(&xsurface->events.request_configure,
173 &surface->request_configure); 202 &surface->request_configure);
174 surface->request_configure.notify = unmanaged_handle_request_configure; 203 surface->request_configure.notify = unmanaged_handle_request_configure;
175 wl_signal_add(&xsurface->events.map, &surface->map); 204 wl_signal_add(&xsurface->events.associate, &surface->associate);
176 surface->map.notify = unmanaged_handle_map; 205 surface->associate.notify = unmanaged_handle_associate;
177 wl_signal_add(&xsurface->events.unmap, &surface->unmap); 206 wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
178 surface->unmap.notify = unmanaged_handle_unmap; 207 surface->dissociate.notify = unmanaged_handle_dissociate;
179 wl_signal_add(&xsurface->events.destroy, &surface->destroy); 208 wl_signal_add(&xsurface->events.destroy, &surface->destroy);
180 surface->destroy.notify = unmanaged_handle_destroy; 209 surface->destroy.notify = unmanaged_handle_destroy;
181 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); 210 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
182 surface->override_redirect.notify = unmanaged_handle_override_redirect; 211 surface->override_redirect.notify = unmanaged_handle_override_redirect;
212 wl_signal_add(&xsurface->events.request_activate, &surface->request_activate);
213 surface->request_activate.notify = unmanaged_handle_request_activate;
183 214
184 return surface; 215 return surface;
185} 216}
@@ -258,6 +289,7 @@ static void set_activated(struct sway_view *view, bool activated) {
258 } 289 }
259 290
260 wlr_xwayland_surface_activate(surface, activated); 291 wlr_xwayland_surface_activate(surface, activated);
292 wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
261} 293}
262 294
263static void set_tiled(struct sway_view *view, bool tiled) { 295static void set_tiled(struct sway_view *view, bool tiled) {
@@ -297,7 +329,7 @@ static bool wants_floating(struct sway_view *view) {
297 } 329 }
298 } 330 }
299 331
300 struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; 332 xcb_size_hints_t *size_hints = surface->size_hints;
301 if (size_hints != NULL && 333 if (size_hints != NULL &&
302 size_hints->min_width > 0 && size_hints->min_height > 0 && 334 size_hints->min_width > 0 && size_hints->min_height > 0 &&
303 (size_hints->max_width == size_hints->min_width || 335 (size_hints->max_width == size_hints->min_width ||
@@ -351,7 +383,7 @@ static void destroy(struct sway_view *view) {
351static void get_constraints(struct sway_view *view, double *min_width, 383static void get_constraints(struct sway_view *view, double *min_width,
352 double *max_width, double *min_height, double *max_height) { 384 double *max_width, double *min_height, double *max_height) {
353 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; 385 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
354 struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; 386 xcb_size_hints_t *size_hints = surface->size_hints;
355 387
356 if (size_hints == NULL) { 388 if (size_hints == NULL) {
357 *min_width = DBL_MIN; 389 *min_width = DBL_MIN;
@@ -381,17 +413,6 @@ static const struct sway_view_impl view_impl = {
381 .destroy = destroy, 413 .destroy = destroy,
382}; 414};
383 415
384static void get_geometry(struct sway_view *view, struct wlr_box *box) {
385 box->x = box->y = 0;
386 if (view->surface) {
387 box->width = view->surface->current.width;
388 box->height = view->surface->current.height;
389 } else {
390 box->width = 0;
391 box->height = 0;
392 }
393}
394
395static void handle_commit(struct wl_listener *listener, void *data) { 416static void handle_commit(struct wl_listener *listener, void *data) {
396 struct sway_xwayland_view *xwayland_view = 417 struct sway_xwayland_view *xwayland_view =
397 wl_container_of(listener, xwayland_view, commit); 418 wl_container_of(listener, xwayland_view, commit);
@@ -399,33 +420,38 @@ static void handle_commit(struct wl_listener *listener, void *data) {
399 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 420 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
400 struct wlr_surface_state *state = &xsurface->surface->current; 421 struct wlr_surface_state *state = &xsurface->surface->current;
401 422
423 struct wlr_box new_geo = {0};
424 new_geo.width = state->width;
425 new_geo.height = state->height;
426
427 bool new_size = new_geo.width != view->geometry.width ||
428 new_geo.height != view->geometry.height;
429
430 if (new_size) {
431 // The client changed its surface size in this commit. For floating
432 // containers, we resize the container to match. For tiling containers,
433 // we only recenter the surface.
434 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
435 if (container_is_floating(view->container)) {
436 view_update_size(view);
437 transaction_commit_dirty_client();
438 }
439
440 view_center_and_clip_surface(view);
441 }
442
402 if (view->container->node.instruction) { 443 if (view->container->node.instruction) {
403 get_geometry(view, &view->geometry); 444 bool successful = transaction_notify_view_ready_by_geometry(view,
404 transaction_notify_view_ready_by_geometry(view,
405 xsurface->x, xsurface->y, state->width, state->height); 445 xsurface->x, xsurface->y, state->width, state->height);
406 } else { 446
407 struct wlr_box new_geo; 447 // If we saved the view and this commit isn't what we're looking for
408 get_geometry(view, &new_geo); 448 // that means the user will never actually see the buffers submitted to
409 449 // us here. Just send frame done events to these surfaces so they can
410 if ((new_geo.width != view->geometry.width || 450 // commit another time for us.
411 new_geo.height != view->geometry.height || 451 if (view->saved_surface_tree && !successful) {
412 new_geo.x != view->geometry.x || 452 view_send_frame_done(view);
413 new_geo.y != view->geometry.y)) {
414 // The view has unexpectedly sent a new size
415 // eg. The Firefox "Save As" dialog when downloading a file
416 desktop_damage_view(view);
417 view_update_size(view, new_geo.width, new_geo.height);
418 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
419 desktop_damage_view(view);
420 transaction_commit_dirty();
421 transaction_notify_view_ready_by_geometry(view,
422 xsurface->x, xsurface->y, new_geo.width, new_geo.height);
423 } else {
424 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
425 } 453 }
426 } 454 }
427
428 view_damage_from(view);
429} 455}
430 456
431static void handle_destroy(struct wl_listener *listener, void *data) { 457static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -438,6 +464,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
438 wl_list_remove(&xwayland_view->commit.link); 464 wl_list_remove(&xwayland_view->commit.link);
439 } 465 }
440 466
467 xwayland_view->view.wlr_xwayland_surface = NULL;
468
441 wl_list_remove(&xwayland_view->destroy.link); 469 wl_list_remove(&xwayland_view->destroy.link);
442 wl_list_remove(&xwayland_view->request_configure.link); 470 wl_list_remove(&xwayland_view->request_configure.link);
443 wl_list_remove(&xwayland_view->request_fullscreen.link); 471 wl_list_remove(&xwayland_view->request_fullscreen.link);
@@ -448,11 +476,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
448 wl_list_remove(&xwayland_view->set_title.link); 476 wl_list_remove(&xwayland_view->set_title.link);
449 wl_list_remove(&xwayland_view->set_class.link); 477 wl_list_remove(&xwayland_view->set_class.link);
450 wl_list_remove(&xwayland_view->set_role.link); 478 wl_list_remove(&xwayland_view->set_role.link);
479 wl_list_remove(&xwayland_view->set_startup_id.link);
451 wl_list_remove(&xwayland_view->set_window_type.link); 480 wl_list_remove(&xwayland_view->set_window_type.link);
452 wl_list_remove(&xwayland_view->set_hints.link); 481 wl_list_remove(&xwayland_view->set_hints.link);
453 wl_list_remove(&xwayland_view->set_decorations.link); 482 wl_list_remove(&xwayland_view->set_decorations.link);
454 wl_list_remove(&xwayland_view->map.link); 483 wl_list_remove(&xwayland_view->associate.link);
455 wl_list_remove(&xwayland_view->unmap.link); 484 wl_list_remove(&xwayland_view->dissociate.link);
456 wl_list_remove(&xwayland_view->override_redirect.link); 485 wl_list_remove(&xwayland_view->override_redirect.link);
457 view_begin_destroy(&xwayland_view->view); 486 view_begin_destroy(&xwayland_view->view);
458} 487}
@@ -466,16 +495,28 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
466 return; 495 return;
467 } 496 }
468 497
498 wl_list_remove(&xwayland_view->commit.link);
499 wl_list_remove(&xwayland_view->surface_tree_destroy.link);
500
501 if (xwayland_view->surface_tree) {
502 wlr_scene_node_destroy(&xwayland_view->surface_tree->node);
503 xwayland_view->surface_tree = NULL;
504 }
505
469 view_unmap(view); 506 view_unmap(view);
507}
470 508
471 wl_list_remove(&xwayland_view->commit.link); 509static void handle_surface_tree_destroy(struct wl_listener *listener, void *data) {
510 struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view,
511 surface_tree_destroy);
512 xwayland_view->surface_tree = NULL;
472} 513}
473 514
474static void handle_map(struct wl_listener *listener, void *data) { 515static void handle_map(struct wl_listener *listener, void *data) {
475 struct sway_xwayland_view *xwayland_view = 516 struct sway_xwayland_view *xwayland_view =
476 wl_container_of(listener, xwayland_view, map); 517 wl_container_of(listener, xwayland_view, map);
477 struct wlr_xwayland_surface *xsurface = data;
478 struct sway_view *view = &xwayland_view->view; 518 struct sway_view *view = &xwayland_view->view;
519 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
479 520
480 view->natural_width = xsurface->width; 521 view->natural_width = xsurface->width;
481 view->natural_height = xsurface->height; 522 view->natural_height = xsurface->height;
@@ -488,23 +529,42 @@ static void handle_map(struct wl_listener *listener, void *data) {
488 // Put it back into the tree 529 // Put it back into the tree
489 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false); 530 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false);
490 531
532 xwayland_view->surface_tree = wlr_scene_subsurface_tree_create(
533 xwayland_view->view.content_tree, xsurface->surface);
534
535 if (xwayland_view->surface_tree) {
536 xwayland_view->surface_tree_destroy.notify = handle_surface_tree_destroy;
537 wl_signal_add(&xwayland_view->surface_tree->node.events.destroy,
538 &xwayland_view->surface_tree_destroy);
539 }
540
491 transaction_commit_dirty(); 541 transaction_commit_dirty();
492} 542}
493 543
544static void handle_dissociate(struct wl_listener *listener, void *data);
545
494static void handle_override_redirect(struct wl_listener *listener, void *data) { 546static void handle_override_redirect(struct wl_listener *listener, void *data) {
495 struct sway_xwayland_view *xwayland_view = 547 struct sway_xwayland_view *xwayland_view =
496 wl_container_of(listener, xwayland_view, override_redirect); 548 wl_container_of(listener, xwayland_view, override_redirect);
497 struct wlr_xwayland_surface *xsurface = data;
498 struct sway_view *view = &xwayland_view->view; 549 struct sway_view *view = &xwayland_view->view;
550 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
499 551
500 bool mapped = xsurface->mapped; 552 bool associated = xsurface->surface != NULL;
553 bool mapped = associated && xsurface->surface->mapped;
501 if (mapped) { 554 if (mapped) {
502 handle_unmap(&xwayland_view->unmap, NULL); 555 handle_unmap(&xwayland_view->unmap, NULL);
503 } 556 }
557 if (associated) {
558 handle_dissociate(&xwayland_view->dissociate, NULL);
559 }
504 560
505 handle_destroy(&xwayland_view->destroy, view); 561 handle_destroy(&xwayland_view->destroy, view);
506 xsurface->data = NULL; 562 xsurface->data = NULL;
563
507 struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); 564 struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
565 if (associated) {
566 unmanaged_handle_associate(&unmanaged->associate, NULL);
567 }
508 if (mapped) { 568 if (mapped) {
509 unmanaged_handle_map(&unmanaged->map, xsurface); 569 unmanaged_handle_map(&unmanaged->map, xsurface);
510 } 570 }
@@ -516,7 +576,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
516 struct wlr_xwayland_surface_configure_event *ev = data; 576 struct wlr_xwayland_surface_configure_event *ev = data;
517 struct sway_view *view = &xwayland_view->view; 577 struct sway_view *view = &xwayland_view->view;
518 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 578 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
519 if (!xsurface->mapped) { 579 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
520 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, 580 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y,
521 ev->width, ev->height); 581 ev->width, ev->height);
522 return; 582 return;
@@ -527,10 +587,10 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
527 view->natural_height = ev->height; 587 view->natural_height = ev->height;
528 container_floating_resize_and_center(view->container); 588 container_floating_resize_and_center(view->container);
529 589
530 configure(view, view->container->content_x, 590 configure(view, view->container->pending.content_x,
531 view->container->content_y, 591 view->container->pending.content_y,
532 view->container->content_width, 592 view->container->pending.content_width,
533 view->container->content_height); 593 view->container->pending.content_height);
534 node_set_dirty(&view->container->node); 594 node_set_dirty(&view->container->node);
535 } else { 595 } else {
536 configure(view, view->container->current.content_x, 596 configure(view, view->container->current.content_x,
@@ -545,7 +605,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
545 wl_container_of(listener, xwayland_view, request_fullscreen); 605 wl_container_of(listener, xwayland_view, request_fullscreen);
546 struct sway_view *view = &xwayland_view->view; 606 struct sway_view *view = &xwayland_view->view;
547 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 607 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
548 if (!xsurface->mapped) { 608 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
549 return; 609 return;
550 } 610 }
551 container_set_fullscreen(view->container, xsurface->fullscreen); 611 container_set_fullscreen(view->container, xsurface->fullscreen);
@@ -559,7 +619,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) {
559 wl_container_of(listener, xwayland_view, request_minimize); 619 wl_container_of(listener, xwayland_view, request_minimize);
560 struct sway_view *view = &xwayland_view->view; 620 struct sway_view *view = &xwayland_view->view;
561 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 621 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
562 if (!xsurface->mapped) { 622 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
563 return; 623 return;
564 } 624 }
565 625
@@ -574,10 +634,11 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
574 wl_container_of(listener, xwayland_view, request_move); 634 wl_container_of(listener, xwayland_view, request_move);
575 struct sway_view *view = &xwayland_view->view; 635 struct sway_view *view = &xwayland_view->view;
576 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 636 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
577 if (!xsurface->mapped) { 637 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
578 return; 638 return;
579 } 639 }
580 if (!container_is_floating(view->container)) { 640 if (!container_is_floating(view->container) ||
641 view->container->pending.fullscreen_mode) {
581 return; 642 return;
582 } 643 }
583 struct sway_seat *seat = input_manager_current_seat(); 644 struct sway_seat *seat = input_manager_current_seat();
@@ -589,7 +650,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
589 wl_container_of(listener, xwayland_view, request_resize); 650 wl_container_of(listener, xwayland_view, request_resize);
590 struct sway_view *view = &xwayland_view->view; 651 struct sway_view *view = &xwayland_view->view;
591 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 652 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
592 if (!xsurface->mapped) { 653 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
593 return; 654 return;
594 } 655 }
595 if (!container_is_floating(view->container)) { 656 if (!container_is_floating(view->container)) {
@@ -605,10 +666,10 @@ static void handle_request_activate(struct wl_listener *listener, void *data) {
605 wl_container_of(listener, xwayland_view, request_activate); 666 wl_container_of(listener, xwayland_view, request_activate);
606 struct sway_view *view = &xwayland_view->view; 667 struct sway_view *view = &xwayland_view->view;
607 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 668 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
608 if (!xsurface->mapped) { 669 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
609 return; 670 return;
610 } 671 }
611 view_request_activate(view); 672 view_request_activate(view, NULL);
612 673
613 transaction_commit_dirty(); 674 transaction_commit_dirty();
614} 675}
@@ -618,7 +679,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
618 wl_container_of(listener, xwayland_view, set_title); 679 wl_container_of(listener, xwayland_view, set_title);
619 struct sway_view *view = &xwayland_view->view; 680 struct sway_view *view = &xwayland_view->view;
620 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 681 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
621 if (!xsurface->mapped) { 682 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
622 return; 683 return;
623 } 684 }
624 view_update_title(view, false); 685 view_update_title(view, false);
@@ -630,7 +691,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
630 wl_container_of(listener, xwayland_view, set_class); 691 wl_container_of(listener, xwayland_view, set_class);
631 struct sway_view *view = &xwayland_view->view; 692 struct sway_view *view = &xwayland_view->view;
632 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 693 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
633 if (!xsurface->mapped) { 694 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
634 return; 695 return;
635 } 696 }
636 view_execute_criteria(view); 697 view_execute_criteria(view);
@@ -641,18 +702,43 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
641 wl_container_of(listener, xwayland_view, set_role); 702 wl_container_of(listener, xwayland_view, set_role);
642 struct sway_view *view = &xwayland_view->view; 703 struct sway_view *view = &xwayland_view->view;
643 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 704 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
644 if (!xsurface->mapped) { 705 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
645 return; 706 return;
646 } 707 }
647 view_execute_criteria(view); 708 view_execute_criteria(view);
648} 709}
649 710
711static void handle_set_startup_id(struct wl_listener *listener, void *data) {
712 struct sway_xwayland_view *xwayland_view =
713 wl_container_of(listener, xwayland_view, set_startup_id);
714 struct sway_view *view = &xwayland_view->view;
715 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
716 if (xsurface->startup_id == NULL) {
717 return;
718 }
719
720 struct wlr_xdg_activation_token_v1 *token =
721 wlr_xdg_activation_v1_find_token(
722 server.xdg_activation_v1, xsurface->startup_id);
723 if (token == NULL) {
724 // Tried to activate with an unknown or expired token
725 return;
726 }
727
728 struct launcher_ctx *ctx = token->data;
729 if (token->data == NULL) {
730 // TODO: support external launchers in X
731 return;
732 }
733 view_assign_ctx(view, ctx);
734}
735
650static void handle_set_window_type(struct wl_listener *listener, void *data) { 736static void handle_set_window_type(struct wl_listener *listener, void *data) {
651 struct sway_xwayland_view *xwayland_view = 737 struct sway_xwayland_view *xwayland_view =
652 wl_container_of(listener, xwayland_view, set_window_type); 738 wl_container_of(listener, xwayland_view, set_window_type);
653 struct sway_view *view = &xwayland_view->view; 739 struct sway_view *view = &xwayland_view->view;
654 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 740 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
655 if (!xsurface->mapped) { 741 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
656 return; 742 return;
657 } 743 }
658 view_execute_criteria(view); 744 view_execute_criteria(view);
@@ -663,20 +749,39 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
663 wl_container_of(listener, xwayland_view, set_hints); 749 wl_container_of(listener, xwayland_view, set_hints);
664 struct sway_view *view = &xwayland_view->view; 750 struct sway_view *view = &xwayland_view->view;
665 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 751 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
666 if (!xsurface->mapped) { 752 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
667 return; 753 return;
668 } 754 }
669 if (!xsurface->hints_urgency && view->urgent_timer) { 755 const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints);
756 if (!hints_urgency && view->urgent_timer) {
670 // The view is in the timeout period. We'll ignore the request to 757 // The view is in the timeout period. We'll ignore the request to
671 // unset urgency so that the view remains urgent until the timer clears 758 // unset urgency so that the view remains urgent until the timer clears
672 // it. 759 // it.
673 return; 760 return;
674 } 761 }
675 if (view->allow_request_urgent) { 762 if (view->allow_request_urgent) {
676 view_set_urgent(view, (bool)xsurface->hints_urgency); 763 view_set_urgent(view, hints_urgency);
677 } 764 }
678} 765}
679 766
767static void handle_associate(struct wl_listener *listener, void *data) {
768 struct sway_xwayland_view *xwayland_view =
769 wl_container_of(listener, xwayland_view, associate);
770 struct wlr_xwayland_surface *xsurface =
771 xwayland_view->view.wlr_xwayland_surface;
772 wl_signal_add(&xsurface->surface->events.unmap, &xwayland_view->unmap);
773 xwayland_view->unmap.notify = handle_unmap;
774 wl_signal_add(&xsurface->surface->events.map, &xwayland_view->map);
775 xwayland_view->map.notify = handle_map;
776}
777
778static void handle_dissociate(struct wl_listener *listener, void *data) {
779 struct sway_xwayland_view *xwayland_view =
780 wl_container_of(listener, xwayland_view, dissociate);
781 wl_list_remove(&xwayland_view->map.link);
782 wl_list_remove(&xwayland_view->unmap.link);
783}
784
680struct sway_view *view_from_wlr_xwayland_surface( 785struct sway_view *view_from_wlr_xwayland_surface(
681 struct wlr_xwayland_surface *xsurface) { 786 struct wlr_xwayland_surface *xsurface) {
682 return xsurface->data; 787 return xsurface->data;
@@ -692,7 +797,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
692 return NULL; 797 return NULL;
693 } 798 }
694 799
695 view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); 800 if (!view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl)) {
801 free(xwayland_view);
802 return NULL;
803 }
696 xwayland_view->view.wlr_xwayland_surface = xsurface; 804 xwayland_view->view.wlr_xwayland_surface = xsurface;
697 805
698 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy); 806 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy);
@@ -731,6 +839,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
731 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role); 839 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role);
732 xwayland_view->set_role.notify = handle_set_role; 840 xwayland_view->set_role.notify = handle_set_role;
733 841
842 wl_signal_add(&xsurface->events.set_startup_id,
843 &xwayland_view->set_startup_id);
844 xwayland_view->set_startup_id.notify = handle_set_startup_id;
845
734 wl_signal_add(&xsurface->events.set_window_type, 846 wl_signal_add(&xsurface->events.set_window_type,
735 &xwayland_view->set_window_type); 847 &xwayland_view->set_window_type);
736 xwayland_view->set_window_type.notify = handle_set_window_type; 848 xwayland_view->set_window_type.notify = handle_set_window_type;
@@ -742,11 +854,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
742 &xwayland_view->set_decorations); 854 &xwayland_view->set_decorations);
743 xwayland_view->set_decorations.notify = handle_set_decorations; 855 xwayland_view->set_decorations.notify = handle_set_decorations;
744 856
745 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); 857 wl_signal_add(&xsurface->events.associate, &xwayland_view->associate);
746 xwayland_view->unmap.notify = handle_unmap; 858 xwayland_view->associate.notify = handle_associate;
747 859
748 wl_signal_add(&xsurface->events.map, &xwayland_view->map); 860 wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate);
749 xwayland_view->map.notify = handle_map; 861 xwayland_view->dissociate.notify = handle_dissociate;
750 862
751 wl_signal_add(&xsurface->events.set_override_redirect, 863 wl_signal_add(&xsurface->events.set_override_redirect,
752 &xwayland_view->override_redirect); 864 &xwayland_view->override_redirect);