diff options
-rw-r--r-- | include/sway/tree/view.h | 1 | ||||
-rw-r--r-- | sway/config.c | 12 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 50 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 50 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 9 | ||||
-rw-r--r-- | sway/input/seat.c | 6 | ||||
-rw-r--r-- | sway/tree/view.c | 9 |
7 files changed, 127 insertions, 10 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 7dc8ac46..21d6403e 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -35,6 +35,7 @@ struct sway_view_impl { | |||
35 | void (*set_tiled)(struct sway_view *view, bool tiled); | 35 | void (*set_tiled)(struct sway_view *view, bool tiled); |
36 | void (*set_fullscreen)(struct sway_view *view, bool fullscreen); | 36 | void (*set_fullscreen)(struct sway_view *view, bool fullscreen); |
37 | bool (*wants_floating)(struct sway_view *view); | 37 | bool (*wants_floating)(struct sway_view *view); |
38 | bool (*has_client_side_decorations)(struct sway_view *view); | ||
38 | void (*for_each_surface)(struct sway_view *view, | 39 | void (*for_each_surface)(struct sway_view *view, |
39 | wlr_surface_iterator_func_t iterator, void *user_data); | 40 | wlr_surface_iterator_func_t iterator, void *user_data); |
40 | void (*close)(struct sway_view *view); | 41 | void (*close)(struct sway_view *view); |
diff --git a/sway/config.c b/sway/config.c index c59f4f0d..d2386f46 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -560,7 +560,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { | |||
560 | 560 | ||
561 | bool read_config(FILE *file, struct sway_config *config) { | 561 | bool read_config(FILE *file, struct sway_config *config) { |
562 | bool reading_main_config = false; | 562 | bool reading_main_config = false; |
563 | char *current_config, *config_pos; | 563 | char *this_config = NULL, *config_pos; |
564 | long config_size = 0; | 564 | long config_size = 0; |
565 | if (config->current_config == NULL) { | 565 | if (config->current_config == NULL) { |
566 | reading_main_config = true; | 566 | reading_main_config = true; |
@@ -569,8 +569,8 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
569 | config_size = ftell(file); | 569 | config_size = ftell(file); |
570 | rewind(file); | 570 | rewind(file); |
571 | 571 | ||
572 | config_pos = current_config = malloc(config_size + 1); | 572 | config_pos = this_config = malloc(config_size + 1); |
573 | if (current_config == NULL) { | 573 | if (this_config == NULL) { |
574 | wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); | 574 | wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); |
575 | return false; | 575 | return false; |
576 | } | 576 | } |
@@ -616,7 +616,7 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
616 | list_foreach(stack, free); | 616 | list_foreach(stack, free); |
617 | list_free(stack); | 617 | list_free(stack); |
618 | free(line); | 618 | free(line); |
619 | free(current_config); | 619 | free(this_config); |
620 | return false; | 620 | return false; |
621 | } | 621 | } |
622 | wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); | 622 | wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); |
@@ -678,8 +678,8 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
678 | list_free(stack); | 678 | list_free(stack); |
679 | 679 | ||
680 | if (reading_main_config) { | 680 | if (reading_main_config) { |
681 | current_config[config_size - 1] = '\0'; | 681 | this_config[config_size - 1] = '\0'; |
682 | config->current_config = current_config; | 682 | config->current_config = this_config; |
683 | } | 683 | } |
684 | return success; | 684 | return success; |
685 | } | 685 | } |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index be14adbe..17b7b750 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -45,6 +45,53 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { | |||
45 | view_child_destroy(&popup->child); | 45 | view_child_destroy(&popup->child); |
46 | } | 46 | } |
47 | 47 | ||
48 | static void popup_unconstrain(struct sway_xdg_popup *popup) { | ||
49 | // get the output of the popup's positioner anchor point and convert it to | ||
50 | // the toplevel parent's coordinate system and then pass it to | ||
51 | // wlr_xdg_popup_unconstrain_from_box | ||
52 | |||
53 | struct sway_view *view = popup->child.view; | ||
54 | struct wlr_output_layout *output_layout = | ||
55 | root_container.sway_root->output_layout; | ||
56 | struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup; | ||
57 | |||
58 | int anchor_lx, anchor_ly; | ||
59 | wlr_xdg_popup_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); | ||
60 | |||
61 | int popup_lx, popup_ly; | ||
62 | wlr_xdg_popup_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x, | ||
63 | wlr_popup->geometry.y, &popup_lx, &popup_ly); | ||
64 | popup_lx += view->x; | ||
65 | popup_ly += view->y; | ||
66 | |||
67 | anchor_lx += popup_lx; | ||
68 | anchor_ly += popup_ly; | ||
69 | |||
70 | double dest_x = 0, dest_y = 0; | ||
71 | wlr_output_layout_closest_point(output_layout, NULL, anchor_lx, anchor_ly, | ||
72 | &dest_x, &dest_y); | ||
73 | |||
74 | struct wlr_output *output = | ||
75 | wlr_output_layout_output_at(output_layout, dest_x, dest_y); | ||
76 | if (output == NULL) { | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | int width = 0, height = 0; | ||
81 | wlr_output_effective_resolution(output, &width, &height); | ||
82 | |||
83 | // the output box expressed in the coordinate system of the toplevel parent | ||
84 | // of the popup | ||
85 | struct wlr_box output_toplevel_sx_box = { | ||
86 | .x = output->lx - view->x, | ||
87 | .y = output->ly - view->y, | ||
88 | .width = width, | ||
89 | .height = height | ||
90 | }; | ||
91 | |||
92 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | ||
93 | } | ||
94 | |||
48 | static struct sway_xdg_popup *popup_create( | 95 | static struct sway_xdg_popup *popup_create( |
49 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { | 96 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { |
50 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; | 97 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; |
@@ -55,12 +102,15 @@ static struct sway_xdg_popup *popup_create( | |||
55 | return NULL; | 102 | return NULL; |
56 | } | 103 | } |
57 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | 104 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); |
105 | popup->wlr_xdg_surface = xdg_surface; | ||
58 | 106 | ||
59 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | 107 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); |
60 | popup->new_popup.notify = popup_handle_new_popup; | 108 | popup->new_popup.notify = popup_handle_new_popup; |
61 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | 109 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); |
62 | popup->destroy.notify = popup_handle_destroy; | 110 | popup->destroy.notify = popup_handle_destroy; |
63 | 111 | ||
112 | popup_unconstrain(popup); | ||
113 | |||
64 | return popup; | 114 | return popup; |
65 | } | 115 | } |
66 | 116 | ||
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index f5cf085a..43e58918 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -44,6 +44,53 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { | |||
44 | view_child_destroy(&popup->child); | 44 | view_child_destroy(&popup->child); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) { | ||
48 | // get the output of the popup's positioner anchor point and convert it to | ||
49 | // the toplevel parent's coordinate system and then pass it to | ||
50 | // wlr_xdg_popup_unconstrain_from_box | ||
51 | |||
52 | struct sway_view *view = popup->child.view; | ||
53 | struct wlr_output_layout *output_layout = | ||
54 | root_container.sway_root->output_layout; | ||
55 | struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup; | ||
56 | |||
57 | int anchor_lx, anchor_ly; | ||
58 | wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); | ||
59 | |||
60 | int popup_lx, popup_ly; | ||
61 | wlr_xdg_popup_v6_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x, | ||
62 | wlr_popup->geometry.y, &popup_lx, &popup_ly); | ||
63 | popup_lx += view->x; | ||
64 | popup_ly += view->y; | ||
65 | |||
66 | anchor_lx += popup_lx; | ||
67 | anchor_ly += popup_ly; | ||
68 | |||
69 | double dest_x = 0, dest_y = 0; | ||
70 | wlr_output_layout_closest_point(output_layout, NULL, anchor_lx, anchor_ly, | ||
71 | &dest_x, &dest_y); | ||
72 | |||
73 | struct wlr_output *output = | ||
74 | wlr_output_layout_output_at(output_layout, dest_x, dest_y); | ||
75 | if (output == NULL) { | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | int width = 0, height = 0; | ||
80 | wlr_output_effective_resolution(output, &width, &height); | ||
81 | |||
82 | // the output box expressed in the coordinate system of the toplevel parent | ||
83 | // of the popup | ||
84 | struct wlr_box output_toplevel_sx_box = { | ||
85 | .x = output->lx - view->x, | ||
86 | .y = output->ly - view->y, | ||
87 | .width = width, | ||
88 | .height = height | ||
89 | }; | ||
90 | |||
91 | wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | ||
92 | } | ||
93 | |||
47 | static struct sway_xdg_popup_v6 *popup_create( | 94 | static struct sway_xdg_popup_v6 *popup_create( |
48 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { | 95 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { |
49 | struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; | 96 | struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; |
@@ -54,12 +101,15 @@ static struct sway_xdg_popup_v6 *popup_create( | |||
54 | return NULL; | 101 | return NULL; |
55 | } | 102 | } |
56 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | 103 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); |
104 | popup->wlr_xdg_surface_v6 = xdg_surface; | ||
57 | 105 | ||
58 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | 106 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); |
59 | popup->new_popup.notify = popup_handle_new_popup; | 107 | popup->new_popup.notify = popup_handle_new_popup; |
60 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | 108 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); |
61 | popup->destroy.notify = popup_handle_destroy; | 109 | popup->destroy.notify = popup_handle_destroy; |
62 | 110 | ||
111 | popup_unconstrain(popup); | ||
112 | |||
63 | return popup; | 113 | return popup; |
64 | } | 114 | } |
65 | 115 | ||
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 4e5cea7d..460d1cc8 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -246,6 +246,14 @@ static bool wants_floating(struct sway_view *view) { | |||
246 | return false; | 246 | return false; |
247 | } | 247 | } |
248 | 248 | ||
249 | static bool has_client_side_decorations(struct sway_view *view) { | ||
250 | if (xwayland_view_from_view(view) == NULL) { | ||
251 | return false; | ||
252 | } | ||
253 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | ||
254 | return surface->decorations != WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; | ||
255 | } | ||
256 | |||
249 | static void _close(struct sway_view *view) { | 257 | static void _close(struct sway_view *view) { |
250 | if (xwayland_view_from_view(view) == NULL) { | 258 | if (xwayland_view_from_view(view) == NULL) { |
251 | return; | 259 | return; |
@@ -269,6 +277,7 @@ static const struct sway_view_impl view_impl = { | |||
269 | .set_tiled = set_tiled, | 277 | .set_tiled = set_tiled, |
270 | .set_fullscreen = set_fullscreen, | 278 | .set_fullscreen = set_fullscreen, |
271 | .wants_floating = wants_floating, | 279 | .wants_floating = wants_floating, |
280 | .has_client_side_decorations = has_client_side_decorations, | ||
272 | .close = _close, | 281 | .close = _close, |
273 | .destroy = destroy, | 282 | .destroy = destroy, |
274 | }; | 283 | }; |
diff --git a/sway/input/seat.c b/sway/input/seat.c index bf4e8876..5e65ca70 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -669,9 +669,11 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
669 | // If we've focused a floating container, bring it to the front. | 669 | // If we've focused a floating container, bring it to the front. |
670 | // We do this by putting it at the end of the floating list. | 670 | // We do this by putting it at the end of the floating list. |
671 | // This must happen for both the pending and current children lists. | 671 | // This must happen for both the pending and current children lists. |
672 | if (container_is_floating(container)) { | 672 | if (container && container_is_floating(container)) { |
673 | list_move_to_end(container->parent->children, container); | 673 | list_move_to_end(container->parent->children, container); |
674 | list_move_to_end(container->parent->current.children, container); | 674 | if (container_has_ancestor(container, container->current.parent)) { |
675 | list_move_to_end(container->parent->current.children, container); | ||
676 | } | ||
675 | } | 677 | } |
676 | 678 | ||
677 | // clean up unfocused empty workspace on new output | 679 | // clean up unfocused empty workspace on new output |
diff --git a/sway/tree/view.c b/sway/tree/view.c index f99def6c..b356183c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -315,7 +315,11 @@ void view_set_activated(struct sway_view *view, bool activated) { | |||
315 | } | 315 | } |
316 | 316 | ||
317 | void view_set_tiled(struct sway_view *view, bool tiled) { | 317 | void view_set_tiled(struct sway_view *view, bool tiled) { |
318 | view->border = tiled ? config->border : B_NONE; | 318 | bool csd = true; |
319 | if (view->impl->has_client_side_decorations) { | ||
320 | csd = view->impl->has_client_side_decorations(view); | ||
321 | } | ||
322 | view->border = tiled || !csd ? config->border : B_NONE; | ||
319 | if (view->impl->set_tiled) { | 323 | if (view->impl->set_tiled) { |
320 | view->impl->set_tiled(view, tiled); | 324 | view->impl->set_tiled(view, tiled); |
321 | } | 325 | } |
@@ -752,8 +756,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { | |||
752 | return NULL; | 756 | return NULL; |
753 | } | 757 | } |
754 | 758 | ||
759 | const char *role = wlr_surface->role ? wlr_surface->role->name : NULL; | ||
755 | wlr_log(WLR_DEBUG, "Surface of unknown type (role %s): %p", | 760 | wlr_log(WLR_DEBUG, "Surface of unknown type (role %s): %p", |
756 | wlr_surface->role, wlr_surface); | 761 | role, wlr_surface); |
757 | return NULL; | 762 | return NULL; |
758 | } | 763 | } |
759 | 764 | ||