aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/layers.h20
-rw-r--r--sway/desktop/layer_shell.c130
-rw-r--r--sway/desktop/output.c30
-rw-r--r--sway/input/cursor.c11
4 files changed, 182 insertions, 9 deletions
diff --git a/include/sway/layers.h b/include/sway/layers.h
index 51878fc9..01d066d5 100644
--- a/include/sway/layers.h
+++ b/include/sway/layers.h
@@ -5,6 +5,11 @@
5#include <wlr/types/wlr_surface.h> 5#include <wlr/types/wlr_surface.h>
6#include <wlr/types/wlr_layer_shell_v1.h> 6#include <wlr/types/wlr_layer_shell_v1.h>
7 7
8enum layer_parent {
9 LAYER_PARENT_LAYER,
10 LAYER_PARENT_POPUP,
11};
12
8struct sway_layer_surface { 13struct sway_layer_surface {
9 struct wlr_layer_surface_v1 *layer_surface; 14 struct wlr_layer_surface_v1 *layer_surface;
10 struct wl_list link; 15 struct wl_list link;
@@ -14,11 +19,26 @@ struct sway_layer_surface {
14 struct wl_listener unmap; 19 struct wl_listener unmap;
15 struct wl_listener surface_commit; 20 struct wl_listener surface_commit;
16 struct wl_listener output_destroy; 21 struct wl_listener output_destroy;
22 struct wl_listener new_popup;
17 23
18 bool configured; 24 bool configured;
19 struct wlr_box geo; 25 struct wlr_box geo;
20}; 26};
21 27
28struct sway_layer_popup {
29 struct wlr_xdg_popup *wlr_popup;
30 enum layer_parent parent_type;
31 union {
32 struct sway_layer_surface *parent_layer;
33 struct sway_layer_popup *parent_popup;
34 };
35 struct wl_listener map;
36 struct wl_listener unmap;
37 struct wl_listener destroy;
38 struct wl_listener commit;
39 struct wl_listener new_popup;
40};
41
22struct sway_output; 42struct sway_output;
23void arrange_layers(struct sway_output *output); 43void arrange_layers(struct sway_output *output);
24 44
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 34ba5592..f1f79c1b 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -320,6 +320,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
320 wl_list_remove(&sway_layer->map.link); 320 wl_list_remove(&sway_layer->map.link);
321 wl_list_remove(&sway_layer->unmap.link); 321 wl_list_remove(&sway_layer->unmap.link);
322 wl_list_remove(&sway_layer->surface_commit.link); 322 wl_list_remove(&sway_layer->surface_commit.link);
323 wl_list_remove(&sway_layer->new_popup.link);
323 if (sway_layer->layer_surface->output != NULL) { 324 if (sway_layer->layer_surface->output != NULL) {
324 struct sway_output *output = sway_layer->layer_surface->output->data; 325 struct sway_output *output = sway_layer->layer_surface->output->data;
325 if (output != NULL) { 326 if (output != NULL) {
@@ -338,7 +339,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
338 struct sway_output *output = sway_layer->layer_surface->output->data; 339 struct sway_output *output = sway_layer->layer_surface->output->data;
339 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, 340 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
340 sway_layer->layer_surface->surface, true); 341 sway_layer->layer_surface->surface, true);
341 // TODO: send enter to subsurfaces and popups
342 wlr_surface_send_enter(sway_layer->layer_surface->surface, 342 wlr_surface_send_enter(sway_layer->layer_surface->surface,
343 sway_layer->layer_surface->output); 343 sway_layer->layer_surface->output);
344 cursor_rebase_all(); 344 cursor_rebase_all();
@@ -350,6 +350,131 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
350 unmap(sway_layer); 350 unmap(sway_layer);
351} 351}
352 352
353static struct sway_layer_surface *popup_get_layer(
354 struct sway_layer_popup *popup) {
355 while (popup->parent_type == LAYER_PARENT_POPUP) {
356 popup = popup->parent_popup;
357 }
358 return popup->parent_layer;
359}
360
361static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
362 struct wlr_xdg_popup *popup = layer_popup->wlr_popup;
363 struct wlr_surface *surface = popup->base->surface;
364 int popup_sx = popup->geometry.x - popup->base->geometry.x;
365 int popup_sy = popup->geometry.y - popup->base->geometry.y;
366 int ox = popup_sx, oy = popup_sy;
367 struct sway_layer_surface *layer;
368 while (true) {
369 if (layer_popup->parent_type == LAYER_PARENT_POPUP) {
370 layer_popup = layer_popup->parent_popup;
371 ox += layer_popup->wlr_popup->base->geometry.x +
372 layer_popup->wlr_popup->geometry.x;
373 oy += layer_popup->wlr_popup->base->geometry.y +
374 layer_popup->wlr_popup->geometry.y;
375 } else {
376 layer = layer_popup->parent_layer;
377 ox += layer->geo.x;
378 oy += layer->geo.y;
379 break;
380 }
381 }
382 struct wlr_output *wlr_output = layer->layer_surface->output;
383 struct sway_output *output = wlr_output->data;
384 output_damage_surface(output, ox, oy, surface, whole);
385}
386
387static void popup_handle_map(struct wl_listener *listener, void *data) {
388 struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
389 struct sway_layer_surface *layer = popup_get_layer(popup);
390 struct wlr_output *wlr_output = layer->layer_surface->output;
391 wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
392 popup_damage(popup, true);
393}
394
395static void popup_handle_unmap(struct wl_listener *listener, void *data) {
396 struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
397 popup_damage(popup, true);
398}
399
400static void popup_handle_commit(struct wl_listener *listener, void *data) {
401 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
402 popup_damage(popup, false);
403}
404
405static void popup_handle_destroy(struct wl_listener *listener, void *data) {
406 struct sway_layer_popup *popup =
407 wl_container_of(listener, popup, destroy);
408
409 wl_list_remove(&popup->map.link);
410 wl_list_remove(&popup->unmap.link);
411 wl_list_remove(&popup->destroy.link);
412 wl_list_remove(&popup->commit.link);
413 free(popup);
414}
415
416static void popup_unconstrain(struct sway_layer_popup *popup) {
417 struct sway_layer_surface *layer = popup_get_layer(popup);
418 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
419
420 struct sway_output *output = layer->layer_surface->output->data;
421
422 // the output box expressed in the coordinate system of the toplevel parent
423 // of the popup
424 struct wlr_box output_toplevel_sx_box = {
425 .x = -layer->geo.x,
426 .y = -layer->geo.y,
427 .width = output->width,
428 .height = output->height,
429 };
430
431 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
432}
433
434static void popup_handle_new_popup(struct wl_listener *listener, void *data);
435
436static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
437 enum layer_parent parent_type, void *parent) {
438 struct sway_layer_popup *popup =
439 calloc(1, sizeof(struct sway_layer_popup));
440 if (popup == NULL) {
441 return NULL;
442 }
443
444 popup->wlr_popup = wlr_popup;
445 popup->parent_type = parent_type;
446 popup->parent_layer = parent;
447
448 popup->map.notify = popup_handle_map;
449 wl_signal_add(&wlr_popup->base->events.map, &popup->map);
450 popup->unmap.notify = popup_handle_unmap;
451 wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
452 popup->destroy.notify = popup_handle_destroy;
453 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
454 popup->commit.notify = popup_handle_commit;
455 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
456 popup->new_popup.notify = popup_handle_new_popup;
457 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
458
459 popup_unconstrain(popup);
460
461 return popup;
462}
463
464static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
465 struct sway_layer_popup *sway_layer_popup =
466 wl_container_of(listener, sway_layer_popup, new_popup);
467 struct wlr_xdg_popup *wlr_popup = data;
468 create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup);
469}
470
471static void handle_new_popup(struct wl_listener *listener, void *data) {
472 struct sway_layer_surface *sway_layer_surface =
473 wl_container_of(listener, sway_layer_surface, new_popup);
474 struct wlr_xdg_popup *wlr_popup = data;
475 create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface);
476}
477
353struct sway_layer_surface *layer_from_wlr_layer_surface_v1( 478struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
354 struct wlr_layer_surface_v1 *layer_surface) { 479 struct wlr_layer_surface_v1 *layer_surface) {
355 return layer_surface->data; 480 return layer_surface->data;
@@ -406,7 +531,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
406 wl_signal_add(&layer_surface->events.map, &sway_layer->map); 531 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
407 sway_layer->unmap.notify = handle_unmap; 532 sway_layer->unmap.notify = handle_unmap;
408 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); 533 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
409 // TODO: Listen for subsurfaces 534 sway_layer->new_popup.notify = handle_new_popup;
535 wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
410 536
411 sway_layer->layer_surface = layer_surface; 537 sway_layer->layer_surface = layer_surface;
412 layer_surface->data = sway_layer; 538 layer_surface->data = sway_layer;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index e7bdf677..4bfc3b77 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -204,6 +204,36 @@ void output_layer_for_each_surface(struct sway_output *output,
204 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface, 204 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
205 layer_surface->geo.x, layer_surface->geo.y, iterator, 205 layer_surface->geo.x, layer_surface->geo.y, iterator,
206 user_data); 206 user_data);
207
208 struct wlr_xdg_popup *state;
209 wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) {
210 struct wlr_xdg_surface *popup = state->base;
211 if (!popup->configured) {
212 continue;
213 }
214
215 double popup_sx, popup_sy;
216 popup_sx = layer_surface->geo.x +
217 popup->popup->geometry.x - popup->geometry.x;
218 popup_sy = layer_surface->geo.y +
219 popup->popup->geometry.y - popup->geometry.y;
220
221 struct wlr_surface *surface = popup->surface;
222
223 struct surface_iterator_data data = {
224 .user_iterator = iterator,
225 .user_data = user_data,
226 .output = output,
227 .ox = popup_sx,
228 .oy = popup_sy,
229 .width = surface->current.width,
230 .height = surface->current.height,
231 .rotation = 0,
232 };
233
234 wlr_xdg_surface_for_each_surface(
235 popup, output_for_each_surface_iterator, &data);
236 }
207 } 237 }
208} 238}
209 239
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 5739aafb..c6a332b8 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -39,15 +39,12 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output,
39 struct wl_list *layer, double ox, double oy, double *sx, double *sy) { 39 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
40 struct sway_layer_surface *sway_layer; 40 struct sway_layer_surface *sway_layer;
41 wl_list_for_each_reverse(sway_layer, layer, link) { 41 wl_list_for_each_reverse(sway_layer, layer, link) {
42 struct wlr_surface *wlr_surface =
43 sway_layer->layer_surface->surface;
44 double _sx = ox - sway_layer->geo.x; 42 double _sx = ox - sway_layer->geo.x;
45 double _sy = oy - sway_layer->geo.y; 43 double _sy = oy - sway_layer->geo.y;
46 // TODO: Test popups/subsurfaces 44 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
47 if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) { 45 sway_layer->layer_surface, _sx, _sy, sx, sy);
48 *sx = _sx; 46 if (sub) {
49 *sy = _sy; 47 return sub;
50 return wlr_surface;
51 } 48 }
52 } 49 }
53 return NULL; 50 return NULL;