Add popup to display pressed keys

This commit is contained in:
Willow Barraco 2023-09-06 09:28:09 +02:00
parent b1890848d5
commit 24e354ce9e
No known key found for this signature in database
GPG Key ID: EABA44759877E02A
5 changed files with 137 additions and 15 deletions

12
drw.c
View File

@ -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) {

2
drw.h
View File

@ -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,

View File

@ -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)

View File

@ -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);

82
main.c
View File

@ -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 <linux/input-event-codes.h>
#include <stdio.h>
#include <stdlib.h>
@ -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, &registry_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) {