From 24e354ce9e56b9e7dfdf9c1d2dc0c121eca72881 Mon Sep 17 00:00:00 2001 From: Willow Barraco Date: Wed, 6 Sep 2023 09:28:09 +0200 Subject: [PATCH] Add popup to display pressed keys --- drw.c | 12 ++++++++ drw.h | 2 ++ keyboard.c | 49 +++++++++++++++++++++++++------- keyboard.h | 7 ++++- main.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 137 insertions(+), 15 deletions(-) diff --git a/drw.c b/drw.c index 078a3ec..94e9983 100644 --- a/drw.c +++ b/drw.c @@ -51,6 +51,18 @@ drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y, cairo_restore(d->cairo); } +void +drw_do_clear(struct drwsurf *d, uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { + cairo_save(d->cairo); + + cairo_set_operator(d->cairo, CAIRO_OPERATOR_CLEAR); + cairo_rectangle(d->cairo, x, y, w, h); + cairo_fill(d->cairo); + + cairo_restore(d->cairo); +} + void drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, uint32_t w, uint32_t h, bool over) { diff --git a/drw.h b/drw.h index 1ed6b19..3fb6ce0 100644 --- a/drw.h +++ b/drw.h @@ -30,6 +30,8 @@ typedef union { uint32_t color; } Color; +void drw_do_clear(struct drwsurf *d, uint32_t x, uint32_t y, + uint32_t w, uint32_t h); void drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, uint32_t w, uint32_t h, bool fill); void drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, diff --git a/keyboard.c b/keyboard.c index 2fe62c9..bba2ca3 100644 --- a/keyboard.c +++ b/keyboard.c @@ -306,6 +306,9 @@ kbd_release_key(struct kbd *kb, uint32_t time) { } drwsurf_flip(kb->surf); + + kbd_clear_last_popup(kb); + drwsurf_flip(kb->popup_surf); } void @@ -331,6 +334,9 @@ kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y) { } drwsurf_flip(kb->surf); + + kbd_clear_last_popup(kb); + drwsurf_flip(kb->popup_surf); } void @@ -456,6 +462,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) { } drwsurf_flip(kb->surf); + drwsurf_flip(kb->popup_surf); } void @@ -497,9 +504,18 @@ kbd_print_key_stdout(struct kbd *kb, struct key *k) { fflush(stdout); } +void +kbd_clear_last_popup(struct kbd *kb) { + if (kb->last_popup_w && kb->last_popup_h) { + drw_do_clear(kb->popup_surf, kb->last_popup_x, kb->last_popup_y, kb->last_popup_w, kb->last_popup_h); + wl_surface_damage(kb->popup_surf->surf, kb->last_popup_x, kb->last_popup_y, kb->last_popup_w, kb->last_popup_h); + + kb->last_popup_w = kb->last_popup_h = 0; + } +} + void kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type) { - struct drwsurf *d = kb->surf; const char *label = (kb->mods & Shift) ? k->shift_label : k->label; if (kb->debug) fprintf(stderr, "Draw key +%d+%d %dx%d -> %s\n", k->x, k->y, k->w, k->h, @@ -507,20 +523,34 @@ kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type) { struct clr_scheme *scheme = (k->scheme == 0) ? &(kb->scheme) : &(kb->scheme1); switch (type) { + case None: case Unpress: - draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->fg); + draw_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->fg); break; case Press: - draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->high); + draw_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->high); break; case Swipe: - draw_over_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->swipe); + draw_over_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->swipe); break; } - drw_draw_text(d, scheme->text, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, label); + drw_draw_text(kb->surf, scheme->text, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, label); + wl_surface_damage(kb->surf->surf, k->x, k->y, k->w, k->h); - wl_surface_damage(d->surf, k->x, k->y, k->w, k->h); + if (type == Press || type == Unpress) { + kbd_clear_last_popup(kb); + + kb->last_popup_x = k->x; + kb->last_popup_y = kb->h + k->y - k->h; + kb->last_popup_w = k->w; + kb->last_popup_h = k->h; + + drw_fill_rectangle(kb->popup_surf, kb->scheme.bg, k->x, kb->last_popup_y, k->w, k->h); + draw_inset(kb->popup_surf, k->x, kb->last_popup_y, k->w, k->h, KBD_KEY_BORDER, scheme->high); + drw_draw_text(kb->popup_surf, scheme->text, k->x, kb->last_popup_y, k->w, k->h, KBD_KEY_BORDER, label); + wl_surface_damage(kb->popup_surf->surf, k->x, kb->last_popup_y, k->w, k->h); + } } void @@ -541,7 +571,7 @@ kbd_draw_layout(struct kbd *kb) { (next_key->type == Compose && kb->compose)) { kbd_draw_key(kb, next_key, Press); } else { - kbd_draw_key(kb, next_key, Unpress); + kbd_draw_key(kb, next_key, None); } next_key++; } @@ -550,12 +580,11 @@ kbd_draw_layout(struct kbd *kb) { void kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount) { - struct drwsurf *d = kb->surf; - fprintf(stderr, "Resize %dx%d %d, %d layouts\n", kb->w, kb->h, kb->scale, layoutcount); - drwsurf_resize(d, kb->w, kb->h, kb->scale); + drwsurf_resize(kb->surf, kb->w, kb->h, kb->scale); + drwsurf_resize(kb->popup_surf, kb->w, kb->h*2, kb->scale); for (int i = 0; i < layoutcount; i++) { if (kb->debug) { if (layouts[i].name) diff --git a/keyboard.h b/keyboard.h index c02735f..e45444d 100644 --- a/keyboard.h +++ b/keyboard.h @@ -42,7 +42,8 @@ enum key_modifier_type { }; enum key_draw_type { - Unpress = 0, + None = 0, + Unpress, Press, Swipe, }; @@ -110,7 +111,10 @@ struct kbd { enum layout_id *landscape_layers; struct drwsurf *surf; + struct drwsurf *popup_surf; struct zwp_virtual_keyboard_v1 *vkbd; + + uint32_t last_popup_x, last_popup_y, last_popup_w, last_popup_h; }; void draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width, @@ -128,6 +132,7 @@ void kbd_release_key(struct kbd *kb, uint32_t time); void kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y); void kbd_press_key(struct kbd *kb, struct key *k, uint32_t time); void kbd_print_key_stdout(struct kbd *kb, struct key *k); +void kbd_clear_last_popup(struct kbd *kb); void kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type); void kbd_draw_layout(struct kbd *kb); void kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount); diff --git a/main.c b/main.c index 88852ea..35eea1d 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include "proto/virtual-keyboard-unstable-v1-client-protocol.h" #include "proto/wlr-layer-shell-unstable-v1-client-protocol.h" +#include "proto/xdg-shell-client-protocol.h" #include #include #include @@ -27,8 +28,13 @@ static struct wl_compositor *compositor; static struct wl_seat *seat; static struct wl_pointer *pointer; static struct wl_touch *touch; +static struct wl_region *empty_region; static struct zwlr_layer_shell_v1 *layer_shell; static struct zwlr_layer_surface_v1 *layer_surface; +static struct xdg_wm_base *wm_base; +static struct xdg_surface *popup_xdg_surface; +static struct xdg_popup *popup_xdg_popup; +static struct xdg_positioner *popup_xdg_positioner; static struct zwp_virtual_keyboard_manager_v1 *vkbd_mgr; struct Output { @@ -43,7 +49,7 @@ static int wl_outputs_size; /* drawing */ static struct drw draw_ctx; -static struct drwsurf draw_surf; +static struct drwsurf draw_surf, popup_draw_surf; /* layer surface parameters */ static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; @@ -348,6 +354,16 @@ static const struct wl_output_listener output_listener = { .done = display_handle_done, .scale = display_handle_scale}; +static void +xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = xdg_wm_base_ping, +}; + void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { @@ -370,6 +386,10 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { + wm_base = + wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(wm_base, &xdg_wm_base_listener, NULL); } else if (strcmp(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0) { vkbd_mgr = wl_registry_bind(registry, name, @@ -391,18 +411,64 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { } } +static void +xdg_popup_surface_configure(void *data, + struct xdg_surface *xdg_surface, uint32_t serial) +{ + xdg_surface_ack_configure(xdg_surface, serial); + drwsurf_flip(&popup_draw_surf); +} + +static const struct xdg_surface_listener xdg_popup_surface_listener = { + .configure = xdg_popup_surface_configure, +}; + + +static void +xdg_popup_configure(void *data, + struct xdg_popup *xdg_popup, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + kbd_resize(&keyboard, layouts, NumLayouts); + + drwsurf_flip(&draw_surf); +} + +static void +xdg_popup_done(void *data, struct xdg_popup *xdg_popup) { +} + +static const struct xdg_popup_listener xdg_popup_listener = { + .configure = xdg_popup_configure, + .popup_done = xdg_popup_done, +}; + void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h) { if (keyboard.w != w || keyboard.h != h) { keyboard.w = w; keyboard.h = h; - kbd_resize(&keyboard, layouts, NumLayouts); + + xdg_positioner_set_size(popup_xdg_positioner, w, h*2); + xdg_positioner_set_anchor_rect(popup_xdg_positioner, 0, -h, w, h*2); + + if (popup_xdg_popup) { + xdg_popup_destroy(popup_xdg_popup); + } + + popup_draw_surf.surf = wl_compositor_create_surface(compositor); + wl_surface_set_input_region(popup_draw_surf.surf, empty_region); + popup_xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, popup_draw_surf.surf); + xdg_surface_add_listener(popup_xdg_surface, &xdg_popup_surface_listener, NULL); + popup_xdg_popup = xdg_surface_get_popup(popup_xdg_surface, NULL, popup_xdg_positioner); + xdg_popup_add_listener(popup_xdg_popup, &xdg_popup_listener, NULL); + zwlr_layer_surface_v1_get_popup(layer_surface, popup_xdg_popup); + wl_surface_commit(popup_draw_surf.surf); } zwlr_layer_surface_v1_ack_configure(surface, serial); - - drwsurf_flip(&draw_surf); } void @@ -689,7 +755,9 @@ main(int argc, char **argv) { } draw_surf.ctx = &draw_ctx; + popup_draw_surf.ctx = &draw_ctx; keyboard.surf = &draw_surf; + keyboard.popup_surf = &popup_draw_surf; struct wl_registry *registry = wl_display_get_registry(display); wl_registry_add_listener(registry, ®istry_listener, NULL); @@ -704,10 +772,16 @@ main(int argc, char **argv) { if (layer_shell == NULL) { die("layer_shell not available\n"); } + if (wm_base == NULL) { + die("wm_base not available\n"); + } if (vkbd_mgr == NULL) { die("virtual_keyboard_manager not available\n"); } + empty_region = wl_compositor_create_region(compositor); + popup_xdg_positioner = xdg_wm_base_create_positioner(wm_base); + keyboard.vkbd = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkbd_mgr, seat); if (keyboard.vkbd == NULL) {