diff --git a/src/backend/wayland/wl_framebuf.c b/src/backend/wayland/wl_framebuf.c index bc9eae7..6977b47 100644 --- a/src/backend/wayland/wl_framebuf.c +++ b/src/backend/wayland/wl_framebuf.c @@ -301,23 +301,26 @@ frame_buf_hit(int px, int py) if (!fb) fb = frame_buf_button_at(px, py); - /* If we landed on a top-level frame (parent_id==0), check whether a - * child sub-window (resizebar, titlebar) actually contains (px,py). - * Child frame_bufs may not have a committed scene_buf buffer so - * wlr_scene_node_at skips them; we find them by coordinate instead. - * Return the smallest (most specific) child that encloses the point. */ - if (fb && fb->parent_id == 0) { - struct wl_frame_buf *child, *best_child = NULL; - wl_list_for_each(child, &wl_state.frame_list, link) { - if (child->parent_id != fb->id) continue; - if (px < child->x || px >= child->x + child->width) continue; - if (py < child->y || py >= child->y + child->height) continue; - if (!best_child || - (child->width * child->height) < (best_child->width * best_child->height)) - best_child = child; + /* Walk children (and grandchildren) to find the most specific + * frame_buf enclosing the point. Handles titlebar/resizebar buttons + * AND WINGs views nested inside fake_leader frames. */ + if (fb) { + int depth; + for (depth = 0; depth < 4; depth++) { + struct wl_frame_buf *child, *best_child = NULL; + wl_list_for_each(child, &wl_state.frame_list, link) { + if (child->parent_id != fb->id) continue; + if (px < child->x || px >= child->x + child->width) continue; + if (py < child->y || py >= child->y + child->height) continue; + if (!best_child || + (child->width * child->height) < (best_child->width * best_child->height)) + best_child = child; + } + if (best_child) + fb = best_child; + else + break; } - if (best_child) - fb = best_child; } return fb;