diff options
-rw-r--r-- | include/sway/tree/view.h | 11 | ||||
-rw-r--r-- | include/sway/xdg_decoration.h | 2 | ||||
-rw-r--r-- | sway/commands/border.c | 45 | ||||
-rw-r--r-- | sway/tree/container.c | 6 | ||||
-rw-r--r-- | sway/tree/view.c | 8 | ||||
-rw-r--r-- | sway/xdg_decoration.c | 30 |
6 files changed, 72 insertions, 30 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index e7aaffd7..2c7b4c2b 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -76,8 +76,19 @@ struct sway_view { | |||
76 | int natural_width, natural_height; | 76 | int natural_width, natural_height; |
77 | 77 | ||
78 | char *title_format; | 78 | char *title_format; |
79 | |||
80 | // Our border types are B_NONE, B_PIXEL, B_NORMAL and B_CSD. We normally | ||
81 | // just assign this to the border property and ignore the other two. | ||
82 | // However, when a view using CSD is tiled, we want to render our own | ||
83 | // borders as well. So in this case the border property becomes one of the | ||
84 | // first three, and using_csd is true. | ||
85 | // Lastly, views can change their decoration mode at any time. When an SSD | ||
86 | // view becomes CSD without our approval, we save the SSD border type so it | ||
87 | // can be restored if/when the view returns from CSD to SSD. | ||
79 | enum sway_container_border border; | 88 | enum sway_container_border border; |
80 | enum sway_container_border saved_border; | 89 | enum sway_container_border saved_border; |
90 | bool using_csd; | ||
91 | |||
81 | int border_thickness; | 92 | int border_thickness; |
82 | bool border_top; | 93 | bool border_top; |
83 | bool border_bottom; | 94 | bool border_bottom; |
diff --git a/include/sway/xdg_decoration.h b/include/sway/xdg_decoration.h index 46fb8d34..8bef4c6d 100644 --- a/include/sway/xdg_decoration.h +++ b/include/sway/xdg_decoration.h | |||
@@ -10,7 +10,7 @@ struct sway_xdg_decoration { | |||
10 | struct sway_view *view; | 10 | struct sway_view *view; |
11 | 11 | ||
12 | struct wl_listener destroy; | 12 | struct wl_listener destroy; |
13 | struct wl_listener surface_commit; | 13 | struct wl_listener request_mode; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct sway_xdg_decoration *xdg_decoration_from_surface( | 16 | struct sway_xdg_decoration *xdg_decoration_from_surface( |
diff --git a/sway/commands/border.c b/sway/commands/border.c index 5e101564..bfd3b9ed 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c | |||
@@ -7,15 +7,49 @@ | |||
7 | #include "sway/tree/container.h" | 7 | #include "sway/tree/container.h" |
8 | #include "sway/tree/view.h" | 8 | #include "sway/tree/view.h" |
9 | 9 | ||
10 | // A couple of things here: | ||
11 | // - view->border should never be B_CSD when the view is tiled, even when CSD is | ||
12 | // in use (we set using_csd instead and render a sway border). | ||
13 | // - view->saved_border should be the last applied border when switching to CSD. | ||
14 | // - view->using_csd should always reflect whether CSD is applied or not. | ||
10 | static void set_border(struct sway_view *view, | 15 | static void set_border(struct sway_view *view, |
11 | enum sway_container_border new_border) { | 16 | enum sway_container_border new_border) { |
12 | if (view->border == B_CSD && new_border != B_CSD) { | 17 | if (view->using_csd && new_border != B_CSD) { |
13 | view_set_csd_from_server(view, false); | 18 | view_set_csd_from_server(view, false); |
14 | } else if (view->border != B_CSD && new_border == B_CSD) { | 19 | } else if (!view->using_csd && new_border == B_CSD) { |
15 | view_set_csd_from_server(view, true); | 20 | view_set_csd_from_server(view, true); |
21 | view->saved_border = view->border; | ||
22 | } | ||
23 | if (new_border != B_CSD || container_is_floating(view->container)) { | ||
24 | view->border = new_border; | ||
25 | } | ||
26 | view->using_csd = new_border == B_CSD; | ||
27 | } | ||
28 | |||
29 | static void border_toggle(struct sway_view *view) { | ||
30 | if (view->using_csd) { | ||
31 | set_border(view, B_NONE); | ||
32 | return; | ||
33 | } | ||
34 | switch (view->border) { | ||
35 | case B_NONE: | ||
36 | set_border(view, B_PIXEL); | ||
37 | break; | ||
38 | case B_PIXEL: | ||
39 | set_border(view, B_NORMAL); | ||
40 | break; | ||
41 | case B_NORMAL: | ||
42 | if (view->xdg_decoration) { | ||
43 | set_border(view, B_CSD); | ||
44 | } else { | ||
45 | set_border(view, B_NONE); | ||
46 | } | ||
47 | break; | ||
48 | case B_CSD: | ||
49 | // view->using_csd should be true so it would have returned above | ||
50 | sway_assert(false, "Unreachable"); | ||
51 | break; | ||
16 | } | 52 | } |
17 | view->saved_border = view->border; | ||
18 | view->border = new_border; | ||
19 | } | 53 | } |
20 | 54 | ||
21 | struct cmd_results *cmd_border(int argc, char **argv) { | 55 | struct cmd_results *cmd_border(int argc, char **argv) { |
@@ -44,8 +78,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { | |||
44 | } | 78 | } |
45 | set_border(view, B_CSD); | 79 | set_border(view, B_CSD); |
46 | } else if (strcmp(argv[0], "toggle") == 0) { | 80 | } else if (strcmp(argv[0], "toggle") == 0) { |
47 | int num_available = view->xdg_decoration ? 4 : 3; | 81 | border_toggle(view); |
48 | set_border(view, (view->border + 1) % num_available); | ||
49 | } else { | 82 | } else { |
50 | return cmd_results_new(CMD_INVALID, "border", | 83 | return cmd_results_new(CMD_INVALID, "border", |
51 | "Expected 'border <none|normal|pixel|toggle>' " | 84 | "Expected 'border <none|normal|pixel|toggle>' " |
diff --git a/sway/tree/container.c b/sway/tree/container.c index d75e34a5..9b671c1d 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -669,6 +669,9 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
669 | container_init_floating(container); | 669 | container_init_floating(container); |
670 | if (container->view) { | 670 | if (container->view) { |
671 | view_set_tiled(container->view, false); | 671 | view_set_tiled(container->view, false); |
672 | if (container->view->using_csd) { | ||
673 | container->view->border = B_CSD; | ||
674 | } | ||
672 | } | 675 | } |
673 | if (old_parent) { | 676 | if (old_parent) { |
674 | container_reap_empty(old_parent); | 677 | container_reap_empty(old_parent); |
@@ -695,6 +698,9 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
695 | } | 698 | } |
696 | if (container->view) { | 699 | if (container->view) { |
697 | view_set_tiled(container->view, true); | 700 | view_set_tiled(container->view, true); |
701 | if (container->view->using_csd) { | ||
702 | container->view->border = container->view->saved_border; | ||
703 | } | ||
698 | } | 704 | } |
699 | container->is_sticky = false; | 705 | container->is_sticky = false; |
700 | } | 706 | } |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 1c94de4c..9ffcf206 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -309,6 +309,7 @@ void view_request_activate(struct sway_view *view) { | |||
309 | } | 309 | } |
310 | 310 | ||
311 | void view_set_csd_from_server(struct sway_view *view, bool enabled) { | 311 | void view_set_csd_from_server(struct sway_view *view, bool enabled) { |
312 | wlr_log(WLR_DEBUG, "Telling view %p to set CSD to %i", view, enabled); | ||
312 | if (view->xdg_decoration) { | 313 | if (view->xdg_decoration) { |
313 | uint32_t mode = enabled ? | 314 | uint32_t mode = enabled ? |
314 | WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : | 315 | WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : |
@@ -316,15 +317,20 @@ void view_set_csd_from_server(struct sway_view *view, bool enabled) { | |||
316 | wlr_xdg_toplevel_decoration_v1_set_mode( | 317 | wlr_xdg_toplevel_decoration_v1_set_mode( |
317 | view->xdg_decoration->wlr_xdg_decoration, mode); | 318 | view->xdg_decoration->wlr_xdg_decoration, mode); |
318 | } | 319 | } |
320 | view->using_csd = enabled; | ||
319 | } | 321 | } |
320 | 322 | ||
321 | void view_update_csd_from_client(struct sway_view *view, bool enabled) { | 323 | void view_update_csd_from_client(struct sway_view *view, bool enabled) { |
324 | wlr_log(WLR_DEBUG, "View %p updated CSD to %i", view, enabled); | ||
322 | if (enabled && view->border != B_CSD) { | 325 | if (enabled && view->border != B_CSD) { |
323 | view->saved_border = view->border; | 326 | view->saved_border = view->border; |
324 | view->border = B_CSD; | 327 | if (container_is_floating(view->container)) { |
328 | view->border = B_CSD; | ||
329 | } | ||
325 | } else if (!enabled && view->border == B_CSD) { | 330 | } else if (!enabled && view->border == B_CSD) { |
326 | view->border = view->saved_border; | 331 | view->border = view->saved_border; |
327 | } | 332 | } |
333 | view->using_csd = enabled; | ||
328 | } | 334 | } |
329 | 335 | ||
330 | void view_set_tiled(struct sway_view *view, bool tiled) { | 336 | void view_set_tiled(struct sway_view *view, bool tiled) { |
diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index 80b2f57e..39e0df56 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c | |||
@@ -12,31 +12,22 @@ static void xdg_decoration_handle_destroy(struct wl_listener *listener, | |||
12 | wl_container_of(listener, deco, destroy); | 12 | wl_container_of(listener, deco, destroy); |
13 | deco->view->xdg_decoration = NULL; | 13 | deco->view->xdg_decoration = NULL; |
14 | wl_list_remove(&deco->destroy.link); | 14 | wl_list_remove(&deco->destroy.link); |
15 | wl_list_remove(&deco->surface_commit.link); | 15 | wl_list_remove(&deco->request_mode.link); |
16 | wl_list_remove(&deco->link); | 16 | wl_list_remove(&deco->link); |
17 | free(deco); | 17 | free(deco); |
18 | } | 18 | } |
19 | 19 | ||
20 | static void xdg_decoration_handle_surface_commit(struct wl_listener *listener, | 20 | static void xdg_decoration_handle_request_mode(struct wl_listener *listener, |
21 | void *data) { | 21 | void *data) { |
22 | struct sway_xdg_decoration *decoration = | 22 | struct sway_xdg_decoration *deco = |
23 | wl_container_of(listener, decoration, surface_commit); | 23 | wl_container_of(listener, deco, request_mode); |
24 | 24 | wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, | |
25 | bool csd = decoration->wlr_xdg_decoration->current_mode == | 25 | WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); |
26 | WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; | ||
27 | struct sway_view *view = decoration->view; | ||
28 | |||
29 | view_update_csd_from_client(view, csd); | ||
30 | |||
31 | arrange_container(view->container); | ||
32 | transaction_commit_dirty(); | ||
33 | } | 26 | } |
34 | 27 | ||
35 | void handle_xdg_decoration(struct wl_listener *listener, void *data) { | 28 | void handle_xdg_decoration(struct wl_listener *listener, void *data) { |
36 | struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; | 29 | struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; |
37 | struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->surface->data; | 30 | struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->surface->data; |
38 | struct wlr_xdg_surface *wlr_xdg_surface = | ||
39 | xdg_shell_view->view.wlr_xdg_surface; | ||
40 | 31 | ||
41 | struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco)); | 32 | struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco)); |
42 | if (deco == NULL) { | 33 | if (deco == NULL) { |
@@ -50,13 +41,8 @@ void handle_xdg_decoration(struct wl_listener *listener, void *data) { | |||
50 | wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); | 41 | wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); |
51 | deco->destroy.notify = xdg_decoration_handle_destroy; | 42 | deco->destroy.notify = xdg_decoration_handle_destroy; |
52 | 43 | ||
53 | // Note: We don't listen to the request_mode signal here, effectively | 44 | wl_signal_add(&wlr_deco->events.request_mode, &deco->request_mode); |
54 | // ignoring any modes the client asks to set. The client can still force a | 45 | deco->request_mode.notify = xdg_decoration_handle_request_mode; |
55 | // mode upon us, in which case we get upset but live with it. | ||
56 | |||
57 | deco->surface_commit.notify = xdg_decoration_handle_surface_commit; | ||
58 | wl_signal_add(&wlr_xdg_surface->surface->events.commit, | ||
59 | &deco->surface_commit); | ||
60 | 46 | ||
61 | wl_list_insert(&server.xdg_decorations, &deco->link); | 47 | wl_list_insert(&server.xdg_decorations, &deco->link); |
62 | } | 48 | } |