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.c189
1 files changed, 134 insertions, 55 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index b3b1473d..65d4fcd4 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -69,16 +69,11 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
69 surface->ly = xsurface->y; 69 surface->ly = xsurface->y;
70 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true); 70 desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true);
71 71
72 if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { 72 struct sway_seat *seat = input_manager_current_seat(input_manager);
73 struct sway_seat *seat = input_manager_current_seat(input_manager); 73 struct wlr_xwayland *xwayland =
74 struct wlr_xwayland *xwayland = 74 seat->input->server->xwayland.wlr_xwayland;
75 seat->input->server->xwayland.wlr_xwayland; 75 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
76 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 76 seat_set_focus_surface(seat, xsurface->surface, false);
77 seat_set_focus_surface(seat, xsurface->surface);
78 }
79
80 // TODO: we don't send surface enter/leave events to xwayland unmanaged
81 // surfaces, but xwayland doesn't support HiDPI anyway
82} 77}
83 78
84static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { 79static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
@@ -89,18 +84,16 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
89 wl_list_remove(&surface->link); 84 wl_list_remove(&surface->link);
90 wl_list_remove(&surface->commit.link); 85 wl_list_remove(&surface->commit.link);
91 86
92 if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { 87 struct sway_seat *seat = input_manager_current_seat(input_manager);
93 struct sway_seat *seat = input_manager_current_seat(input_manager); 88 if (seat->wlr_seat->keyboard_state.focused_surface ==
94 if (seat->wlr_seat->keyboard_state.focused_surface == 89 xsurface->surface) {
95 xsurface->surface) { 90 // Restore focus
96 // Restore focus 91 struct sway_container *previous =
97 struct sway_container *previous = 92 seat_get_focus_inactive(seat, &root_container);
98 seat_get_focus_inactive(seat, &root_container); 93 if (previous) {
99 if (previous) { 94 // Hack to get seat to re-focus the return value of get_focus
100 // Hack to get seat to re-focus the return value of get_focus 95 seat_set_focus(seat, previous->parent);
101 seat_set_focus(seat, previous->parent); 96 seat_set_focus(seat, previous);
102 seat_set_focus(seat, previous);
103 }
104 } 97 }
105 } 98 }
106} 99}
@@ -119,7 +112,7 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
119 struct sway_xwayland_unmanaged *surface = 112 struct sway_xwayland_unmanaged *surface =
120 calloc(1, sizeof(struct sway_xwayland_unmanaged)); 113 calloc(1, sizeof(struct sway_xwayland_unmanaged));
121 if (surface == NULL) { 114 if (surface == NULL) {
122 wlr_log(L_ERROR, "Allocation failed"); 115 wlr_log(WLR_ERROR, "Allocation failed");
123 return NULL; 116 return NULL;
124 } 117 }
125 118
@@ -246,6 +239,14 @@ static bool wants_floating(struct sway_view *view) {
246 return false; 239 return false;
247} 240}
248 241
242static bool has_client_side_decorations(struct sway_view *view) {
243 if (xwayland_view_from_view(view) == NULL) {
244 return false;
245 }
246 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
247 return surface->decorations != WLR_XWAYLAND_SURFACE_DECORATIONS_ALL;
248}
249
249static void _close(struct sway_view *view) { 250static void _close(struct sway_view *view) {
250 if (xwayland_view_from_view(view) == NULL) { 251 if (xwayland_view_from_view(view) == NULL) {
251 return; 252 return;
@@ -269,6 +270,7 @@ static const struct sway_view_impl view_impl = {
269 .set_tiled = set_tiled, 270 .set_tiled = set_tiled,
270 .set_fullscreen = set_fullscreen, 271 .set_fullscreen = set_fullscreen,
271 .wants_floating = wants_floating, 272 .wants_floating = wants_floating,
273 .has_client_side_decorations = has_client_side_decorations,
272 .close = _close, 274 .close = _close,
273 .destroy = destroy, 275 .destroy = destroy,
274}; 276};
@@ -278,15 +280,42 @@ static void handle_commit(struct wl_listener *listener, void *data) {
278 wl_container_of(listener, xwayland_view, commit); 280 wl_container_of(listener, xwayland_view, commit);
279 struct sway_view *view = &xwayland_view->view; 281 struct sway_view *view = &xwayland_view->view;
280 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 282 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
281 struct wlr_surface_state *surface_state = xsurface->surface->current; 283 struct wlr_surface_state *surface_state = &xsurface->surface->current;
282 284
283 if (view->swayc->instructions->length) { 285 if (view->swayc->instructions->length) {
284 transaction_notify_view_ready_by_size(view, 286 transaction_notify_view_ready_by_size(view,
285 surface_state->width, surface_state->height); 287 surface_state->width, surface_state->height);
288 } else if (container_is_floating(view->swayc)) {
289 view_update_size(view, surface_state->width, surface_state->height);
286 } 290 }
291
287 view_damage_from(view); 292 view_damage_from(view);
288} 293}
289 294
295static void handle_destroy(struct wl_listener *listener, void *data) {
296 struct sway_xwayland_view *xwayland_view =
297 wl_container_of(listener, xwayland_view, destroy);
298 struct sway_view *view = &xwayland_view->view;
299
300 if (view->surface) {
301 view_unmap(view);
302 wl_list_remove(&xwayland_view->commit.link);
303 }
304
305 wl_list_remove(&xwayland_view->destroy.link);
306 wl_list_remove(&xwayland_view->request_configure.link);
307 wl_list_remove(&xwayland_view->request_fullscreen.link);
308 wl_list_remove(&xwayland_view->request_move.link);
309 wl_list_remove(&xwayland_view->request_resize.link);
310 wl_list_remove(&xwayland_view->set_title.link);
311 wl_list_remove(&xwayland_view->set_class.link);
312 wl_list_remove(&xwayland_view->set_window_type.link);
313 wl_list_remove(&xwayland_view->set_hints.link);
314 wl_list_remove(&xwayland_view->map.link);
315 wl_list_remove(&xwayland_view->unmap.link);
316 view_destroy(&xwayland_view->view);
317}
318
290static void handle_unmap(struct wl_listener *listener, void *data) { 319static void handle_unmap(struct wl_listener *listener, void *data) {
291 struct sway_xwayland_view *xwayland_view = 320 struct sway_xwayland_view *xwayland_view =
292 wl_container_of(listener, xwayland_view, unmap); 321 wl_container_of(listener, xwayland_view, unmap);
@@ -307,6 +336,15 @@ static void handle_map(struct wl_listener *listener, void *data) {
307 struct wlr_xwayland_surface *xsurface = data; 336 struct wlr_xwayland_surface *xsurface = data;
308 struct sway_view *view = &xwayland_view->view; 337 struct sway_view *view = &xwayland_view->view;
309 338
339 if (xsurface->override_redirect) {
340 // This window used not to have the override redirect flag and has it
341 // now. Switch to unmanaged.
342 handle_destroy(&xwayland_view->destroy, view);
343 struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
344 unmanaged_handle_map(&unmanaged->map, xsurface);
345 return;
346 }
347
310 view->natural_width = xsurface->width; 348 view->natural_width = xsurface->width;
311 view->natural_height = xsurface->height; 349 view->natural_height = xsurface->height;
312 350
@@ -321,31 +359,11 @@ static void handle_map(struct wl_listener *listener, void *data) {
321 if (xsurface->fullscreen) { 359 if (xsurface->fullscreen) {
322 view_set_fullscreen(view, true); 360 view_set_fullscreen(view, true);
323 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 361 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
324 arrange_and_commit(ws); 362 arrange_windows(ws);
325 } else { 363 } else {
326 arrange_and_commit(view->swayc->parent); 364 arrange_windows(view->swayc->parent);
327 }
328}
329
330static void handle_destroy(struct wl_listener *listener, void *data) {
331 struct sway_xwayland_view *xwayland_view =
332 wl_container_of(listener, xwayland_view, destroy);
333 struct sway_view *view = &xwayland_view->view;
334
335 if (view->surface) {
336 view_unmap(view);
337 wl_list_remove(&xwayland_view->commit.link);
338 } 365 }
339 366 transaction_commit_dirty();
340 wl_list_remove(&xwayland_view->destroy.link);
341 wl_list_remove(&xwayland_view->request_configure.link);
342 wl_list_remove(&xwayland_view->request_fullscreen.link);
343 wl_list_remove(&xwayland_view->set_title.link);
344 wl_list_remove(&xwayland_view->set_class.link);
345 wl_list_remove(&xwayland_view->set_window_type.link);
346 wl_list_remove(&xwayland_view->map.link);
347 wl_list_remove(&xwayland_view->unmap.link);
348 view_destroy(&xwayland_view->view);
349} 367}
350 368
351static void handle_request_configure(struct wl_listener *listener, void *data) { 369static void handle_request_configure(struct wl_listener *listener, void *data) {
@@ -379,8 +397,40 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
379 } 397 }
380 view_set_fullscreen(view, xsurface->fullscreen); 398 view_set_fullscreen(view, xsurface->fullscreen);
381 399
382 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 400 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
383 arrange_and_commit(ws); 401 arrange_windows(output);
402 transaction_commit_dirty();
403}
404
405static void handle_request_move(struct wl_listener *listener, void *data) {
406 struct sway_xwayland_view *xwayland_view =
407 wl_container_of(listener, xwayland_view, request_move);
408 struct sway_view *view = &xwayland_view->view;
409 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
410 if (!xsurface->mapped) {
411 return;
412 }
413 if (!container_is_floating(view->swayc)) {
414 return;
415 }
416 struct sway_seat *seat = input_manager_current_seat(input_manager);
417 seat_begin_move(seat, view->swayc, seat->last_button);
418}
419
420static void handle_request_resize(struct wl_listener *listener, void *data) {
421 struct sway_xwayland_view *xwayland_view =
422 wl_container_of(listener, xwayland_view, request_resize);
423 struct sway_view *view = &xwayland_view->view;
424 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
425 if (!xsurface->mapped) {
426 return;
427 }
428 if (!container_is_floating(view->swayc)) {
429 return;
430 }
431 struct wlr_xwayland_resize_event *e = data;
432 struct sway_seat *seat = input_manager_current_seat(input_manager);
433 seat_begin_resize(seat, view->swayc, seat->last_button, e->edges);
384} 434}
385 435
386static void handle_set_title(struct wl_listener *listener, void *data) { 436static void handle_set_title(struct wl_listener *listener, void *data) {
@@ -417,6 +467,25 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) {
417 view_execute_criteria(view); 467 view_execute_criteria(view);
418} 468}
419 469
470static void handle_set_hints(struct wl_listener *listener, void *data) {
471 struct sway_xwayland_view *xwayland_view =
472 wl_container_of(listener, xwayland_view, set_hints);
473 struct sway_view *view = &xwayland_view->view;
474 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
475 if (!xsurface->mapped) {
476 return;
477 }
478 if (!xsurface->hints_urgency && view->urgent_timer) {
479 // The view is is in the timeout period. We'll ignore the request to
480 // unset urgency so that the view remains urgent until the timer clears
481 // it.
482 return;
483 }
484 if (view->allow_request_urgent) {
485 view_set_urgent(view, (bool)xsurface->hints_urgency);
486 }
487}
488
420struct sway_view *view_from_wlr_xwayland_surface( 489struct sway_view *view_from_wlr_xwayland_surface(
421 struct wlr_xwayland_surface *xsurface) { 490 struct wlr_xwayland_surface *xsurface) {
422 return xsurface->data; 491 return xsurface->data;
@@ -427,14 +496,13 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
427 xwayland_surface); 496 xwayland_surface);
428 struct wlr_xwayland_surface *xsurface = data; 497 struct wlr_xwayland_surface *xsurface = data;
429 498
430 if (wlr_xwayland_surface_is_unmanaged(xsurface) || 499 if (xsurface->override_redirect) {
431 xsurface->override_redirect) { 500 wlr_log(WLR_DEBUG, "New xwayland unmanaged surface");
432 wlr_log(L_DEBUG, "New xwayland unmanaged surface");
433 create_unmanaged(xsurface); 501 create_unmanaged(xsurface);
434 return; 502 return;
435 } 503 }
436 504
437 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", 505 wlr_log(WLR_DEBUG, "New xwayland surface title='%s' class='%s'",
438 xsurface->title, xsurface->class); 506 xsurface->title, xsurface->class);
439 507
440 struct sway_xwayland_view *xwayland_view = 508 struct sway_xwayland_view *xwayland_view =
@@ -457,6 +525,14 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
457 &xwayland_view->request_fullscreen); 525 &xwayland_view->request_fullscreen);
458 xwayland_view->request_fullscreen.notify = handle_request_fullscreen; 526 xwayland_view->request_fullscreen.notify = handle_request_fullscreen;
459 527
528 wl_signal_add(&xsurface->events.request_move,
529 &xwayland_view->request_move);
530 xwayland_view->request_move.notify = handle_request_move;
531
532 wl_signal_add(&xsurface->events.request_resize,
533 &xwayland_view->request_resize);
534 xwayland_view->request_resize.notify = handle_request_resize;
535
460 wl_signal_add(&xsurface->events.set_title, &xwayland_view->set_title); 536 wl_signal_add(&xsurface->events.set_title, &xwayland_view->set_title);
461 xwayland_view->set_title.notify = handle_set_title; 537 xwayland_view->set_title.notify = handle_set_title;
462 538
@@ -467,6 +543,9 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
467 &xwayland_view->set_window_type); 543 &xwayland_view->set_window_type);
468 xwayland_view->set_window_type.notify = handle_set_window_type; 544 xwayland_view->set_window_type.notify = handle_set_window_type;
469 545
546 wl_signal_add(&xsurface->events.set_hints, &xwayland_view->set_hints);
547 xwayland_view->set_hints.notify = handle_set_hints;
548
470 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); 549 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap);
471 xwayland_view->unmap.notify = handle_unmap; 550 xwayland_view->unmap.notify = handle_unmap;
472 551
@@ -484,7 +563,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) {
484 xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); 563 xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL);
485 int err = xcb_connection_has_error(xcb_conn); 564 int err = xcb_connection_has_error(xcb_conn);
486 if (err) { 565 if (err) {
487 wlr_log(L_ERROR, "XCB connect failed: %d", err); 566 wlr_log(WLR_ERROR, "XCB connect failed: %d", err);
488 return; 567 return;
489 } 568 }
490 569
@@ -503,7 +582,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) {
503 free(reply); 582 free(reply);
504 583
505 if (error != NULL) { 584 if (error != NULL) {
506 wlr_log(L_ERROR, "could not resolve atom %s, X11 error code %d", 585 wlr_log(WLR_ERROR, "could not resolve atom %s, X11 error code %d",
507 atom_map[i], error->error_code); 586 atom_map[i], error->error_code);
508 free(error); 587 free(error);
509 break; 588 break;