summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/tree/view.h1
-rw-r--r--sway/config.c12
-rw-r--r--sway/desktop/xdg_shell.c50
-rw-r--r--sway/desktop/xdg_shell_v6.c50
-rw-r--r--sway/desktop/xwayland.c9
-rw-r--r--sway/input/seat.c6
-rw-r--r--sway/tree/view.c9
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
561bool read_config(FILE *file, struct sway_config *config) { 561bool 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
48static 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
48static struct sway_xdg_popup *popup_create( 95static 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
47static 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
47static struct sway_xdg_popup_v6 *popup_create( 94static 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
249static 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
249static void _close(struct sway_view *view) { 257static 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
317void view_set_tiled(struct sway_view *view, bool tiled) { 317void 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