aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
authorLibravatar Jonathan Buch <jbuch@synyx.de>2018-10-03 11:05:30 +0200
committerLibravatar Jonathan Buch <jbuch@synyx.de>2018-10-03 16:23:14 +0200
commit7e978d7a4c521a98b9f44274cd65791b06266ed3 (patch)
tree83a1f99fd42c41ae8f15ea0580fb864046dcf427 /sway/tree/container.c
parentFix focusing topmost floating windows (diff)
downloadsway-7e978d7a4c521a98b9f44274cd65791b06266ed3.tar.gz
sway-7e978d7a4c521a98b9f44274cd65791b06266ed3.tar.zst
sway-7e978d7a4c521a98b9f44274cd65791b06266ed3.zip
Use "raycasting" for determining focus for floating windows
Floating containers and their surfaces are ordered in "raised last". This is used to detect the topmost surface and thus the focus.
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c50
1 files changed, 11 insertions, 39 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index f9ddf3d6..f069a9e9 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -151,10 +151,10 @@ struct sway_container *container_find_child(struct sway_container *container,
151 return NULL; 151 return NULL;
152} 152}
153 153
154static void surface_at_view(struct sway_container *con, double lx, double ly, 154static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly,
155 struct wlr_surface **surface, double *sx, double *sy) { 155 struct wlr_surface **surface, double *sx, double *sy) {
156 if (!sway_assert(con->view, "Expected a view")) { 156 if (!sway_assert(con->view, "Expected a view")) {
157 return; 157 return NULL;
158 } 158 }
159 struct sway_view *view = con->view; 159 struct sway_view *view = con->view;
160 double view_sx = lx - view->x + view->geometry.x; 160 double view_sx = lx - view->x + view->geometry.x;
@@ -184,7 +184,9 @@ static void surface_at_view(struct sway_container *con, double lx, double ly,
184 *sx = _sx; 184 *sx = _sx;
185 *sy = _sy; 185 *sy = _sy;
186 *surface = _surface; 186 *surface = _surface;
187 return con;
187 } 188 }
189 return NULL;
188} 190}
189 191
190/** 192/**
@@ -354,46 +356,16 @@ static bool surface_is_popup(struct wlr_surface *surface) {
354struct sway_container *container_at(struct sway_workspace *workspace, 356struct sway_container *container_at(struct sway_workspace *workspace,
355 double lx, double ly, 357 double lx, double ly,
356 struct wlr_surface **surface, double *sx, double *sy) { 358 struct wlr_surface **surface, double *sx, double *sy) {
357 struct sway_container *c; 359 struct sway_container *c = NULL;
358 // Focused view's popups
359 struct sway_seat *seat = input_manager_current_seat(input_manager);
360 struct sway_container *focus = seat_get_focused_container(seat);
361 bool is_floating = focus && container_is_floating_or_child(focus);
362 // Focused view's popups
363 if (focus && focus->view) {
364 surface_at_view(focus, lx, ly, surface, sx, sy);
365 if (*surface && surface_is_popup(*surface)) {
366 return focus;
367 }
368 *surface = NULL;
369 }
370 // If focused is floating, focused view's non-popups
371 if (focus && focus->view && is_floating) {
372 // only switch to unfocused container if focused container has no menus open
373 bool has_subsurfaces = wl_list_length(&focus->view->surface->subsurfaces) > 0;
374 c = floating_container_at(lx, ly, surface, sx, sy);
375 if (!has_subsurfaces && c && c->view && *surface && c != focus) {
376 return c;
377 }
378 360
379 surface_at_view(focus, lx, ly, surface, sx, sy); 361 // First cast a ray to handle floating windows
380 if (*surface) { 362 for (int i = workspace->floating->length - 1; i >= 0; --i) {
381 return focus; 363 struct sway_container *cn = workspace->floating->items[i];
382 } 364 if (cn->view && (c = surface_at_view(cn, lx, ly, surface, sx, sy))) {
383 *surface = NULL; 365 return c;
384 }
385 // Floating (non-focused)
386 if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
387 return c;
388 }
389 // If focused is tiling, focused view's non-popups
390 if (focus && focus->view && !is_floating) {
391 surface_at_view(focus, lx, ly, surface, sx, sy);
392 if (*surface) {
393 return focus;
394 } 366 }
395 *surface = NULL;
396 } 367 }
368
397 // Tiling (non-focused) 369 // Tiling (non-focused)
398 if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { 370 if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) {
399 return c; 371 return c;