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.c268
1 files changed, 180 insertions, 88 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 7c5dde53..270cf08f 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -1,21 +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>
9#include <xcb/xcb_icccm.h> 10#include <xcb/xcb_icccm.h>
10#include "log.h" 11#include "log.h"
11#include "sway/desktop.h"
12#include "sway/desktop/transaction.h" 12#include "sway/desktop/transaction.h"
13#include "sway/input/cursor.h" 13#include "sway/input/cursor.h"
14#include "sway/input/input-manager.h" 14#include "sway/input/input-manager.h"
15#include "sway/input/seat.h" 15#include "sway/input/seat.h"
16#include "sway/output.h" 16#include "sway/output.h"
17#include "sway/scene_descriptor.h"
17#include "sway/tree/arrange.h" 18#include "sway/tree/arrange.h"
18#include "sway/tree/container.h" 19#include "sway/tree/container.h"
20#include "sway/server.h"
19#include "sway/tree/view.h" 21#include "sway/tree/view.h"
20#include "sway/tree/workspace.h" 22#include "sway/tree/workspace.h"
21 23
@@ -43,29 +45,12 @@ static void unmanaged_handle_request_configure(struct wl_listener *listener,
43 ev->width, ev->height); 45 ev->width, ev->height);
44} 46}
45 47
46static void unmanaged_handle_commit(struct wl_listener *listener, void *data) {
47 struct sway_xwayland_unmanaged *surface =
48 wl_container_of(listener, surface, commit);
49 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
50
51 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
52 false);
53}
54
55static void unmanaged_handle_set_geometry(struct wl_listener *listener, void *data) { 48static void unmanaged_handle_set_geometry(struct wl_listener *listener, void *data) {
56 struct sway_xwayland_unmanaged *surface = 49 struct sway_xwayland_unmanaged *surface =
57 wl_container_of(listener, surface, set_geometry); 50 wl_container_of(listener, surface, set_geometry);
58 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 51 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
59 52
60 if (xsurface->x != surface->lx || xsurface->y != surface->ly) { 53 wlr_scene_node_set_position(&surface->surface_scene->buffer->node, xsurface->x, xsurface->y);
61 // Surface has moved
62 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
63 true);
64 surface->lx = xsurface->x;
65 surface->ly = xsurface->y;
66 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
67 true);
68 }
69} 54}
70 55
71static void unmanaged_handle_map(struct wl_listener *listener, void *data) { 56static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
@@ -73,17 +58,18 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
73 wl_container_of(listener, surface, map); 58 wl_container_of(listener, surface, map);
74 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 59 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
75 60
76 wl_list_insert(root->xwayland_unmanaged.prev, &surface->link); 61 surface->surface_scene = wlr_scene_surface_create(root->layers.unmanaged,
62 xsurface->surface);
77 63
78 wl_signal_add(&xsurface->events.set_geometry, &surface->set_geometry); 64 if (surface->surface_scene) {
79 surface->set_geometry.notify = unmanaged_handle_set_geometry; 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);
80 69
81 wl_signal_add(&xsurface->surface->events.commit, &surface->commit); 70 wl_signal_add(&xsurface->events.set_geometry, &surface->set_geometry);
82 surface->commit.notify = unmanaged_handle_commit; 71 surface->set_geometry.notify = unmanaged_handle_set_geometry;
83 72 }
84 surface->lx = xsurface->x;
85 surface->ly = xsurface->y;
86 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true);
87 73
88 if (wlr_xwayland_or_surface_wants_focus(xsurface)) { 74 if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
89 struct sway_seat *seat = input_manager_current_seat(); 75 struct sway_seat *seat = input_manager_current_seat();
@@ -97,10 +83,13 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
97 struct sway_xwayland_unmanaged *surface = 83 struct sway_xwayland_unmanaged *surface =
98 wl_container_of(listener, surface, unmap); 84 wl_container_of(listener, surface, unmap);
99 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 85 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
100 desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, true); 86
101 wl_list_remove(&surface->link); 87 if (surface->surface_scene) {
102 wl_list_remove(&surface->set_geometry.link); 88 wl_list_remove(&surface->set_geometry.link);
103 wl_list_remove(&surface->commit.link); 89
90 wlr_scene_node_destroy(&surface->surface_scene->buffer->node);
91 surface->surface_scene = NULL;
92 }
104 93
105 struct sway_seat *seat = input_manager_current_seat(); 94 struct sway_seat *seat = input_manager_current_seat();
106 if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { 95 if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) {
@@ -123,8 +112,10 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
123} 112}
124 113
125static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) { 114static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) {
126 struct wlr_xwayland_surface *xsurface = data; 115 struct sway_xwayland_unmanaged *surface =
127 if (!xsurface->mapped) { 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) {
128 return; 119 return;
129 } 120 }
130 struct sway_seat *seat = input_manager_current_seat(); 121 struct sway_seat *seat = input_manager_current_seat();
@@ -136,12 +127,29 @@ static void unmanaged_handle_request_activate(struct wl_listener *listener, void
136 seat_set_focus_surface(seat, xsurface->surface, false); 127 seat_set_focus_surface(seat, xsurface->surface, false);
137} 128}
138 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
139static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { 147static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
140 struct sway_xwayland_unmanaged *surface = 148 struct sway_xwayland_unmanaged *surface =
141 wl_container_of(listener, surface, destroy); 149 wl_container_of(listener, surface, destroy);
142 wl_list_remove(&surface->request_configure.link); 150 wl_list_remove(&surface->request_configure.link);
143 wl_list_remove(&surface->map.link); 151 wl_list_remove(&surface->associate.link);
144 wl_list_remove(&surface->unmap.link); 152 wl_list_remove(&surface->dissociate.link);
145 wl_list_remove(&surface->destroy.link); 153 wl_list_remove(&surface->destroy.link);
146 wl_list_remove(&surface->override_redirect.link); 154 wl_list_remove(&surface->override_redirect.link);
147 wl_list_remove(&surface->request_activate.link); 155 wl_list_remove(&surface->request_activate.link);
@@ -149,6 +157,7 @@ static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
149} 157}
150 158
151static 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);
152 161
153struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); 162struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);
154 163
@@ -157,14 +166,22 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
157 wl_container_of(listener, surface, override_redirect); 166 wl_container_of(listener, surface, override_redirect);
158 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; 167 struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
159 168
160 bool mapped = xsurface->mapped; 169 bool associated = xsurface->surface != NULL;
170 bool mapped = associated && xsurface->surface->mapped;
161 if (mapped) { 171 if (mapped) {
162 unmanaged_handle_unmap(&surface->unmap, NULL); 172 unmanaged_handle_unmap(&surface->unmap, NULL);
163 } 173 }
174 if (associated) {
175 unmanaged_handle_dissociate(&surface->dissociate, NULL);
176 }
164 177
165 unmanaged_handle_destroy(&surface->destroy, NULL); 178 unmanaged_handle_destroy(&surface->destroy, NULL);
166 xsurface->data = NULL; 179 xsurface->data = NULL;
180
167 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 }
168 if (mapped) { 185 if (mapped) {
169 handle_map(&xwayland_view->map, xsurface); 186 handle_map(&xwayland_view->map, xsurface);
170 } 187 }
@@ -184,10 +201,10 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
184 wl_signal_add(&xsurface->events.request_configure, 201 wl_signal_add(&xsurface->events.request_configure,
185 &surface->request_configure); 202 &surface->request_configure);
186 surface->request_configure.notify = unmanaged_handle_request_configure; 203 surface->request_configure.notify = unmanaged_handle_request_configure;
187 wl_signal_add(&xsurface->events.map, &surface->map); 204 wl_signal_add(&xsurface->events.associate, &surface->associate);
188 surface->map.notify = unmanaged_handle_map; 205 surface->associate.notify = unmanaged_handle_associate;
189 wl_signal_add(&xsurface->events.unmap, &surface->unmap); 206 wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
190 surface->unmap.notify = unmanaged_handle_unmap; 207 surface->dissociate.notify = unmanaged_handle_dissociate;
191 wl_signal_add(&xsurface->events.destroy, &surface->destroy); 208 wl_signal_add(&xsurface->events.destroy, &surface->destroy);
192 surface->destroy.notify = unmanaged_handle_destroy; 209 surface->destroy.notify = unmanaged_handle_destroy;
193 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); 210 wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
@@ -396,17 +413,6 @@ static const struct sway_view_impl view_impl = {
396 .destroy = destroy, 413 .destroy = destroy,
397}; 414};
398 415
399static void get_geometry(struct sway_view *view, struct wlr_box *box) {
400 box->x = box->y = 0;
401 if (view->surface) {
402 box->width = view->surface->current.width;
403 box->height = view->surface->current.height;
404 } else {
405 box->width = 0;
406 box->height = 0;
407 }
408}
409
410static void handle_commit(struct wl_listener *listener, void *data) { 416static void handle_commit(struct wl_listener *listener, void *data) {
411 struct sway_xwayland_view *xwayland_view = 417 struct sway_xwayland_view *xwayland_view =
412 wl_container_of(listener, xwayland_view, commit); 418 wl_container_of(listener, xwayland_view, commit);
@@ -414,34 +420,38 @@ static void handle_commit(struct wl_listener *listener, void *data) {
414 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 420 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
415 struct wlr_surface_state *state = &xsurface->surface->current; 421 struct wlr_surface_state *state = &xsurface->surface->current;
416 422
417 struct wlr_box new_geo; 423 struct wlr_box new_geo = {0};
418 get_geometry(view, &new_geo); 424 new_geo.width = state->width;
425 new_geo.height = state->height;
426
419 bool new_size = new_geo.width != view->geometry.width || 427 bool new_size = new_geo.width != view->geometry.width ||
420 new_geo.height != view->geometry.height || 428 new_geo.height != view->geometry.height;
421 new_geo.x != view->geometry.x ||
422 new_geo.y != view->geometry.y;
423 429
424 if (new_size) { 430 if (new_size) {
425 // The client changed its surface size in this commit. For floating 431 // The client changed its surface size in this commit. For floating
426 // containers, we resize the container to match. For tiling containers, 432 // containers, we resize the container to match. For tiling containers,
427 // we only recenter the surface. 433 // we only recenter the surface.
428 desktop_damage_view(view);
429 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); 434 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
430 if (container_is_floating(view->container)) { 435 if (container_is_floating(view->container)) {
431 view_update_size(view); 436 view_update_size(view);
432 transaction_commit_dirty_client(); 437 transaction_commit_dirty_client();
433 } else {
434 view_center_surface(view);
435 } 438 }
436 desktop_damage_view(view); 439
440 view_center_and_clip_surface(view);
437 } 441 }
438 442
439 if (view->container->node.instruction) { 443 if (view->container->node.instruction) {
440 transaction_notify_view_ready_by_geometry(view, 444 bool successful = transaction_notify_view_ready_by_geometry(view,
441 xsurface->x, xsurface->y, state->width, state->height); 445 xsurface->x, xsurface->y, state->width, state->height);
442 }
443 446
444 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 }
445} 455}
446 456
447static void handle_destroy(struct wl_listener *listener, void *data) { 457static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -466,11 +476,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
466 wl_list_remove(&xwayland_view->set_title.link); 476 wl_list_remove(&xwayland_view->set_title.link);
467 wl_list_remove(&xwayland_view->set_class.link); 477 wl_list_remove(&xwayland_view->set_class.link);
468 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);
469 wl_list_remove(&xwayland_view->set_window_type.link); 480 wl_list_remove(&xwayland_view->set_window_type.link);
470 wl_list_remove(&xwayland_view->set_hints.link); 481 wl_list_remove(&xwayland_view->set_hints.link);
471 wl_list_remove(&xwayland_view->set_decorations.link); 482 wl_list_remove(&xwayland_view->set_decorations.link);
472 wl_list_remove(&xwayland_view->map.link); 483 wl_list_remove(&xwayland_view->associate.link);
473 wl_list_remove(&xwayland_view->unmap.link); 484 wl_list_remove(&xwayland_view->dissociate.link);
474 wl_list_remove(&xwayland_view->override_redirect.link); 485 wl_list_remove(&xwayland_view->override_redirect.link);
475 view_begin_destroy(&xwayland_view->view); 486 view_begin_destroy(&xwayland_view->view);
476} 487}
@@ -484,16 +495,28 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
484 return; 495 return;
485 } 496 }
486 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
487 view_unmap(view); 506 view_unmap(view);
507}
488 508
489 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;
490} 513}
491 514
492static void handle_map(struct wl_listener *listener, void *data) { 515static void handle_map(struct wl_listener *listener, void *data) {
493 struct sway_xwayland_view *xwayland_view = 516 struct sway_xwayland_view *xwayland_view =
494 wl_container_of(listener, xwayland_view, map); 517 wl_container_of(listener, xwayland_view, map);
495 struct wlr_xwayland_surface *xsurface = data;
496 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;
497 520
498 view->natural_width = xsurface->width; 521 view->natural_width = xsurface->width;
499 view->natural_height = xsurface->height; 522 view->natural_height = xsurface->height;
@@ -506,23 +529,42 @@ static void handle_map(struct wl_listener *listener, void *data) {
506 // Put it back into the tree 529 // Put it back into the tree
507 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false); 530 view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false);
508 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
509 transaction_commit_dirty(); 541 transaction_commit_dirty();
510} 542}
511 543
544static void handle_dissociate(struct wl_listener *listener, void *data);
545
512static void handle_override_redirect(struct wl_listener *listener, void *data) { 546static void handle_override_redirect(struct wl_listener *listener, void *data) {
513 struct sway_xwayland_view *xwayland_view = 547 struct sway_xwayland_view *xwayland_view =
514 wl_container_of(listener, xwayland_view, override_redirect); 548 wl_container_of(listener, xwayland_view, override_redirect);
515 struct wlr_xwayland_surface *xsurface = data;
516 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;
517 551
518 bool mapped = xsurface->mapped; 552 bool associated = xsurface->surface != NULL;
553 bool mapped = associated && xsurface->surface->mapped;
519 if (mapped) { 554 if (mapped) {
520 handle_unmap(&xwayland_view->unmap, NULL); 555 handle_unmap(&xwayland_view->unmap, NULL);
521 } 556 }
557 if (associated) {
558 handle_dissociate(&xwayland_view->dissociate, NULL);
559 }
522 560
523 handle_destroy(&xwayland_view->destroy, view); 561 handle_destroy(&xwayland_view->destroy, view);
524 xsurface->data = NULL; 562 xsurface->data = NULL;
563
525 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 }
526 if (mapped) { 568 if (mapped) {
527 unmanaged_handle_map(&unmanaged->map, xsurface); 569 unmanaged_handle_map(&unmanaged->map, xsurface);
528 } 570 }
@@ -534,7 +576,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
534 struct wlr_xwayland_surface_configure_event *ev = data; 576 struct wlr_xwayland_surface_configure_event *ev = data;
535 struct sway_view *view = &xwayland_view->view; 577 struct sway_view *view = &xwayland_view->view;
536 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 578 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
537 if (!xsurface->mapped) { 579 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
538 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, 580 wlr_xwayland_surface_configure(xsurface, ev->x, ev->y,
539 ev->width, ev->height); 581 ev->width, ev->height);
540 return; 582 return;
@@ -563,7 +605,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
563 wl_container_of(listener, xwayland_view, request_fullscreen); 605 wl_container_of(listener, xwayland_view, request_fullscreen);
564 struct sway_view *view = &xwayland_view->view; 606 struct sway_view *view = &xwayland_view->view;
565 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 607 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
566 if (!xsurface->mapped) { 608 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
567 return; 609 return;
568 } 610 }
569 container_set_fullscreen(view->container, xsurface->fullscreen); 611 container_set_fullscreen(view->container, xsurface->fullscreen);
@@ -577,7 +619,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) {
577 wl_container_of(listener, xwayland_view, request_minimize); 619 wl_container_of(listener, xwayland_view, request_minimize);
578 struct sway_view *view = &xwayland_view->view; 620 struct sway_view *view = &xwayland_view->view;
579 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 621 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
580 if (!xsurface->mapped) { 622 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
581 return; 623 return;
582 } 624 }
583 625
@@ -592,7 +634,7 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
592 wl_container_of(listener, xwayland_view, request_move); 634 wl_container_of(listener, xwayland_view, request_move);
593 struct sway_view *view = &xwayland_view->view; 635 struct sway_view *view = &xwayland_view->view;
594 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 636 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
595 if (!xsurface->mapped) { 637 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
596 return; 638 return;
597 } 639 }
598 if (!container_is_floating(view->container) || 640 if (!container_is_floating(view->container) ||
@@ -608,7 +650,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
608 wl_container_of(listener, xwayland_view, request_resize); 650 wl_container_of(listener, xwayland_view, request_resize);
609 struct sway_view *view = &xwayland_view->view; 651 struct sway_view *view = &xwayland_view->view;
610 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 652 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
611 if (!xsurface->mapped) { 653 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
612 return; 654 return;
613 } 655 }
614 if (!container_is_floating(view->container)) { 656 if (!container_is_floating(view->container)) {
@@ -624,10 +666,10 @@ static void handle_request_activate(struct wl_listener *listener, void *data) {
624 wl_container_of(listener, xwayland_view, request_activate); 666 wl_container_of(listener, xwayland_view, request_activate);
625 struct sway_view *view = &xwayland_view->view; 667 struct sway_view *view = &xwayland_view->view;
626 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 668 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
627 if (!xsurface->mapped) { 669 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
628 return; 670 return;
629 } 671 }
630 view_request_activate(view); 672 view_request_activate(view, NULL);
631 673
632 transaction_commit_dirty(); 674 transaction_commit_dirty();
633} 675}
@@ -637,7 +679,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
637 wl_container_of(listener, xwayland_view, set_title); 679 wl_container_of(listener, xwayland_view, set_title);
638 struct sway_view *view = &xwayland_view->view; 680 struct sway_view *view = &xwayland_view->view;
639 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 681 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
640 if (!xsurface->mapped) { 682 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
641 return; 683 return;
642 } 684 }
643 view_update_title(view, false); 685 view_update_title(view, false);
@@ -649,7 +691,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
649 wl_container_of(listener, xwayland_view, set_class); 691 wl_container_of(listener, xwayland_view, set_class);
650 struct sway_view *view = &xwayland_view->view; 692 struct sway_view *view = &xwayland_view->view;
651 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 693 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
652 if (!xsurface->mapped) { 694 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
653 return; 695 return;
654 } 696 }
655 view_execute_criteria(view); 697 view_execute_criteria(view);
@@ -660,18 +702,43 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
660 wl_container_of(listener, xwayland_view, set_role); 702 wl_container_of(listener, xwayland_view, set_role);
661 struct sway_view *view = &xwayland_view->view; 703 struct sway_view *view = &xwayland_view->view;
662 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 704 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
663 if (!xsurface->mapped) { 705 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
664 return; 706 return;
665 } 707 }
666 view_execute_criteria(view); 708 view_execute_criteria(view);
667} 709}
668 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
669static void handle_set_window_type(struct wl_listener *listener, void *data) { 736static void handle_set_window_type(struct wl_listener *listener, void *data) {
670 struct sway_xwayland_view *xwayland_view = 737 struct sway_xwayland_view *xwayland_view =
671 wl_container_of(listener, xwayland_view, set_window_type); 738 wl_container_of(listener, xwayland_view, set_window_type);
672 struct sway_view *view = &xwayland_view->view; 739 struct sway_view *view = &xwayland_view->view;
673 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 740 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
674 if (!xsurface->mapped) { 741 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
675 return; 742 return;
676 } 743 }
677 view_execute_criteria(view); 744 view_execute_criteria(view);
@@ -682,7 +749,7 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
682 wl_container_of(listener, xwayland_view, set_hints); 749 wl_container_of(listener, xwayland_view, set_hints);
683 struct sway_view *view = &xwayland_view->view; 750 struct sway_view *view = &xwayland_view->view;
684 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 751 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
685 if (!xsurface->mapped) { 752 if (xsurface->surface == NULL || !xsurface->surface->mapped) {
686 return; 753 return;
687 } 754 }
688 const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints); 755 const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints);
@@ -697,6 +764,24 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
697 } 764 }
698} 765}
699 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
700struct sway_view *view_from_wlr_xwayland_surface( 785struct sway_view *view_from_wlr_xwayland_surface(
701 struct wlr_xwayland_surface *xsurface) { 786 struct wlr_xwayland_surface *xsurface) {
702 return xsurface->data; 787 return xsurface->data;
@@ -712,7 +797,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
712 return NULL; 797 return NULL;
713 } 798 }
714 799
715 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 }
716 xwayland_view->view.wlr_xwayland_surface = xsurface; 804 xwayland_view->view.wlr_xwayland_surface = xsurface;
717 805
718 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy); 806 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy);
@@ -751,6 +839,10 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
751 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role); 839 wl_signal_add(&xsurface->events.set_role, &xwayland_view->set_role);
752 xwayland_view->set_role.notify = handle_set_role; 840 xwayland_view->set_role.notify = handle_set_role;
753 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
754 wl_signal_add(&xsurface->events.set_window_type, 846 wl_signal_add(&xsurface->events.set_window_type,
755 &xwayland_view->set_window_type); 847 &xwayland_view->set_window_type);
756 xwayland_view->set_window_type.notify = handle_set_window_type; 848 xwayland_view->set_window_type.notify = handle_set_window_type;
@@ -762,11 +854,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
762 &xwayland_view->set_decorations); 854 &xwayland_view->set_decorations);
763 xwayland_view->set_decorations.notify = handle_set_decorations; 855 xwayland_view->set_decorations.notify = handle_set_decorations;
764 856
765 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); 857 wl_signal_add(&xsurface->events.associate, &xwayland_view->associate);
766 xwayland_view->unmap.notify = handle_unmap; 858 xwayland_view->associate.notify = handle_associate;
767 859
768 wl_signal_add(&xsurface->events.map, &xwayland_view->map); 860 wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate);
769 xwayland_view->map.notify = handle_map; 861 xwayland_view->dissociate.notify = handle_dissociate;
770 862
771 wl_signal_add(&xsurface->events.set_override_redirect, 863 wl_signal_add(&xsurface->events.set_override_redirect,
772 &xwayland_view->override_redirect); 864 &xwayland_view->override_redirect);