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.c297
1 files changed, 206 insertions, 91 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 66cb3b02..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,10 +83,13 @@ 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) {
@@ -121,18 +111,53 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
121 } 111 }
122} 112}
123 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
124static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { 147static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
125 struct sway_xwayland_unmanaged *surface = 148 struct sway_xwayland_unmanaged *surface =
126 wl_container_of(listener, surface, destroy); 149 wl_container_of(listener, surface, destroy);
127 wl_list_remove(&surface->request_configure.link); 150 wl_list_remove(&surface->request_configure.link);
128 wl_list_remove(&surface->map.link); 151 wl_list_remove(&surface->associate.link);
129 wl_list_remove(&surface->unmap.link); 152 wl_list_remove(&surface->dissociate.link);
130 wl_list_remove(&surface->destroy.link); 153 wl_list_remove(&surface->destroy.link);
131 wl_list_remove(&surface->override_redirect.link); 154 wl_list_remove(&surface->override_redirect.link);
155 wl_list_remove(&surface->request_activate.link);
132 free(surface); 156 free(surface);
133} 157}
134 158
135static 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);
136 161
137struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); 162struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);
138 163
@@ -141,14 +166,22 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
141 wl_container_of(listener, surface, override_redirect); 166 wl_container_of(listener, surface, override_redirect);
142 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 167 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
143 168
144 bool mapped = xsurface->mapped; 169 bool associated = xsurface->surface != NULL;
170 bool mapped = associated && xsurface->surface->mapped;
145 if (mapped) { 171 if (mapped) {
146 unmanaged_handle_unmap(&surface->unmap, NULL); 172 unmanaged_handle_unmap(&surface->unmap, NULL);
147 } 173 }
174 if (associated) {
175 unmanaged_handle_dissociate(&surface->dissociate, NULL);
176 }
148 177
149 unmanaged_handle_destroy(&surface->destroy, NULL); 178 unmanaged_handle_destroy(&surface->destroy, NULL);
150 xsurface->data = NULL; 179 xsurface->data = NULL;
180
151 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 }
152 if (mapped) { 185 if (mapped) {
153 handle_map(&xwayland_view->map, xsurface); 186 handle_map(&xwayland_view->map, xsurface);
154 } 187 }
@@ -168,14 +201,16 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
168 wl_signal_add(&xsurface->events.request_configure, 201 wl_signal_add(&xsurface->events.request_configure,
169 &surface->request_configure); 202 &surface->request_configure);
170 surface->request_configure.notify = unmanaged_handle_request_configure; 203 surface->request_configure.notify = unmanaged_handle_request_configure;
171 wl_signal_add(&xsurface->events.map, &surface->map); 204 wl_signal_add(&xsurface->events.associate, &surface->associate);
172 surface->map.notify = unmanaged_handle_map; 205 surface->associate.notify = unmanaged_handle_associate;
173 wl_signal_add(&xsurface->events.unmap, &surface->unmap); 206 wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
174 surface->unmap.notify = unmanaged_handle_unmap; 207 surface->dissociate.notify = unmanaged_handle_dissociate;
175 wl_signal_add(&xsurface->events.destroy, &surface->destroy); 208 wl_signal_add(&xsurface->events.destroy, &surface->destroy);
176 surface->destroy.notify = unmanaged_handle_destroy; 209 surface->destroy.notify = unmanaged_handle_destroy;
177 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); 210 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
178 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;
179 214
180 return surface; 215 return surface;
181} 216}
@@ -254,6 +289,7 @@ static void set_activated(struct sway_view *view, bool activated) {
254 } 289 }
255 290
256 wlr_xwayland_surface_activate(surface, activated); 291 wlr_xwayland_surface_activate(surface, activated);
292 wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
257} 293}
258 294
259static void set_tiled(struct sway_view *view, bool tiled) { 295static void set_tiled(struct sway_view *view, bool tiled) {
@@ -293,7 +329,7 @@ static bool wants_floating(struct sway_view *view) {
293 } 329 }
294 } 330 }
295 331
296 struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; 332 xcb_size_hints_t *size_hints = surface->size_hints;
297 if (size_hints != NULL && 333 if (size_hints != NULL &&
298 size_hints->min_width > 0 && size_hints->min_height > 0 && 334 size_hints->min_width > 0 && size_hints->min_height > 0 &&
299 (size_hints->max_width == size_hints->min_width || 335 (size_hints->max_width == size_hints->min_width ||
@@ -347,7 +383,7 @@ static void destroy(struct sway_view *view) {
347static void get_constraints(struct sway_view *view, double *min_width, 383static void get_constraints(struct sway_view *view, double *min_width,
348 double *max_width, double *min_height, double *max_height) { 384 double *max_width, double *min_height, double *max_height) {
349 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; 385 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
350 struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; 386 xcb_size_hints_t *size_hints = surface->size_hints;
351 387
352 if (size_hints == NULL) { 388 if (size_hints == NULL) {
353 *min_width = DBL_MIN; 389 *min_width = DBL_MIN;
@@ -377,17 +413,6 @@ static const struct sway_view_impl view_impl = {
377 .destroy = destroy, 413 .destroy = destroy,
378}; 414};
379 415
380static void get_geometry(struct sway_view *view, struct wlr_box *box) {
381 box->x = box->y = 0;
382 if (view->surface) {
383 box->width = view->surface->current.width;
384 box->height = view->surface->current.height;
385 } else {
386 box->width = 0;
387 box->height = 0;
388 }
389}
390
391static void handle_commit(struct wl_listener *listener, void *data) { 416static void handle_commit(struct wl_listener *listener, void *data) {
392 struct sway_xwayland_view *xwayland_view = 417 struct sway_xwayland_view *xwayland_view =
393 wl_container_of(listener, xwayland_view, commit); 418 wl_container_of(listener, xwayland_view, commit);
@@ -395,34 +420,38 @@ static void handle_commit(struct wl_listener *listener, void *data) {
395 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 420 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
396 struct wlr_surface_state *state = &xsurface->surface->current; 421 struct wlr_surface_state *state = &xsurface->surface->current;
397 422
398 struct wlr_box new_geo; 423 struct wlr_box new_geo = {0};
399 get_geometry(view, &new_geo); 424 new_geo.width = state->width;
425 new_geo.height = state->height;
426
400 bool new_size = new_geo.width != view->geometry.width || 427 bool new_size = new_geo.width != view->geometry.width ||
401 new_geo.height != view->geometry.height || 428 new_geo.height != view->geometry.height;
402 new_geo.x != view->geometry.x ||
403 new_geo.y != view->geometry.y;
404 429
405 if (new_size) { 430 if (new_size) {
406 // The client changed its surface size in this commit. For floating 431 // The client changed its surface size in this commit. For floating
407 // containers, we resize the container to match. For tiling containers, 432 // containers, we resize the container to match. For tiling containers,
408 // we only recenter the surface. 433 // we only recenter the surface.
409 desktop_damage_view(view);
410 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); 434 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
411 if (container_is_floating(view->container)) { 435 if (container_is_floating(view->container)) {
412 view_update_size(view); 436 view_update_size(view);
413 transaction_commit_dirty_client(); 437 transaction_commit_dirty_client();
414 } else {
415 view_center_surface(view);
416 } 438 }
417 desktop_damage_view(view); 439
440 view_center_and_clip_surface(view);
418 } 441 }
419 442
420 if (view->container->node.instruction) { 443 if (view->container->node.instruction) {
421 transaction_notify_view_ready_by_geometry(view, 444 bool successful = transaction_notify_view_ready_by_geometry(view,
422 xsurface->x, xsurface->y, state->width, state->height); 445 xsurface->x, xsurface->y, state->width, state->height);
423 }
424 446
425 view_damage_from(view); 447 // If we saved the view and this commit isn't what we're looking for
448 // that means the user will never actually see the buffers submitted to
449 // us here. Just send frame done events to these surfaces so they can
450 // commit another time for us.
451 if (view->saved_surface_tree && !successful) {
452 view_send_frame_done(view);
453 }
454 }
426} 455}
427 456
428static void handle_destroy(struct wl_listener *listener, void *data) { 457static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -435,6 +464,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
435 wl_list_remove(&xwayland_view->commit.link); 464 wl_list_remove(&xwayland_view->commit.link);
436 } 465 }
437 466
467 xwayland_view->view.wlr_xwayland_surface = NULL;
468
438 wl_list_remove(&xwayland_view->destroy.link); 469 wl_list_remove(&xwayland_view->destroy.link);
439 wl_list_remove(&xwayland_view->request_configure.link); 470 wl_list_remove(&xwayland_view->request_configure.link);
440 wl_list_remove(&xwayland_view->request_fullscreen.link); 471 wl_list_remove(&xwayland_view->request_fullscreen.link);
@@ -445,11 +476,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
445 wl_list_remove(&xwayland_view->set_title.link); 476 wl_list_remove(&xwayland_view->set_title.link);
446 wl_list_remove(&xwayland_view->set_class.link); 477 wl_list_remove(&xwayland_view->set_class.link);
447 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);
448 wl_list_remove(&xwayland_view->set_window_type.link); 480 wl_list_remove(&xwayland_view->set_window_type.link);
449 wl_list_remove(&xwayland_view->set_hints.link); 481 wl_list_remove(&xwayland_view->set_hints.link);
450 wl_list_remove(&xwayland_view->set_decorations.link); 482 wl_list_remove(&xwayland_view->set_decorations.link);
451 wl_list_remove(&xwayland_view->map.link); 483 wl_list_remove(&xwayland_view->associate.link);
452 wl_list_remove(&xwayland_view->unmap.link); 484 wl_list_remove(&xwayland_view->dissociate.link);
453 wl_list_remove(&xwayland_view->override_redirect.link); 485 wl_list_remove(&xwayland_view->override_redirect.link);
454 view_begin_destroy(&xwayland_view->view); 486 view_begin_destroy(&xwayland_view->view);
455} 487}
@@ -463,16 +495,28 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
463 return; 495 return;
464 } 496 }
465 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
466 view_unmap(view); 506 view_unmap(view);
507}
467 508
468 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;
469} 513}
470 514
471static void handle_map(struct wl_listener *listener, void *data) { 515static void handle_map(struct wl_listener *listener, void *data) {
472 struct sway_xwayland_view *xwayland_view = 516 struct sway_xwayland_view *xwayland_view =
473 wl_container_of(listener, xwayland_view, map); 517 wl_container_of(listener, xwayland_view, map);
474 struct wlr_xwayland_surface *xsurface = data;
475 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;
476 520
477 view->natural_width = xsurface->width; 521 view->natural_width = xsurface->width;
478 view->natural_height = xsurface->height; 522 view->natural_height = xsurface->height;
@@ -485,23 +529,42 @@ static void handle_map(struct wl_listener *listener, void *data) {
485 // Put it back into the tree 529 // Put it back into the tree
486 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false); 530 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false);
487 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
488 transaction_commit_dirty(); 541 transaction_commit_dirty();
489} 542}
490 543
544static void handle_dissociate(struct wl_listener *listener, void *data);
545
491static void handle_override_redirect(struct wl_listener *listener, void *data) { 546static void handle_override_redirect(struct wl_listener *listener, void *data) {
492 struct sway_xwayland_view *xwayland_view = 547 struct sway_xwayland_view *xwayland_view =
493 wl_container_of(listener, xwayland_view, override_redirect); 548 wl_container_of(listener, xwayland_view, override_redirect);
494 struct wlr_xwayland_surface *xsurface = data;
495 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;
496 551
497 bool mapped = xsurface->mapped; 552 bool associated = xsurface->surface != NULL;
553 bool mapped = associated && xsurface->surface->mapped;
498 if (mapped) { 554 if (mapped) {
499 handle_unmap(&xwayland_view->unmap, NULL); 555 handle_unmap(&xwayland_view->unmap, NULL);
500 } 556 }
557 if (associated) {
558 handle_dissociate(&xwayland_view->dissociate, NULL);
559 }
501 560
502 handle_destroy(&xwayland_view->destroy, view); 561 handle_destroy(&xwayland_view->destroy, view);
503 xsurface->data = NULL; 562 xsurface->data = NULL;
563
504 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 }
505 if (mapped) { 568 if (mapped) {
506 unmanaged_handle_map(&unmanaged->map, xsurface); 569 unmanaged_handle_map(&unmanaged->map, xsurface);
507 } 570 }
@@ -513,7 +576,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
513 struct wlr_xwayland_surface_configure_event *ev = data; 576 struct wlr_xwayland_surface_configure_event *ev = data;
514 struct sway_view *view = &xwayland_view->view; 577 struct sway_view *view = &xwayland_view->view;
515 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 578 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
516 if (!xsurface->mapped) { 579 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
517 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, 580 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y,
518 ev->width, ev->height); 581 ev->width, ev->height);
519 return; 582 return;
@@ -542,7 +605,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
542 wl_container_of(listener, xwayland_view, request_fullscreen); 605 wl_container_of(listener, xwayland_view, request_fullscreen);
543 struct sway_view *view = &xwayland_view->view; 606 struct sway_view *view = &xwayland_view->view;
544 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 607 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
545 if (!xsurface->mapped) { 608 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
546 return; 609 return;
547 } 610 }
548 container_set_fullscreen(view->container, xsurface->fullscreen); 611 container_set_fullscreen(view->container, xsurface->fullscreen);
@@ -556,7 +619,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) {
556 wl_container_of(listener, xwayland_view, request_minimize); 619 wl_container_of(listener, xwayland_view, request_minimize);
557 struct sway_view *view = &xwayland_view->view; 620 struct sway_view *view = &xwayland_view->view;
558 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 621 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
559 if (!xsurface->mapped) { 622 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
560 return; 623 return;
561 } 624 }
562 625
@@ -571,10 +634,11 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
571 wl_container_of(listener, xwayland_view, request_move); 634 wl_container_of(listener, xwayland_view, request_move);
572 struct sway_view *view = &xwayland_view->view; 635 struct sway_view *view = &xwayland_view->view;
573 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 636 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
574 if (!xsurface->mapped) { 637 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
575 return; 638 return;
576 } 639 }
577 if (!container_is_floating(view->container)) { 640 if (!container_is_floating(view->container) ||
641 view->container->pending.fullscreen_mode) {
578 return; 642 return;
579 } 643 }
580 struct sway_seat *seat = input_manager_current_seat(); 644 struct sway_seat *seat = input_manager_current_seat();
@@ -586,7 +650,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
586 wl_container_of(listener, xwayland_view, request_resize); 650 wl_container_of(listener, xwayland_view, request_resize);
587 struct sway_view *view = &xwayland_view->view; 651 struct sway_view *view = &xwayland_view->view;
588 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 652 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
589 if (!xsurface->mapped) { 653 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
590 return; 654 return;
591 } 655 }
592 if (!container_is_floating(view->container)) { 656 if (!container_is_floating(view->container)) {
@@ -602,10 +666,10 @@ static void handle_request_activate(struct wl_listener *listener, void *data) {
602 wl_container_of(listener, xwayland_view, request_activate); 666 wl_container_of(listener, xwayland_view, request_activate);
603 struct sway_view *view = &xwayland_view->view; 667 struct sway_view *view = &xwayland_view->view;
604 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 668 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
605 if (!xsurface->mapped) { 669 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
606 return; 670 return;
607 } 671 }
608 view_request_activate(view); 672 view_request_activate(view, NULL);
609 673
610 transaction_commit_dirty(); 674 transaction_commit_dirty();
611} 675}
@@ -615,7 +679,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
615 wl_container_of(listener, xwayland_view, set_title); 679 wl_container_of(listener, xwayland_view, set_title);
616 struct sway_view *view = &xwayland_view->view; 680 struct sway_view *view = &xwayland_view->view;
617 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 681 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
618 if (!xsurface->mapped) { 682 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
619 return; 683 return;
620 } 684 }
621 view_update_title(view, false); 685 view_update_title(view, false);
@@ -627,7 +691,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
627 wl_container_of(listener, xwayland_view, set_class); 691 wl_container_of(listener, xwayland_view, set_class);
628 struct sway_view *view = &xwayland_view->view; 692 struct sway_view *view = &xwayland_view->view;
629 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 693 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
630 if (!xsurface->mapped) { 694 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
631 return; 695 return;
632 } 696 }
633 view_execute_criteria(view); 697 view_execute_criteria(view);
@@ -638,18 +702,43 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
638 wl_container_of(listener, xwayland_view, set_role); 702 wl_container_of(listener, xwayland_view, set_role);
639 struct sway_view *view = &xwayland_view->view; 703 struct sway_view *view = &xwayland_view->view;
640 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 704 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
641 if (!xsurface->mapped) { 705 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
642 return; 706 return;
643 } 707 }
644 view_execute_criteria(view); 708 view_execute_criteria(view);
645} 709}
646 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
647static void handle_set_window_type(struct wl_listener *listener, void *data) { 736static void handle_set_window_type(struct wl_listener *listener, void *data) {
648 struct sway_xwayland_view *xwayland_view = 737 struct sway_xwayland_view *xwayland_view =
649 wl_container_of(listener, xwayland_view, set_window_type); 738 wl_container_of(listener, xwayland_view, set_window_type);
650 struct sway_view *view = &xwayland_view->view; 739 struct sway_view *view = &xwayland_view->view;
651 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 740 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
652 if (!xsurface->mapped) { 741 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
653 return; 742 return;
654 } 743 }
655 view_execute_criteria(view); 744 view_execute_criteria(view);
@@ -660,20 +749,39 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
660 wl_container_of(listener, xwayland_view, set_hints); 749 wl_container_of(listener, xwayland_view, set_hints);
661 struct sway_view *view = &xwayland_view->view; 750 struct sway_view *view = &xwayland_view->view;
662 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 751 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
663 if (!xsurface->mapped) { 752 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
664 return; 753 return;
665 } 754 }
666 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) {
667 // 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
668 // 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
669 // it. 759 // it.
670 return; 760 return;
671 } 761 }
672 if (view->allow_request_urgent) { 762 if (view->allow_request_urgent) {
673 view_set_urgent(view, (bool)xsurface->hints_urgency); 763 view_set_urgent(view, hints_urgency);
674 } 764 }
675} 765}
676 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
677struct sway_view *view_from_wlr_xwayland_surface( 785struct sway_view *view_from_wlr_xwayland_surface(
678 struct wlr_xwayland_surface *xsurface) { 786 struct wlr_xwayland_surface *xsurface) {
679 return xsurface->data; 787 return xsurface->data;
@@ -689,7 +797,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
689 return NULL; 797 return NULL;
690 } 798 }
691 799
692 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 }
693 xwayland_view->view.wlr_xwayland_surface = xsurface; 804 xwayland_view->view.wlr_xwayland_surface = xsurface;
694 805
695 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy); 806 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy);
@@ -728,6 +839,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
728 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role); 839 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role);
729 xwayland_view->set_role.notify = handle_set_role; 840 xwayland_view->set_role.notify = handle_set_role;
730 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
731 wl_signal_add(&xsurface->events.set_window_type, 846 wl_signal_add(&xsurface->events.set_window_type,
732 &xwayland_view->set_window_type); 847 &xwayland_view->set_window_type);
733 xwayland_view->set_window_type.notify = handle_set_window_type; 848 xwayland_view->set_window_type.notify = handle_set_window_type;
@@ -739,11 +854,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
739 &xwayland_view->set_decorations); 854 &xwayland_view->set_decorations);
740 xwayland_view->set_decorations.notify = handle_set_decorations; 855 xwayland_view->set_decorations.notify = handle_set_decorations;
741 856
742 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); 857 wl_signal_add(&xsurface->events.associate, &xwayland_view->associate);
743 xwayland_view->unmap.notify = handle_unmap; 858 xwayland_view->associate.notify = handle_associate;
744 859
745 wl_signal_add(&xsurface->events.map, &xwayland_view->map); 860 wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate);
746 xwayland_view->map.notify = handle_map; 861 xwayland_view->dissociate.notify = handle_dissociate;
747 862
748 wl_signal_add(&xsurface->events.set_override_redirect, 863 wl_signal_add(&xsurface->events.set_override_redirect,
749 &xwayland_view->override_redirect); 864 &xwayland_view->override_redirect);