diff options
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r-- | sway/tree/view.c | 126 |
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 | ||
122 | void view_configure(struct sway_view *view, double ox, double oy, int width, | 122 | void 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 | ||
129 | static 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 | |||
129 | void view_autoconfigure(struct sway_view *view) { | 144 | void 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 | ||
519 | void view_update_position(struct sway_view *view, double ox, double oy) { | 558 | void 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 | |||
545 | static void view_subsurface_create(struct sway_view *view, | 584 | static 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 | } |