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