osd: allow clicking an osd item to focus the window

This commit is contained in:
tokyo4j 2025-10-30 03:22:45 +09:00 committed by Johan Malm
parent 00f0a46ef7
commit 9197eb468a
9 changed files with 55 additions and 1 deletions

View file

@ -47,7 +47,7 @@ enum lab_node_type {
LAB_NODE_FRAME, LAB_NODE_FRAME,
LAB_NODE_ROOT, LAB_NODE_ROOT,
LAB_NODE_MENUITEM, LAB_NODE_MENUITEM,
LAB_NODE_OSD, LAB_NODE_OSD_ITEM,
LAB_NODE_LAYER_SURFACE, LAB_NODE_LAYER_SURFACE,
LAB_NODE_UNMANAGED, LAB_NODE_UNMANAGED,
LAB_NODE_ALL, LAB_NODE_ALL,

View file

@ -52,6 +52,13 @@ struct lab_layer_surface *node_layer_surface_from_node(
struct menuitem *node_menuitem_from_node( struct menuitem *node_menuitem_from_node(
struct wlr_scene_node *wlr_scene_node); struct wlr_scene_node *wlr_scene_node);
/**
* node_osd_item_from_node - return osd item struct from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct osd_item *node_osd_item_from_node(
struct wlr_scene_node *wlr_scene_node);
/** /**
* node_try_ssd_button_from_node - return ssd_button or NULL from node * node_try_ssd_button_from_node - return ssd_button or NULL from node
* @wlr_scene_node: wlr_scene_node from which to return data * @wlr_scene_node: wlr_scene_node from which to return data

View file

@ -45,6 +45,7 @@ struct window_switcher_field {
struct buf; struct buf;
struct view; struct view;
struct server; struct server;
struct wlr_scene_node;
/* Begin window switcher */ /* Begin window switcher */
void osd_begin(struct server *server, enum lab_cycle_dir direction); void osd_begin(struct server *server, enum lab_cycle_dir direction);
@ -58,6 +59,9 @@ void osd_finish(struct server *server, bool switch_focus);
/* Notify OSD about a destroying view */ /* Notify OSD about a destroying view */
void osd_on_view_destroy(struct view *view); void osd_on_view_destroy(struct view *view);
/* Focus the clicked window and close OSD */
void osd_on_cursor_release(struct server *server, struct wlr_scene_node *node);
/* Used by osd.c internally to render window switcher fields */ /* Used by osd.c internally to render window switcher fields */
void osd_field_get_content(struct window_switcher_field *field, void osd_field_get_content(struct window_switcher_field *field,
struct buf *buf, struct view *view); struct buf *buf, struct view *view);

View file

@ -340,6 +340,11 @@ get_cursor_context(struct server *server)
ret.node = node; ret.node = node;
ret.type = LAB_NODE_MENUITEM; ret.type = LAB_NODE_MENUITEM;
return ret; return ret;
case LAB_NODE_OSD_ITEM:
/* Always return the top scene node for osd items */
ret.node = node;
ret.type = LAB_NODE_OSD_ITEM;
return ret;
case LAB_NODE_BUTTON_FIRST...LAB_NODE_BUTTON_LAST: case LAB_NODE_BUTTON_FIRST...LAB_NODE_BUTTON_LAST:
case LAB_NODE_SSD_ROOT: case LAB_NODE_SSD_ROOT:
case LAB_NODE_TITLE: case LAB_NODE_TITLE:

View file

@ -30,6 +30,7 @@
#include "labwc.h" #include "labwc.h"
#include "layers.h" #include "layers.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "osd.h"
#include "output.h" #include "output.h"
#include "resistance.h" #include "resistance.h"
#include "resize-outlines.h" #include "resize-outlines.h"
@ -1190,6 +1191,12 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
} }
return notify; return notify;
} }
if (server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER) {
if (ctx.type == LAB_NODE_OSD_ITEM) {
osd_on_cursor_release(server, ctx.node);
}
return notify;
}
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) { if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
return notify; return notify;

View file

@ -59,6 +59,15 @@ node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
return (struct menuitem *)node_descriptor->data; return (struct menuitem *)node_descriptor->data;
} }
struct osd_item *
node_osd_item_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_OSD_ITEM);
return (struct osd_item *)node_descriptor->data;
}
struct ssd_button * struct ssd_button *
node_try_ssd_button_from_node(struct wlr_scene_node *wlr_scene_node) node_try_ssd_button_from_node(struct wlr_scene_node *wlr_scene_node)
{ {

View file

@ -161,6 +161,8 @@ osd_classic_create(struct output *output, struct wl_array *views)
wl_list_append(&output->osd_scene.items, &item->base.link); wl_list_append(&output->osd_scene.items, &item->base.link);
item->base.view = *view; item->base.view = *view;
item->base.tree = wlr_scene_tree_create(output->osd_scene.tree); item->base.tree = wlr_scene_tree_create(output->osd_scene.tree);
node_descriptor_create(&item->base.tree->node,
LAB_NODE_OSD_ITEM, NULL, item);
/* /*
* OSD border * OSD border
* +---------------------------------+ * +---------------------------------+
@ -200,6 +202,11 @@ osd_classic_create(struct output *output, struct wl_array *views)
item->active_tree, &highlight_opts); item->active_tree, &highlight_opts);
wlr_scene_node_set_position(&highlight_rect->tree->node, padding, y); wlr_scene_node_set_position(&highlight_rect->tree->node, padding, y);
/* hitbox for mouse clicks */
struct wlr_scene_rect *hitbox = wlr_scene_rect_create(item->base.tree,
w - 2 * padding, switcher_theme->item_height, (float[4]) {0});
wlr_scene_node_set_position(&hitbox->node, padding, y);
create_fields_scene(server, *view, item->normal_tree, create_fields_scene(server, *view, item->normal_tree,
text_color, bg_color, field_widths_sum, x, y); text_color, bg_color, field_widths_sum, x, y);
create_fields_scene(server, *view, item->active_tree, create_fields_scene(server, *view, item->active_tree,

View file

@ -128,6 +128,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
struct osd_thumbnail_item *item = znew(*item); struct osd_thumbnail_item *item = znew(*item);
wl_list_append(&output->osd_scene.items, &item->base.link); wl_list_append(&output->osd_scene.items, &item->base.link);
struct wlr_scene_tree *tree = wlr_scene_tree_create(parent); struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
node_descriptor_create(&tree->node, LAB_NODE_OSD_ITEM, NULL, item);
item->base.tree = tree; item->base.tree = tree;
item->base.view = view; item->base.view = view;
@ -142,6 +143,10 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
}; };
item->active_bg = lab_scene_rect_create(tree, &opts); item->active_bg = lab_scene_rect_create(tree, &opts);
/* hitbox for mouse clicks */
wlr_scene_rect_create(tree, switcher_theme->item_width,
switcher_theme->item_height, (float[4]) {0});
/* thumbnail */ /* thumbnail */
struct wlr_buffer *thumb_buffer = render_thumb(output, view); struct wlr_buffer *thumb_buffer = render_thumb(output, view);
if (thumb_buffer) { if (thumb_buffer) {

View file

@ -144,6 +144,16 @@ osd_on_view_destroy(struct view *view)
} }
} }
void
osd_on_cursor_release(struct server *server, struct wlr_scene_node *node)
{
assert(server->input_mode == LAB_INPUT_STATE_WINDOW_SWITCHER);
struct osd_item *item = node_osd_item_from_node(node);
server->osd_state.cycle_view = item->view;
osd_finish(server, /*switch_focus*/ true);
}
static void static void
restore_preview_node(struct server *server) restore_preview_node(struct server *server)
{ {