aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/view.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r--sway/tree/view.c126
1 files changed, 90 insertions, 36 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 26ff1e8d..3117ded6 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -119,13 +119,28 @@ const char *view_get_shell(struct sway_view *view) {
119 return "unknown"; 119 return "unknown";
120} 120}
121 121
122void view_configure(struct sway_view *view, double ox, double oy, int width, 122void view_configure(struct sway_view *view, double lx, double ly, int width,
123 int height) { 123 int height) {
124 if (view->impl->configure) { 124 if (view->impl->configure) {
125 view->impl->configure(view, ox, oy, width, height); 125 view->impl->configure(view, lx, ly, width, height);
126 } 126 }
127} 127}
128 128
129static void view_autoconfigure_floating(struct sway_view *view) {
130 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
131 int max_width = ws->width * 0.6666;
132 int max_height = ws->height * 0.6666;
133 int width =
134 view->natural_width > max_width ? max_width : view->natural_width;
135 int height =
136 view->natural_height > max_height ? max_height : view->natural_height;
137 int lx = ws->x + (ws->width - width) / 2;
138 int ly = ws->y + (ws->height - height) / 2;
139
140 view->border_left = view->border_right = view->border_bottom = true;
141 view_configure(view, lx, ly, width, height);
142}
143
129void view_autoconfigure(struct sway_view *view) { 144void view_autoconfigure(struct sway_view *view) {
130 if (!sway_assert(view->swayc, 145 if (!sway_assert(view->swayc,
131 "Called view_autoconfigure() on a view without a swayc")) { 146 "Called view_autoconfigure() on a view without a swayc")) {
@@ -135,8 +150,12 @@ void view_autoconfigure(struct sway_view *view) {
135 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 150 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
136 151
137 if (view->is_fullscreen) { 152 if (view->is_fullscreen) {
138 view_configure(view, 0, 0, output->width, output->height); 153 view_configure(view, output->x, output->y, output->width, output->height);
139 view->x = view->y = 0; 154 return;
155 }
156
157 if (container_is_floating(view->swayc)) {
158 view_autoconfigure_floating(view);
140 return; 159 return;
141 } 160 }
142 161
@@ -158,21 +177,19 @@ void view_autoconfigure(struct sway_view *view) {
158 177
159 view->border_top = view->border_bottom = true; 178 view->border_top = view->border_bottom = true;
160 view->border_left = view->border_right = true; 179 view->border_left = view->border_right = true;
161 if (view->swayc->layout != L_FLOATING) { 180 if (config->hide_edge_borders == E_BOTH
162 if (config->hide_edge_borders == E_BOTH 181 || config->hide_edge_borders == E_VERTICAL
163 || config->hide_edge_borders == E_VERTICAL 182 || (config->hide_edge_borders == E_SMART && !other_views)) {
164 || (config->hide_edge_borders == E_SMART && !other_views)) { 183 view->border_left = view->swayc->x != ws->x;
165 view->border_left = view->swayc->x != ws->x; 184 int right_x = view->swayc->x + view->swayc->width;
166 int right_x = view->swayc->x + view->swayc->width; 185 view->border_right = right_x != ws->x + ws->width;
167 view->border_right = right_x != ws->x + ws->width; 186 }
168 } 187 if (config->hide_edge_borders == E_BOTH
169 if (config->hide_edge_borders == E_BOTH 188 || config->hide_edge_borders == E_HORIZONTAL
170 || config->hide_edge_borders == E_HORIZONTAL 189 || (config->hide_edge_borders == E_SMART && !other_views)) {
171 || (config->hide_edge_borders == E_SMART && !other_views)) { 190 view->border_top = view->swayc->y != ws->y;
172 view->border_top = view->swayc->y != ws->y; 191 int bottom_y = view->swayc->y + view->swayc->height;
173 int bottom_y = view->swayc->y + view->swayc->height; 192 view->border_bottom = bottom_y != ws->y + ws->height;
174 view->border_bottom = bottom_y != ws->y + ws->height;
175 }
176 } 193 }
177 194
178 double x, y, width, height; 195 double x, y, width, height;
@@ -184,11 +201,11 @@ void view_autoconfigure(struct sway_view *view) {
184 // disable any top border because we'll always have the title bar. 201 // disable any top border because we'll always have the title bar.
185 if (view->swayc->parent->layout == L_TABBED) { 202 if (view->swayc->parent->layout == L_TABBED) {
186 y_offset = container_titlebar_height(); 203 y_offset = container_titlebar_height();
187 view->border_top = 0; 204 view->border_top = false;
188 } else if (view->swayc->parent->layout == L_STACKED) { 205 } else if (view->swayc->parent->layout == L_STACKED) {
189 y_offset = container_titlebar_height() 206 y_offset = container_titlebar_height()
190 * view->swayc->parent->children->length; 207 * view->swayc->parent->children->length;
191 view->border_top = 0; 208 view->border_top = false;
192 } 209 }
193 210
194 switch (view->border) { 211 switch (view->border) {
@@ -257,6 +274,12 @@ void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) {
257 view_set_fullscreen(workspace->sway_workspace->fullscreen, false); 274 view_set_fullscreen(workspace->sway_workspace->fullscreen, false);
258 } 275 }
259 workspace->sway_workspace->fullscreen = view; 276 workspace->sway_workspace->fullscreen = view;
277 view->saved_x = view->x;
278 view->saved_y = view->y;
279 view->saved_width = view->width;
280 view->saved_height = view->height;
281 view->swayc->saved_x = view->swayc->x;
282 view->swayc->saved_y = view->swayc->y;
260 view->swayc->saved_width = view->swayc->width; 283 view->swayc->saved_width = view->swayc->width;
261 view->swayc->saved_height = view->swayc->height; 284 view->swayc->saved_height = view->swayc->height;
262 285
@@ -277,8 +300,14 @@ void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) {
277 } 300 }
278 } else { 301 } else {
279 workspace->sway_workspace->fullscreen = NULL; 302 workspace->sway_workspace->fullscreen = NULL;
280 view->swayc->width = view->swayc->saved_width; 303 if (container_is_floating(view->swayc)) {
281 view->swayc->height = view->swayc->saved_height; 304 view_configure(view, view->saved_x, view->saved_y,
305 view->saved_width, view->saved_height);
306 } else {
307 view->swayc->width = view->swayc->saved_width;
308 view->swayc->height = view->swayc->saved_height;
309 view_autoconfigure(view);
310 }
282 } 311 }
283} 312}
284 313
@@ -452,6 +481,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
452 // TODO: CT_ASSIGN_OUTPUT 481 // TODO: CT_ASSIGN_OUTPUT
453 } 482 }
454 } 483 }
484 // If we're about to launch the view into the floating container, then
485 // launch it as a tiled view in the root of the workspace instead.
486 if (container_is_floating(focus)) {
487 focus = focus->parent->parent;
488 }
455 free(criterias); 489 free(criterias);
456 cont = container_view_create(focus, view); 490 cont = container_view_create(focus, view);
457 491
@@ -468,7 +502,12 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
468 wl_signal_add(&view->swayc->events.reparent, &view->container_reparent); 502 wl_signal_add(&view->swayc->events.reparent, &view->container_reparent);
469 view->container_reparent.notify = view_handle_container_reparent; 503 view->container_reparent.notify = view_handle_container_reparent;
470 504
471 arrange_children_of(cont->parent); 505 if (view->impl->wants_floating && view->impl->wants_floating(view)) {
506 container_set_floating(view->swayc, true);
507 } else {
508 arrange_children_of(cont->parent);
509 }
510
472 input_manager_set_focus(input_manager, cont); 511 input_manager_set_focus(input_manager, cont);
473 if (workspace) { 512 if (workspace) {
474 workspace_switch(workspace); 513 workspace_switch(workspace);
@@ -516,16 +555,16 @@ void view_unmap(struct sway_view *view) {
516 } 555 }
517} 556}
518 557
519void view_update_position(struct sway_view *view, double ox, double oy) { 558void view_update_position(struct sway_view *view, double lx, double ly) {
520 if (view->swayc->x == ox && view->swayc->y == oy) { 559 if (view->x == lx && view->y == ly) {
521 return; 560 return;
522 } 561 }
523
524 // TODO: Only allow this if the view is floating (this function will only be
525 // called in response to wayland clients wanting to reposition themselves).
526 container_damage_whole(view->swayc); 562 container_damage_whole(view->swayc);
527 view->swayc->x = ox; 563 view->x = lx;
528 view->swayc->y = oy; 564 view->y = ly;
565 if (container_is_floating(view->swayc)) {
566 container_set_geometry_from_floating_view(view->swayc);
567 }
529 container_damage_whole(view->swayc); 568 container_damage_whole(view->swayc);
530} 569}
531 570
@@ -533,15 +572,15 @@ void view_update_size(struct sway_view *view, int width, int height) {
533 if (view->width == width && view->height == height) { 572 if (view->width == width && view->height == height) {
534 return; 573 return;
535 } 574 }
536
537 container_damage_whole(view->swayc); 575 container_damage_whole(view->swayc);
538 // Should we update the swayc width/height here too?
539 view->width = width; 576 view->width = width;
540 view->height = height; 577 view->height = height;
578 if (container_is_floating(view->swayc)) {
579 container_set_geometry_from_floating_view(view->swayc);
580 }
541 container_damage_whole(view->swayc); 581 container_damage_whole(view->swayc);
542} 582}
543 583
544
545static void view_subsurface_create(struct sway_view *view, 584static void view_subsurface_create(struct sway_view *view,
546 struct wlr_subsurface *subsurface) { 585 struct wlr_subsurface *subsurface) {
547 struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); 586 struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child));
@@ -888,6 +927,19 @@ bool view_is_visible(struct sway_view *view) {
888 if (!view->swayc) { 927 if (!view->swayc) {
889 return false; 928 return false;
890 } 929 }
930 struct sway_container *workspace =
931 container_parent(view->swayc, C_WORKSPACE);
932 // Determine if view is nested inside a floating container which is sticky.
933 // A simple floating view will have this ancestry:
934 // C_VIEW -> floating -> workspace
935 // A more complex ancestry could be:
936 // C_VIEW -> C_CONTAINER (tabbed) -> floating -> workspace
937 struct sway_container *floater = view->swayc;
938 while (floater->parent->type != C_WORKSPACE
939 && floater->parent->parent->type != C_WORKSPACE) {
940 floater = floater->parent;
941 }
942 bool is_sticky = container_is_floating(floater) && floater->is_sticky;
891 // Check view isn't in a tabbed or stacked container on an inactive tab 943 // Check view isn't in a tabbed or stacked container on an inactive tab
892 struct sway_seat *seat = input_manager_current_seat(input_manager); 944 struct sway_seat *seat = input_manager_current_seat(input_manager);
893 struct sway_container *container = view->swayc; 945 struct sway_container *container = view->swayc;
@@ -901,10 +953,12 @@ bool view_is_visible(struct sway_view *view) {
901 container = container->parent; 953 container = container->parent;
902 } 954 }
903 // Check view isn't hidden by another fullscreen view 955 // Check view isn't hidden by another fullscreen view
904 struct sway_container *workspace = container;
905 if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { 956 if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) {
906 return false; 957 return false;
907 } 958 }
908 // Check the workspace is visible 959 // Check the workspace is visible
909 return workspace_is_visible(workspace); 960 if (!is_sticky) {
961 return workspace_is_visible(workspace);
962 }
963 return true;
910} 964}