diff --git a/include/common/node-type.h b/include/common/node-type.h index ac83b2b5..9987af38 100644 --- a/include/common/node-type.h +++ b/include/common/node-type.h @@ -47,7 +47,7 @@ enum lab_node_type { LAB_NODE_FRAME, LAB_NODE_ROOT, LAB_NODE_MENUITEM, - LAB_NODE_OSD, + LAB_NODE_OSD_ITEM, LAB_NODE_LAYER_SURFACE, LAB_NODE_UNMANAGED, LAB_NODE_ALL, diff --git a/include/node.h b/include/node.h index bfad1373..ad21f313 100644 --- a/include/node.h +++ b/include/node.h @@ -52,6 +52,13 @@ struct lab_layer_surface *node_layer_surface_from_node( struct menuitem *node_menuitem_from_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 * @wlr_scene_node: wlr_scene_node from which to return data diff --git a/include/osd.h b/include/osd.h index 3397ccf3..a9b4cdff 100644 --- a/include/osd.h +++ b/include/osd.h @@ -45,6 +45,7 @@ struct window_switcher_field { struct buf; struct view; struct server; +struct wlr_scene_node; /* Begin window switcher */ 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 */ 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 */ void osd_field_get_content(struct window_switcher_field *field, struct buf *buf, struct view *view); diff --git a/src/desktop.c b/src/desktop.c index 2d883445..d805eae3 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -340,6 +340,11 @@ get_cursor_context(struct server *server) ret.node = node; ret.type = LAB_NODE_MENUITEM; 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_SSD_ROOT: case LAB_NODE_TITLE: diff --git a/src/input/cursor.c b/src/input/cursor.c index fe694db4..6c12d3da 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -30,6 +30,7 @@ #include "labwc.h" #include "layers.h" #include "menu/menu.h" +#include "osd.h" #include "output.h" #include "resistance.h" #include "resize-outlines.h" @@ -1190,6 +1191,12 @@ cursor_process_button_release(struct seat *seat, uint32_t button, } 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) { return notify; diff --git a/src/node.c b/src/node.c index ce4fb040..1b3dce99 100644 --- a/src/node.c +++ b/src/node.c @@ -59,6 +59,15 @@ node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node) 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 * node_try_ssd_button_from_node(struct wlr_scene_node *wlr_scene_node) { diff --git a/src/osd/osd-classic.c b/src/osd/osd-classic.c index df33caac..0c80bd79 100644 --- a/src/osd/osd-classic.c +++ b/src/osd/osd-classic.c @@ -161,6 +161,8 @@ osd_classic_create(struct output *output, struct wl_array *views) wl_list_append(&output->osd_scene.items, &item->base.link); item->base.view = *view; 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 * +---------------------------------+ @@ -200,6 +202,11 @@ osd_classic_create(struct output *output, struct wl_array *views) item->active_tree, &highlight_opts); 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, text_color, bg_color, field_widths_sum, x, y); create_fields_scene(server, *view, item->active_tree, diff --git a/src/osd/osd-thumbnail.c b/src/osd/osd-thumbnail.c index 14d7c846..76cdf277 100644 --- a/src/osd/osd-thumbnail.c +++ b/src/osd/osd-thumbnail.c @@ -128,6 +128,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view, struct osd_thumbnail_item *item = znew(*item); wl_list_append(&output->osd_scene.items, &item->base.link); 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.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); + /* hitbox for mouse clicks */ + wlr_scene_rect_create(tree, switcher_theme->item_width, + switcher_theme->item_height, (float[4]) {0}); + /* thumbnail */ struct wlr_buffer *thumb_buffer = render_thumb(output, view); if (thumb_buffer) { diff --git a/src/osd/osd.c b/src/osd/osd.c index 6191640e..ca64920c 100644 --- a/src/osd/osd.c +++ b/src/osd/osd.c @@ -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 restore_preview_node(struct server *server) {