svkbd

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/svkbd
Log | Files | Refs | README | LICENSE

commit c6739137f261945b2ae071f96c4b9daf1270eea7
parent b25e55e4622d419f252570d15080cdd2628b9236
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Mon, 26 Apr 2021 20:30:22 -0500

port to wayland

stolen from oasis' dmenu wayland port

Diffstat:
MMakefile | 12++++++++++--
Mconfig.def.h | 2+-
Mconfig.mk | 16+++++++++-------
Mdrw.c | 129++++++++++++++++++++++++++++++++++++-------------------------------------------
Mdrw.h | 22++++++++++------------
Mlayout.mobile-intl.h | 786++++++++++++++++++++++++++++++++++++++++----------------------------------------
Alayout.mobile-minimal.h | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aprotocol/virtual-keyboard-unstable-v1.xml | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msvkbd.c | 905+++++++++++++++++++++++++++++--------------------------------------------------
Mutil.c | 17+++++++++++++++++
Mutil.h | 1+
11 files changed, 1047 insertions(+), 1054 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,7 +8,7 @@ VERSION = 0.3 include config.mk BIN = ${NAME}-${LAYOUT} -SRC = drw.c ${NAME}.c util.c +SRC = drw.c ${NAME}.c util.c swc-protocol.c OBJ = ${SRC:.c=.o} MAN1 = ${NAME}.1 @@ -29,7 +29,15 @@ svkbd.o: config.h layout.${LAYOUT}.h .c.o: ${CC} ${SVKBD_CFLAGS} ${SVKBD_CPPFLAGS} -c $< -${OBJ}: config.h config.mk +swc-protocol.c: $(SWCPROTO) + @echo GEN $@ + wayland-scanner code < $< > $@ + +swc-client-protocol.h: $(SWCPROTO) + @echo GEN $@ + wayland-scanner client-header < $< > $@ + +${OBJ}: config.h config.mk swc-client-protocol.h ${BIN}: ${OBJ} ${CC} -o ${BIN} ${OBJ} ${SVKBD_LDFLAGS} diff --git a/config.def.h b/config.def.h @@ -1,4 +1,4 @@ -static const Bool wmborder = True; +static const Bool wmborder = true; static int fontsize = 22; static double overlay_delay = 1.0; //in seconds static double repeat_delay = 0.75; //in seconds, will not work on keys with overlays diff --git a/config.mk b/config.mk @@ -9,19 +9,21 @@ X11LIB = /usr/X11R6/lib PKG_CONFIG = pkg-config -# Xinerama, comment if you don't want it -XINERAMALIBS = -L${X11LIB} -lXinerama -XINERAMAFLAGS = -DXINERAMA +PIXMANINC = /usr/include/pixman-1 +SWCPROTO = /usr/share/swc/swc.xml +VKPROTO = protocols/virtual-keyboard-unstable-v1.xml # includes and libs INCS = -I. -I./layouts -I${X11INC} \ `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L${X11LIB} -lX11 -lXtst -lXft ${XINERAMALIBS} \ + `$(PKG_CONFIG) --cflags freetype2` \ + `$(PKG_CONFIG) --cflags pixman-1` +LIBS = -L${X11LIB} -lX11 -lwayland-client -lxkbcommon -lwld -lswc \ `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` + `$(PKG_CONFIG) --libs freetype2` \ + `$(PKG_CONFIG) --libs pixman-1` # use system flags SVKBD_CFLAGS = ${CFLAGS} ${INCS} SVKBD_LDFLAGS = ${LDFLAGS} ${LIBS} -SVKBD_CPPFLAGS = ${CPPFLAGS} -D_DEFAULT_SOURCE -DVERSION=\"VERSION\" ${XINERAMAFLAGS} -DLAYOUT=\"layout.${LAYOUT}.h\" +SVKBD_CPPFLAGS = ${CPPFLAGS} -D_DEFAULT_SOURCE -DVERSION=\"VERSION\" -DLAYOUT=\"layout.${LAYOUT}.h\" diff --git a/drw.c b/drw.c @@ -2,8 +2,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <X11/Xlib.h> -#include <X11/Xft/Xft.h> +#include <wayland-client.h> +#include <wld/wld.h> +#include <wld/wayland.h> #include "drw.h" #include "util.h" @@ -61,41 +62,34 @@ utf8decode(const char *c, long *u, size_t clen) } Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +drw_create(struct wl_display *dpy) { Drw *drw = ecalloc(1, sizeof(Drw)); drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + drw->ctx = wld_wayland_create_context(dpy, WLD_SHM); + drw->renderer = wld_create_renderer(drw->ctx); + drw->fontctx = wld_font_create_context(); return drw; } void -drw_resize(Drw *drw, unsigned int w, unsigned int h) +drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h) { - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + if (drw->surface) + wld_destroy_surface(drw->surface); + drw->surface = wld_wayland_create_surface(drw->ctx, w, h, WLD_FORMAT_XRGB8888, 0, surface); } void drw_free(Drw *drw) { - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); + wld_destroy_surface(drw->surface); + wld_destroy_renderer(drw->renderer); + wld_destroy_context(drw->ctx); drw_fontset_free(drw->fonts); + wld_font_destroy_context(drw->fontctx); free(drw); } @@ -103,11 +97,10 @@ drw_free(Drw *drw) * drw_fontset_create instead. */ static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +wldfont_create(Drw *drw, const char *fontname, FcPattern *pattern) { Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; + struct wld_font *wld = NULL; if (fontname) { /* Using the pattern found at font->xfont->pattern does not yield the @@ -115,17 +108,17 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) * FcNameParse; using the latter results in the desired fallback * behaviour whereas the former just results in missing-character * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + if (!(wld = wld_font_open_name(drw->fontctx, fontname))) { fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); return NULL; } if (!(pattern = FcNameParse((FcChar8 *) fontname))) { fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); + wld_font_close(wld); return NULL; } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + } else if (pattern) { + if (!(wld = wld_font_open_pattern(drw->fontctx, pattern))) { fprintf(stderr, "error, cannot load font from pattern.\n"); return NULL; } @@ -141,28 +134,26 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) * and lots more all over the internet. */ FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { - XftFontClose(drw->dpy, xfont); + if(FcPatternGetBool(pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + wld_font_close(wld); return NULL; } font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; + font->wld = wld; font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; return font; } static void -xfont_free(Fnt *font) +wldfont_free(Fnt *font) { if (!font) return; if (font->pattern) FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); + wld_font_close(font->wld); free(font); } @@ -176,7 +167,7 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) return NULL; for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + if ((cur = wldfont_create(drw, fonts[fontcount - i], NULL))) { cur->next = ret; ret = cur; } @@ -189,7 +180,7 @@ drw_fontset_free(Fnt *font) { if (font) { drw_fontset_free(font->next); - xfont_free(font); + wldfont_free(font); } } @@ -199,9 +190,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) if (!drw || !dest || !clrname) return; - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) + if (!(wld_lookup_named_color(clrname, dest))) die("error, cannot allocate color '%s'", clrname); } @@ -214,7 +203,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) Clr *ret; /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(*ret)))) die("error, cannot create color scheme (drw=%d) (clrcount=%d)", drw, clrcount); for (i = 0; i < clrcount; i++) @@ -241,11 +230,15 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int { if (!drw || !drw->scheme) return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + Clr color = invert ? drw->scheme[ColBg] : drw->scheme[ColFg]; if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); + wld_fill_rectangle(drw->renderer, color, x, y, w, h); + else { + wld_fill_rectangle(drw->renderer, color, x, y, w, 1); + wld_fill_rectangle(drw->renderer, color, x + w - 1, y + 1, 1, h - 2); + wld_fill_rectangle(drw->renderer, color, x, y + 1, 1, h - 2); + wld_fill_rectangle(drw->renderer, color, x, y - 1, w, 1); + } } int @@ -254,7 +247,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp char buf[1024]; int ty; unsigned int ew; - XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont; size_t i, len; int utf8strlen, utf8charlen, render = x || y || w || h; @@ -263,7 +255,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcCharSet *fccharset; FcPattern *fcpattern; FcPattern *match; - XftResult result; + FcResult result; int charexists = 0; if (!drw || (render && !drw->scheme) || !text || !drw->fonts) @@ -272,11 +264,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (!render) { w = ~w; } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); + wld_fill_rectangle(drw->renderer, drw->scheme[invert ? ColFg : ColBg], x, y, w, h); x += lpad; w -= lpad; } @@ -289,7 +277,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp while (*text) { utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + charexists = charexists || wld_font_ensure_char(curfont->wld, utf8codepoint); if (charexists) { if (curfont == usedfont) { utf8strlen += utf8charlen; @@ -321,9 +309,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp ; /* NOP */ if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)buf, len); + ty = y + (h - usedfont->wld->height) / 2 + usedfont->wld->ascent; + wld_draw_text(drw->renderer, usedfont->wld, drw->scheme[invert ? ColBg : ColFg], + x, ty, buf, len, NULL); } x += ew; w -= ew; @@ -344,7 +332,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcCharSetAddChar(fccharset, utf8codepoint); if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ + /* Refer to the comment in wldfont_create for more information. */ die("the first font in the cache must be loaded from a font string."); } @@ -355,43 +343,44 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + match = FcFontMatch(NULL, fcpattern, &result); FcCharSetDestroy(fccharset); FcPatternDestroy(fcpattern); if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + usedfont = wldfont_create(drw, NULL, match); + if (usedfont && wld_font_ensure_char(usedfont->wld, utf8codepoint)) { for (curfont = drw->fonts; curfont->next; curfont = curfont->next) ; /* NOP */ curfont->next = usedfont; } else { - xfont_free(usedfont); + wldfont_free(usedfont); usedfont = drw->fonts; } } } } - if (d) - XftDrawDestroy(d); return x + (render ? w : 0); } void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h) { if (!drw) return; - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + wl_surface_damage(surface, x, y, w, h); + wld_flush(drw->renderer); + wld_swap(drw->surface); } void drw_sync(Drw *drw) { - XSync(drw->dpy, False); + wld_flush(drw->renderer); + wld_swap(drw->surface); } unsigned int @@ -405,14 +394,14 @@ drw_fontset_getwidth(Drw *drw, const char *text) void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { - XGlyphInfo ext; + struct wld_extents ext; if (!font || !text) return; - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + wld_font_text_extents_n(font->wld, text, len, &ext); if (w) - *w = ext.xOff; + *w = ext.advance; if (h) - *h = font->h; + *h = font->wld->height; } diff --git a/drw.h b/drw.h @@ -1,30 +1,28 @@ /* See LICENSE file for copyright and license details. */ typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; + struct wld_font *wld; FcPattern *pattern; struct Fnt *next; } Fnt; enum { ColFg, ColBg }; /* Clr scheme index */ -typedef XftColor Clr; +typedef uint32_t Clr; typedef struct { unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; + struct wl_display *dpy; + struct wld_context *ctx; + struct wld_renderer *renderer; + struct wld_surface *surface; + struct wld_font_context *fontctx; Clr *scheme; Fnt *fonts; } Drw; /* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); +Drw *drw_create(struct wl_display *dpy); +void drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ @@ -46,5 +44,5 @@ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); /* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); +void drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h); void drw_sync(Drw *drw); diff --git a/layout.mobile-intl.h b/layout.mobile-intl.h @@ -1,261 +1,261 @@ #define KEYS 55 static Key keys_en[KEYS] = { - { "Esc", "", XK_Escape, 1 }, - { "1", "!", XK_1, 1 }, - { "2", "@", XK_2, 1 }, - { "3", "#", XK_3, 1 }, - { "4", "$", XK_4, 1 }, - { "5", "%", XK_5, 1 }, - { "6", "^", XK_6, 1 }, - { "7", "&", XK_7, 1 }, - { "8", "*", XK_8, 1 }, - { "9", "(", XK_9, 1 }, - { "0", ")", XK_0, 1 }, + { "Esc", "", XKB_KEY_Escape, 1 }, + { "1", "!", XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "0", ")", XKB_KEY_0, 1 }, { 0 }, /* New row */ - { 0, 0, XK_q, 1 }, - { 0, 0, XK_w, 1 }, - { 0, 0, XK_e, 1 }, - { 0, 0, XK_r, 1 }, - { 0, 0, XK_t, 1 }, - { 0, 0, XK_y, 1 }, - { 0, 0, XK_u, 1 }, - { 0, 0, XK_i, 1 }, - { 0, 0, XK_o, 1 }, - { 0, 0, XK_p, 1 }, - { "'", "\"", XK_apostrophe, 1 }, + { "q", 0, XKB_KEY_q, 1 }, + { "w", 0, XKB_KEY_w, 1 }, + { "e", 0, XKB_KEY_e, 1 }, + { "r", 0, XKB_KEY_r, 1 }, + { "t", 0, XKB_KEY_t, 1 }, + { "y", 0, XKB_KEY_y, 1 }, + { "u", 0, XKB_KEY_u, 1 }, + { "i", 0, XKB_KEY_i, 1 }, + { "o", 0, XKB_KEY_o, 1 }, + { "p", 0, XKB_KEY_p, 1 }, + { "'", "\"", XKB_KEY_apostrophe, 1 }, { 0 }, /* New row */ - { 0, 0, XK_a, 1 }, - { 0, 0, XK_s, 1 }, - { 0, 0, XK_d, 1 }, - { 0, 0, XK_f, 1 }, - { 0, 0, XK_g, 1 }, - { 0, 0, XK_h, 1 }, - { 0, 0, XK_j, 1 }, - { 0, 0, XK_k, 1 }, - { 0, 0, XK_l, 1 }, - { "/", "?", XK_slash, 1 }, - { "Tab", 0, XK_Tab, 1 }, + { "a", 0, XKB_KEY_a, 1 }, + { "s", 0, XKB_KEY_s, 1 }, + { "d", 0, XKB_KEY_d, 1 }, + { "f", 0, XKB_KEY_f, 1 }, + { "g", 0, XKB_KEY_g, 1 }, + { "h", 0, XKB_KEY_h, 1 }, + { "j", 0, XKB_KEY_j, 1 }, + { "k", 0, XKB_KEY_k, 1 }, + { "l", 0, XKB_KEY_l, 1 }, + { "/", "?", XKB_KEY_slash, 1 }, + { "Tab", 0, XKB_KEY_Tab, 1 }, { 0 }, /* New row */ - { 0, 0, XK_z, 1 }, - { 0, 0, XK_x, 1 }, - { 0, 0, XK_c, 1 }, - { 0, 0, XK_v, 1 }, - { 0, 0, XK_b, 1 }, - { 0, 0, XK_n, 1 }, - { 0, 0, XK_m, 1 }, - { ",", "<", XK_comma, 1 }, - { ".", ">", XK_period, 1 }, - { "⌫Bksp", 0, XK_BackSpace, 2 }, + { "z", 0, XKB_KEY_z, 1 }, + { "x", 0, XKB_KEY_x, 1 }, + { "c", 0, XKB_KEY_c, 1 }, + { "v", 0, XKB_KEY_v, 1 }, + { "b", 0, XKB_KEY_b, 1 }, + { "n", 0, XKB_KEY_n, 1 }, + { "m", 0, XKB_KEY_m, 1 }, + { ",", "<", XKB_KEY_comma, 1 }, + { ".", ">", XKB_KEY_period, 1 }, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 2 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "Shift", 0, XK_Shift_L, 2 }, - { "Ctrl", 0, XK_Control_L, 1 }, - { "Alt", 0, XK_Alt_L, 1 }, - { "", 0, XK_space, 2 }, - { "↓", 0, XK_Down, 1 }, - { "↑", 0, XK_Up, 1 }, - { "↲ Enter", 0, XK_Return, 2 }, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "Shift", 0, XKB_KEY_Shift_L, 2 }, + { "Ctrl", 0, XKB_KEY_Control_L, 1 }, + { "Alt", 0, XKB_KEY_Alt_L, 1 }, + { "", 0, XKB_KEY_space, 2 }, + { "↓", 0, XKB_KEY_Down, 1 }, + { "↑", 0, XKB_KEY_Up, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, }; #define OVERLAYS 197 static Key overlay[OVERLAYS] = { - { 0, 0, XK_a }, //Overlay for a - //--- - { "à", 0, XK_agrave }, - { "á", 0, XK_aacute }, - { "â", 0, XK_acircumflex }, - { "ä", 0, XK_adiaeresis }, - { "ą", 0, XK_aogonek }, - { "ã", 0, XK_atilde }, - { "ā", 0, XK_amacron }, - { "ă", 0, XK_abreve }, - { "å", 0, XK_aring }, - { "æ", 0, XK_ae }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { 0, 0, XKB_KEY_a }, //Overlay for a + //--- + { "à", 0, XKB_KEY_agrave }, + { "á", 0, XKB_KEY_aacute }, + { "â", 0, XKB_KEY_acircumflex }, + { "ä", 0, XKB_KEY_adiaeresis }, + { "ą", 0, XKB_KEY_aogonek }, + { "ã", 0, XKB_KEY_atilde }, + { "ā", 0, XKB_KEY_amacron }, + { "ă", 0, XKB_KEY_abreve }, + { "å", 0, XKB_KEY_aring }, + { "æ", 0, XKB_KEY_ae }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_e }, //Overlay for e (first item after boundary defines the trigger) - //--- - { "è", 0, XK_egrave }, - { "é", 0, XK_eacute }, - { "ê", 0, XK_ecircumflex }, - { "ë", 0, XK_ediaeresis }, - { "ę", 0, XK_eogonek }, - { "ē", 0, XK_emacron }, - { "ė", 0, XK_eabovedot }, - { 0, 0, XK_Cancel }, + { 0, 0, XKB_KEY_e }, //Overlay for e (first item after boundary defines the trigger) + //--- + { "è", 0, XKB_KEY_egrave }, + { "é", 0, XKB_KEY_eacute }, + { "ê", 0, XKB_KEY_ecircumflex }, + { "ë", 0, XKB_KEY_ediaeresis }, + { "ę", 0, XKB_KEY_eogonek }, + { "ē", 0, XKB_KEY_emacron }, + { "ė", 0, XKB_KEY_eabovedot }, + { 0, 0, XKB_KEY_Cancel }, //-- - { 0, 0, XK_y }, //New overlay + { 0, 0, XKB_KEY_y }, //New overlay //--- - { "ỳ", 0, XK_ygrave }, - { "ý", 0, XK_yacute }, - { "ŷ", 0, XK_ycircumflex }, - { "ÿ", 0, XK_ydiaeresis }, - { 0, 0, XK_Cancel }, + { "ỳ", 0, XKB_KEY_ygrave }, + { "ý", 0, XKB_KEY_yacute }, + { "ŷ", 0, XKB_KEY_ycircumflex }, + { "ÿ", 0, XKB_KEY_ydiaeresis }, + { 0, 0, XKB_KEY_Cancel }, //-- - { 0, 0, XK_u }, //New overlay - //--- - { "ù", 0, XK_ugrave }, - { "ú", 0, XK_uacute }, - { "û", 0, XK_ucircumflex }, - { "ü", 0, XK_udiaeresis }, - { "ų", 0, XK_uogonek }, - { "ū", 0, XK_umacron }, - { "ů", 0, XK_uring}, - { "ŭ", 0, XK_ubreve}, - { "ű", 0, XK_udoubleacute }, - { 0, 0, XK_Cancel }, + { 0, 0, XKB_KEY_u }, //New overlay + //--- + { "ù", 0, XKB_KEY_ugrave }, + { "ú", 0, XKB_KEY_uacute }, + { "û", 0, XKB_KEY_ucircumflex }, + { "ü", 0, XKB_KEY_udiaeresis }, + { "ų", 0, XKB_KEY_uogonek }, + { "ū", 0, XKB_KEY_umacron }, + { "ů", 0, XKB_KEY_uring}, + { "ŭ", 0, XKB_KEY_ubreve}, + { "ű", 0, XKB_KEY_udoubleacute }, + { 0, 0, XKB_KEY_Cancel }, //-- - { 0, 0, XK_i }, //New overlay - //--- - { "ì", 0, XK_igrave }, - { "í", 0, XK_iacute }, - { "î", 0, XK_icircumflex }, - { "ï", 0, XK_idiaeresis }, - { "į", 0, XK_iogonek }, - { "ī", 0, XK_imacron }, - { "ı", 0, XK_idotless }, - { 0, 0, XK_Cancel }, + { 0, 0, XKB_KEY_i }, //New overlay + //--- + { "ì", 0, XKB_KEY_igrave }, + { "í", 0, XKB_KEY_iacute }, + { "î", 0, XKB_KEY_icircumflex }, + { "ï", 0, XKB_KEY_idiaeresis }, + { "į", 0, XKB_KEY_iogonek }, + { "ī", 0, XKB_KEY_imacron }, + { "ı", 0, XKB_KEY_idotless }, + { 0, 0, XKB_KEY_Cancel }, //-- - { 0, 0, XK_o }, //New overlay - //--- - { "ò", 0, XK_ograve }, - { "ó", 0, XK_oacute }, - { "ô", 0, XK_ocircumflex }, - { "ö", 0, XK_odiaeresis }, - { "ǫ", 0, XK_ogonek }, - { "õ", 0, XK_otilde }, - { "ō", 0, XK_omacron }, - { "ø", 0, XK_oslash }, - { "ő", 0, XK_odoubleacute }, - { "œ", 0, XK_oe }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { 0, 0, XKB_KEY_o }, //New overlay + //--- + { "ò", 0, XKB_KEY_ograve }, + { "ó", 0, XKB_KEY_oacute }, + { "ô", 0, XKB_KEY_ocircumflex }, + { "ö", 0, XKB_KEY_odiaeresis }, + { "ǫ", 0, XKB_KEY_ogonek }, + { "õ", 0, XKB_KEY_otilde }, + { "ō", 0, XKB_KEY_omacron }, + { "ø", 0, XKB_KEY_oslash }, + { "ő", 0, XKB_KEY_odoubleacute }, + { "œ", 0, XKB_KEY_oe }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_d }, //New overlay + { 0, 0, XKB_KEY_d }, //New overlay //--- - { "ď", 0, XK_dcaron }, - { "ð", 0, XK_eth }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ď", 0, XKB_KEY_dcaron }, + { "ð", 0, XKB_KEY_eth }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_c }, //New overlay + { 0, 0, XKB_KEY_c }, //New overlay //--- - { "ç", 0, XK_ccedilla }, - { "ĉ", 0, XK_ccircumflex }, - { "č", 0, XK_ccaron }, - { "ć", 0, XK_cacute }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ç", 0, XKB_KEY_ccedilla }, + { "ĉ", 0, XKB_KEY_ccircumflex }, + { "č", 0, XKB_KEY_ccaron }, + { "ć", 0, XKB_KEY_cacute }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_s }, //New overlay + { 0, 0, XKB_KEY_s }, //New overlay //--- - { "ş", 0, XK_scedilla }, - { "ŝ", 0, XK_scircumflex }, - { "š", 0, XK_scaron }, - { "ś", 0, XK_sacute }, - { "ß", 0, XK_ssharp }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ş", 0, XKB_KEY_scedilla }, + { "ŝ", 0, XKB_KEY_scircumflex }, + { "š", 0, XKB_KEY_scaron }, + { "ś", 0, XKB_KEY_sacute }, + { "ß", 0, XKB_KEY_ssharp }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_z }, //New overlay + { 0, 0, XKB_KEY_z }, //New overlay //--- - { "ž", 0, XK_zcaron }, - { "ż", 0, XK_zabovedot }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ž", 0, XKB_KEY_zcaron }, + { "ż", 0, XKB_KEY_zabovedot }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_n }, //New overlay + { 0, 0, XKB_KEY_n }, //New overlay //--- - { "ñ", 0, XK_ntilde }, - { "ń", 0, XK_nacute }, - { "ň", 0, XK_ncaron }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ñ", 0, XKB_KEY_ntilde }, + { "ń", 0, XKB_KEY_nacute }, + { "ň", 0, XKB_KEY_ncaron }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ // - { 0, 0, XK_t }, //New overlay + { 0, 0, XKB_KEY_t }, //New overlay //--- - { "ț", 0, XK_tcedilla }, - { "ť", 0, XK_tcaron }, - { "þ", 0, XK_thorn }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ț", 0, XKB_KEY_tcedilla }, + { "ť", 0, XKB_KEY_tcaron }, + { "þ", 0, XKB_KEY_thorn }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //---- - { 0, 0, XK_g }, //New overlay + { 0, 0, XKB_KEY_g }, //New overlay //--- - { "ĝ", 0, XK_gcircumflex }, - { "ğ", 0, XK_gbreve }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ĝ", 0, XKB_KEY_gcircumflex }, + { "ğ", 0, XKB_KEY_gbreve }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ // - { 0, 0, XK_h }, //New overlay + { 0, 0, XKB_KEY_h }, //New overlay //--- - { "ĥ", 0, XK_hcircumflex }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ĥ", 0, XKB_KEY_hcircumflex }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ // - { 0, 0, XK_j }, //New overlay + { 0, 0, XKB_KEY_j }, //New overlay //--- - { "ĵ", 0, XK_jcircumflex }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ĵ", 0, XKB_KEY_jcircumflex }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_l }, //New overlay + { 0, 0, XKB_KEY_l }, //New overlay //--- - { "ł", 0, XK_lstroke }, - { "ľ", 0, XK_lcaron }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ł", 0, XKB_KEY_lstroke }, + { "ľ", 0, XKB_KEY_lcaron }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { 0, 0, XK_r }, //New overlay + { 0, 0, XKB_KEY_r }, //New overlay //--- - { "ř", 0, XK_rcaron }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ř", 0, XKB_KEY_rcaron }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_softsign }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_softsign }, //New overlay //--- - { "ъ", 0, XK_Cyrillic_hardsign }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ъ", 0, XKB_KEY_Cyrillic_hardsign }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_ie }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_ie }, //New overlay //--- - { "ё", 0, XK_Cyrillic_io }, - { "э", 0, XK_Cyrillic_e }, - { "Є", 0, XK_Ukrainian_ie }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ё", 0, XKB_KEY_Cyrillic_io }, + { "э", 0, XKB_KEY_Cyrillic_e }, + { "Є", 0, XKB_KEY_Ukrainian_ie }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_i }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_i }, //New overlay //--- - { "і", 0, XK_Ukrainian_i }, - { "ї", 0, XK_Ukrainian_yi }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "і", 0, XKB_KEY_Ukrainian_i }, + { "ї", 0, XKB_KEY_Ukrainian_yi }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_u }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_u }, //New overlay //--- - { "ў", 0, XK_Byelorussian_shortu }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ў", 0, XKB_KEY_Byelorussian_shortu }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_shorti }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_shorti }, //New overlay //--- - { "ј", 0, XK_Cyrillic_je }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ј", 0, XKB_KEY_Cyrillic_je }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_el }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_el }, //New overlay //--- - { "љ", 0, XK_Cyrillic_lje }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "љ", 0, XKB_KEY_Cyrillic_lje }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_en }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_en }, //New overlay //--- - { "њ", 0, XK_Cyrillic_nje }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "њ", 0, XKB_KEY_Cyrillic_nje }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_tse }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_tse }, //New overlay //--- - { "џ", 0, XK_Cyrillic_dzhe }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "џ", 0, XKB_KEY_Cyrillic_dzhe }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- - { 0, 0, XK_Cyrillic_che }, //New overlay + { 0, 0, XKB_KEY_Cyrillic_che }, //New overlay //--- - { "ћ", 0, XK_Serbian_tshe }, - { "ђ", 0, XK_Serbian_dje }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "ћ", 0, XKB_KEY_Serbian_tshe }, + { "ђ", 0, XKB_KEY_Serbian_dje }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //--- { "🙂", 0, 0x101f642 }, //emoji overlay //--- @@ -286,264 +286,264 @@ static Key overlay[OVERLAYS] = { { "😭", 0, 0x101f62d }, { "😳", 0, 0x101f633 }, { "😴", 0, 0x101f634 }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ //-- - { "/?", 0, XK_slash }, //punctuation overlay + { "/?", 0, XKB_KEY_slash }, //punctuation overlay //-- - { "1", "!", XK_1, 1 }, - { "2", "@", XK_2, 1 }, - { "3", "#", XK_3, 1 }, - { "4", "$", XK_4, 1 }, - { "5", "%", XK_5, 1 }, - { "6", "^", XK_6, 1 }, - { "7", "&", XK_7, 1 }, - { "8", "*", XK_8, 1 }, - { "9", "(", XK_9, 1 }, - { "0", ")", XK_0, 1 }, - { "'", "\"", XK_apostrophe, 1 }, - { "`", "~", XK_grave, 1 }, - { "-", "_", XK_minus, 1 }, - { "=", "+", XK_plus, 1 }, - { "[", "{", XK_bracketleft, 1 }, - { "]", "}", XK_bracketright, 1 }, - { ",", "<", XK_comma, 1 }, - { ".", ">", XK_period, 1 }, - { "/", "?", XK_slash, 1 }, - { "\\", "|", XK_backslash, 1 }, - { "¡", 0, XK_exclamdown, 1 }, - { "?", 0, XK_questiondown, 1 }, - { "°", 0, XK_degree, 1 }, - { "£", 0, XK_sterling, 1 }, - { "€", 0, XK_EuroSign, 1 }, - { "¥", 0, XK_yen, 1 }, - { ";", ":", XK_colon, 1 }, - { 0, 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ + { "1", "!", XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "0", ")", XKB_KEY_0, 1 }, + { "'", "\"", XKB_KEY_apostrophe, 1 }, + { "`", "~", XKB_KEY_grave, 1 }, + { "-", "_", XKB_KEY_minus, 1 }, + { "=", "+", XKB_KEY_plus, 1 }, + { "[", "{", XKB_KEY_bracketleft, 1 }, + { "]", "}", XKB_KEY_bracketright, 1 }, + { ",", "<", XKB_KEY_comma, 1 }, + { ".", ">", XKB_KEY_period, 1 }, + { "/", "?", XKB_KEY_slash, 1 }, + { "\\", "|", XKB_KEY_backslash, 1 }, + { "¡", 0, XKB_KEY_exclamdown, 1 }, + { "?", 0, XKB_KEY_questiondown, 1 }, + { "°", 0, XKB_KEY_degree, 1 }, + { "£", 0, XKB_KEY_sterling, 1 }, + { "€", 0, XKB_KEY_EuroSign, 1 }, + { "¥", 0, XKB_KEY_yen, 1 }, + { ";", ":", XKB_KEY_colon, 1 }, + { 0, 0, XKB_KEY_Cancel }, /* XKB_KEY_Cancel signifies overlay boundary */ }; static Key keys_symbols[KEYS] = { - { "Esc", 0, XK_Escape, 1 }, - { "F1", 0, XK_F1, 1 }, - { "F2", 0, XK_F2, 1 }, - { "F3", 0, XK_F3, 1 }, - { "F4", 0, XK_F4, 1 }, - { "F5", 0, XK_F5, 1 }, - { "F6", 0, XK_F6, 1 }, - { "F7", 0, XK_F7, 1 }, - { "F8", 0, XK_F8, 1 }, - { "F9", 0, XK_F9, 1 }, - { "F10", 0, XK_F10, 1 }, + { "Esc", 0, XKB_KEY_Escape, 1 }, + { "F1", 0, XKB_KEY_F1, 1 }, + { "F2", 0, XKB_KEY_F2, 1 }, + { "F3", 0, XKB_KEY_F3, 1 }, + { "F4", 0, XKB_KEY_F4, 1 }, + { "F5", 0, XKB_KEY_F5, 1 }, + { "F6", 0, XKB_KEY_F6, 1 }, + { "F7", 0, XKB_KEY_F7, 1 }, + { "F8", 0, XKB_KEY_F8, 1 }, + { "F9", 0, XKB_KEY_F9, 1 }, + { "F10", 0, XKB_KEY_F10, 1 }, { 0 }, /* New row */ - { "'\"", 0, XK_apostrophe, 1 }, - { "1", "!", XK_1, 1 }, - { "2", "@", XK_2, 1 }, - { "3", "#", XK_3, 1 }, - { "4", "$", XK_4, 1 }, - { "5", "%", XK_5, 1 }, - { "6", "^", XK_6, 1 }, - { "7", "&", XK_7, 1 }, - { "8", "*", XK_8, 1 }, - { "9", "(", XK_9, 1 }, - { "0", ")", XK_0, 1 }, + { "'\"", 0, XKB_KEY_apostrophe, 1 }, + { "1", "!", XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "0", ")", XKB_KEY_0, 1 }, { 0 }, /* New row */ - { ".", ">", XK_period, 1 }, - { ",", "<", XK_comma, 1 }, - { "`", "~", XK_grave, 1 }, - { "-", "_", XK_minus, 1 }, - { "=", "+", XK_plus, 1 }, - { "\\", "|", XK_backslash, 1 }, - { ";", ":", XK_colon, 1 }, - { "/", "?", XK_slash, 1 }, - { "[", "{", XK_bracketleft, 1 }, - { "]", "}", XK_bracketright, 1 }, - { "Del", 0, XK_Delete, 1 }, + { ".", ">", XKB_KEY_period, 1 }, + { ",", "<", XKB_KEY_comma, 1 }, + { "`", "~", XKB_KEY_grave, 1 }, + { "-", "_", XKB_KEY_minus, 1 }, + { "=", "+", XKB_KEY_plus, 1 }, + { "\\", "|", XKB_KEY_backslash, 1 }, + { ";", ":", XKB_KEY_colon, 1 }, + { "/", "?", XKB_KEY_slash, 1 }, + { "[", "{", XKB_KEY_bracketleft, 1 }, + { "]", "}", XKB_KEY_bracketright, 1 }, + { "Del", 0, XKB_KEY_Delete, 1 }, { 0 }, /* New row */ - { "abc", 0, XK_Mode_switch, 1 }, + { "abc", 0, XKB_KEY_Mode_switch, 1 }, { "☺", 0, 0x101f642, 1 }, - { "⇤", 0, XK_Home, 1 }, - { "←", 0, XK_Left, 1 }, - { "→", 0, XK_Right, 1 }, - { "⇥", 0, XK_End, 1 }, - { "⇊", 0, XK_Next, 1 }, - { "⇈", 0, XK_Prior, 1 }, - { "Tab", 0, XK_Tab, 1 }, - { "⌫Bksp", 0, XK_BackSpace, 2 }, + { "⇤", 0, XKB_KEY_Home, 1 }, + { "←", 0, XKB_KEY_Left, 1 }, + { "→", 0, XKB_KEY_Right, 1 }, + { "⇥", 0, XKB_KEY_End, 1 }, + { "⇊", 0, XKB_KEY_Next, 1 }, + { "⇈", 0, XKB_KEY_Prior, 1 }, + { "Tab", 0, XKB_KEY_Tab, 1 }, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 2 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "Shift", 0, XK_Shift_L, 2 }, - { "Ctrl", 0, XK_Control_L, 1 }, - { "Alt", 0, XK_Alt_L, 1 }, - { "", 0, XK_space, 2 }, - { "↓", 0, XK_Down, 1 }, - { "↑", 0, XK_Up, 1 }, - { "↲ Enter", 0, XK_Return, 2 }, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "Shift", 0, XKB_KEY_Shift_L, 2 }, + { "Ctrl", 0, XKB_KEY_Control_L, 1 }, + { "Alt", 0, XKB_KEY_Alt_L, 1 }, + { "", 0, XKB_KEY_space, 2 }, + { "↓", 0, XKB_KEY_Down, 1 }, + { "↑", 0, XKB_KEY_Up, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, }; static Key keys_functions[KEYS] = { - { "Esc", 0, XK_Escape, 1 }, - { "▶", 0, XF86XK_AudioPlay, 1 }, - { "●", 0, XF86XK_AudioRecord, 1 }, - { "■", 0, XF86XK_AudioStop, 1 }, - { "◂◂", 0, XF86XK_AudioPrev, 1 }, - { "▸▸", 0, XF86XK_AudioNext, 1 }, - { "♫M", 0, XF86XK_AudioMute, 1 }, - { "♫-", 0, XF86XK_AudioLowerVolume, 1 }, - { "♫+", 0, XF86XK_AudioRaiseVolume, 1 }, - { "☀-", 0, XF86XK_MonBrightnessDown, 1 }, - { "☀+", 0, XF86XK_MonBrightnessUp, 1 }, + { "Esc", 0, XKB_KEY_Escape, 1 }, + { "▶", 0, XKB_KEY_XF86AudioPlay, 1 }, + { "●", 0, XKB_KEY_XF86AudioRecord, 1 }, + { "■", 0, XKB_KEY_XF86AudioStop, 1 }, + { "◂◂", 0, XKB_KEY_XF86AudioPrev, 1 }, + { "▸▸", 0, XKB_KEY_XF86AudioNext, 1 }, + { "♫M", 0, XKB_KEY_XF86AudioMute, 1 }, + { "♫-", 0, XKB_KEY_XF86AudioLowerVolume, 1 }, + { "♫+", 0, XKB_KEY_XF86AudioRaiseVolume, 1 }, + { "☀-", 0, XKB_KEY_XF86MonBrightnessDown, 1 }, + { "☀+", 0, XKB_KEY_XF86MonBrightnessUp, 1 }, { 0 }, /* New row */ - { "≅", 0, XK_KP_Insert, 1 }, - { "Del", 0, XK_Delete, 1 }, - { "⇤", 0, XK_Home, 1 }, - { "←", 0, XK_Left, 1 }, - { "→", 0, XK_Right, 1 }, - { "⇥", 0, XK_End, 1 }, - { "⇊", 0, XK_Next, 1 }, - { "⇈", 0, XK_Prior, 1 }, - { "Tab", 0, XK_Tab, 1 }, - { "⌫Bksp", 0, XK_BackSpace, 2 }, + { "≅", 0, XKB_KEY_KP_Insert, 1 }, + { "Del", 0, XKB_KEY_Delete, 1 }, + { "⇤", 0, XKB_KEY_Home, 1 }, + { "←", 0, XKB_KEY_Left, 1 }, + { "→", 0, XKB_KEY_Right, 1 }, + { "⇥", 0, XKB_KEY_End, 1 }, + { "⇊", 0, XKB_KEY_Next, 1 }, + { "⇈", 0, XKB_KEY_Prior, 1 }, + { "Tab", 0, XKB_KEY_Tab, 1 }, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 2 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "Shift", 0, XK_Shift_L, 2 }, - { "Ctrl", 0, XK_Control_L, 1 }, - { "Alt", 0, XK_Alt_L, 1 }, - { "", 0, XK_space, 2 }, - { "↓", 0, XK_Down, 1 }, - { "↑", 0, XK_Up, 1 }, - { "↲ Enter", 0, XK_Return, 2 }, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "Shift", 0, XKB_KEY_Shift_L, 2 }, + { "Ctrl", 0, XKB_KEY_Control_L, 1 }, + { "Alt", 0, XKB_KEY_Alt_L, 1 }, + { "", 0, XKB_KEY_space, 2 }, + { "↓", 0, XKB_KEY_Down, 1 }, + { "↑", 0, XKB_KEY_Up, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, { 0 }, /* Last item (double 0) */ { 0 }, /* Last item (double 0) */ }; static Key keys_navigation[KEYS] = { - { "Esc", 0, XK_Escape, 1 }, - { "⇤", 0, XK_Home, 1 }, - { "↑", 0, XK_Up, 1 }, - { "⇥", 0, XK_End, 1 }, - { "⇈", 0, XK_Prior, 1 }, + { "Esc", 0, XKB_KEY_Escape, 1 }, + { "⇤", 0, XKB_KEY_Home, 1 }, + { "↑", 0, XKB_KEY_Up, 1 }, + { "⇥", 0, XKB_KEY_End, 1 }, + { "⇈", 0, XKB_KEY_Prior, 1 }, { 0 }, /* New row */ - { "Shift", 0, XK_Shift_L, 1 }, - { "←", 0, XK_Left, 1 }, - { "", 0, XK_space, 1 }, - { "→", 0, XK_Right, 1 }, - { "⇊", 0, XK_Next, 1 }, + { "Shift", 0, XKB_KEY_Shift_L, 1 }, + { "←", 0, XKB_KEY_Left, 1 }, + { "", 0, XKB_KEY_space, 1 }, + { "→", 0, XKB_KEY_Right, 1 }, + { "⇊", 0, XKB_KEY_Next, 1 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "⌫Bksp", 0, XK_BackSpace, 1 }, - { "↓", 0, XK_Down, 1 }, - { "Tab", 0, XK_Tab, 1 }, - { "↲ Enter", 0, XK_Return, 1}, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 1 }, + { "↓", 0, XKB_KEY_Down, 1 }, + { "Tab", 0, XKB_KEY_Tab, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 1}, { 0 }, /* Last item (double 0) */ { 0 }, /* Last item (double 0) */ }; static Key keys_ru[KEYS] = { - { "Esc", 0, XK_Escape, 1 }, - { "1", "!", XK_1, 1 }, - { "2", "@", XK_2, 1 }, - { "3", "#", XK_3, 1 }, - { "4", "$", XK_4, 1 }, - { "5", "%", XK_5, 1 }, - { "6", "^", XK_6, 1 }, - { "7", "&", XK_7, 1 }, - { "8", "*", XK_8, 1 }, - { "9", "(", XK_9, 1 }, - { "0", ")", XK_0, 1 }, + { "Esc", 0, XKB_KEY_Escape, 1 }, + { "1", "!", XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "0", ")", XKB_KEY_0, 1 }, { 0 }, /* New row */ - { "й", 0, XK_Cyrillic_shorti, 1 }, - { "ц", 0, XK_Cyrillic_tse, 1 }, - { "у", 0, XK_Cyrillic_u, 1 }, - { "к", 0, XK_Cyrillic_ka, 1 }, - { "е", 0, XK_Cyrillic_ie, 1 }, - { "н", 0, XK_Cyrillic_en, 1 }, - { "г", 0, XK_Cyrillic_ghe, 1 }, - { "ш", 0, XK_Cyrillic_sha, 1 }, - { "щ", 0, XK_Cyrillic_shcha, 1 }, - { "з", 0, XK_Cyrillic_ze, 1 }, - { "х", 0, XK_Cyrillic_ha, 1 }, + { "й", 0, XKB_KEY_Cyrillic_shorti, 1 }, + { "ц", 0, XKB_KEY_Cyrillic_tse, 1 }, + { "у", 0, XKB_KEY_Cyrillic_u, 1 }, + { "к", 0, XKB_KEY_Cyrillic_ka, 1 }, + { "е", 0, XKB_KEY_Cyrillic_ie, 1 }, + { "н", 0, XKB_KEY_Cyrillic_en, 1 }, + { "г", 0, XKB_KEY_Cyrillic_ghe, 1 }, + { "ш", 0, XKB_KEY_Cyrillic_sha, 1 }, + { "щ", 0, XKB_KEY_Cyrillic_shcha, 1 }, + { "з", 0, XKB_KEY_Cyrillic_ze, 1 }, + { "х", 0, XKB_KEY_Cyrillic_ha, 1 }, { 0 }, /* New row */ - { "ф", 0, XK_Cyrillic_ef, 1 }, - { "ы", 0, XK_Cyrillic_yeru, 1 }, - { "в", 0, XK_Cyrillic_ve, 1 }, - { "а", 0, XK_Cyrillic_a, 1 }, - { "п", 0, XK_Cyrillic_pe, 1 }, - { "р", 0, XK_Cyrillic_er, 1 }, - { "о", 0, XK_Cyrillic_o, 1 }, - { "л", 0, XK_Cyrillic_el, 1 }, - { "д", 0, XK_Cyrillic_de, 1 }, - { "ж", 0, XK_Cyrillic_zhe, 1 }, - { "ю", 0, XK_Cyrillic_yu, 1 }, + { "ф", 0, XKB_KEY_Cyrillic_ef, 1 }, + { "ы", 0, XKB_KEY_Cyrillic_yeru, 1 }, + { "в", 0, XKB_KEY_Cyrillic_ve, 1 }, + { "а", 0, XKB_KEY_Cyrillic_a, 1 }, + { "п", 0, XKB_KEY_Cyrillic_pe, 1 }, + { "р", 0, XKB_KEY_Cyrillic_er, 1 }, + { "о", 0, XKB_KEY_Cyrillic_o, 1 }, + { "л", 0, XKB_KEY_Cyrillic_el, 1 }, + { "д", 0, XKB_KEY_Cyrillic_de, 1 }, + { "ж", 0, XKB_KEY_Cyrillic_zhe, 1 }, + { "ю", 0, XKB_KEY_Cyrillic_yu, 1 }, { 0 }, /* New row */ - { "123", 0, XK_Mode_switch, 1 }, - { "я", 0, XK_Cyrillic_ya, 1 }, - { "ч", 0, XK_Cyrillic_che, 1 }, - { "с", 0, XK_Cyrillic_es, 1 }, - { "м", 0, XK_Cyrillic_em, 1 }, - { "и", 0, XK_Cyrillic_i, 1 }, - { "т", 0, XK_Cyrillic_te, 1 }, - { "ь", 0, XK_Cyrillic_softsign, 1 }, - { "б", 0, XK_Cyrillic_be, 1 }, - { "⌫Bksp", 0, XK_BackSpace, 2 }, + { "123", 0, XKB_KEY_Mode_switch, 1 }, + { "я", 0, XKB_KEY_Cyrillic_ya, 1 }, + { "ч", 0, XKB_KEY_Cyrillic_che, 1 }, + { "с", 0, XKB_KEY_Cyrillic_es, 1 }, + { "м", 0, XKB_KEY_Cyrillic_em, 1 }, + { "и", 0, XKB_KEY_Cyrillic_i, 1 }, + { "т", 0, XKB_KEY_Cyrillic_te, 1 }, + { "ь", 0, XKB_KEY_Cyrillic_softsign, 1 }, + { "б", 0, XKB_KEY_Cyrillic_be, 1 }, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 2 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "Shift", 0, XK_Shift_L, 2 }, - { "Ctrl", 0, XK_Control_L, 1 }, - { "Alt", 0, XK_Alt_L, 1 }, - { "", 0, XK_space, 2 }, - { "↓", 0, XK_Down, 1 }, - { "↑", 0, XK_Up, 1 }, - { "↲ Enter", 0, XK_Return, 2 }, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "Shift", 0, XKB_KEY_Shift_L, 2 }, + { "Ctrl", 0, XKB_KEY_Control_L, 1 }, + { "Alt", 0, XKB_KEY_Alt_L, 1 }, + { "", 0, XKB_KEY_space, 2 }, + { "↓", 0, XKB_KEY_Down, 1 }, + { "↑", 0, XKB_KEY_Up, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, }; static Key keys_dialer[KEYS] = { - { "Esc", 0, XK_Escape, 1 }, - { "1", "!" , XK_1, 1 }, - { "2", "@", XK_2, 1 }, - { "3", "#", XK_3, 1 }, - { "⌫Bksp", 0, XK_BackSpace, 2 }, + { "Esc", 0, XKB_KEY_Escape, 1 }, + { "1", "!" , XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "⌫Bksp", 0, XKB_KEY_BackSpace, 2 }, { 0 }, /* New row */ - { "Shift", 0, XK_Shift_L, 1 }, - { "4", "$", XK_4, 1 }, - { "5", "%", XK_5, 1 }, - { "6", "^", XK_6, 1 }, - { "-", "_", XK_minus, 1 }, - { ",", "<", XK_comma, 1 }, + { "Shift", 0, XKB_KEY_Shift_L, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "-", "_", XKB_KEY_minus, 1 }, + { ",", "<", XKB_KEY_comma, 1 }, { 0 }, /* New row */ - { "abc", 0, XK_Mode_switch, 1 }, - { "7", "&", XK_7, 1 }, - { "8", "*", XK_8, 1 }, - { "9", "(", XK_9, 1 }, - { "=", "+", XK_equal, 1 }, - { "/", "?", XK_slash, 1 }, + { "abc", 0, XKB_KEY_Mode_switch, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "=", "+", XKB_KEY_equal, 1 }, + { "/", "?", XKB_KEY_slash, 1 }, { 0 }, /* New row */ - { "↺", 0, XK_Cancel, 1}, - { "", 0, XK_space, 1 }, - { "0", ")", XK_0, 1 }, - { ".", ">", XK_period, 1 }, - { "↲ Enter", 0, XK_Return, 2}, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "", 0, XKB_KEY_space, 1 }, + { "0", ")", XKB_KEY_0, 1 }, + { ".", ">", XKB_KEY_period, 1 }, + { "↲ Enter", 0, XKB_KEY_Return, 2}, { 0 }, /* New row */ { 0 }, /* Last item (double 0) */ }; @@ -567,6 +567,6 @@ static Key* available_layers[LAYERS] = { Buttonmod buttonmods[] = { - { XK_Shift_L, Button2 }, - { XK_Alt_L, Button3 }, + { XKB_KEY_Shift_L, BTN_RIGHT }, + { XKB_KEY_Alt_L, BTN_MIDDLE }, }; diff --git a/layout.mobile-minimal.h b/layout.mobile-minimal.h @@ -0,0 +1,98 @@ +#define KEYS 44 +static Key keys_en[KEYS] = { + { "q", 0, XKB_KEY_q, 1 }, + { "w", 0, XKB_KEY_w, 1 }, + { "e", 0, XKB_KEY_e, 1 }, + { "r", 0, XKB_KEY_r, 1 }, + { "t", 0, XKB_KEY_t, 1 }, + { "y", 0, XKB_KEY_y, 1 }, + { "u", 0, XKB_KEY_u, 1 }, + { "i", 0, XKB_KEY_i, 1 }, + { "o", 0, XKB_KEY_o, 1 }, + { "p", 0, XKB_KEY_p, 1 }, + + { 0 }, /* New row */ + + { "a", 0, XKB_KEY_a, 1 }, + { "s", 0, XKB_KEY_s, 1 }, + { "d", 0, XKB_KEY_d, 1 }, + { "f", 0, XKB_KEY_f, 1 }, + { "g", 0, XKB_KEY_g, 1 }, + { "h", 0, XKB_KEY_h, 1 }, + { "j", 0, XKB_KEY_j, 1 }, + { "k", 0, XKB_KEY_k, 1 }, + { "l", 0, XKB_KEY_l, 1 }, + { ";",":", XKB_KEY_colon, 1 }, + /*{ "'", XKB_KEY_apostrophe, 2 },*/ + + { 0 }, /* New row */ + + { "Shft", 0, XKB_KEY_Shift_L, 1 }, + { "z", 0, XKB_KEY_z, 1 }, + { "x", 0, XKB_KEY_x, 1 }, + { "c", 0, XKB_KEY_c, 1 }, + { "v", 0, XKB_KEY_v, 1 }, + { "b", 0, XKB_KEY_b, 1 }, + { "n", 0, XKB_KEY_n, 1 }, + { "m", 0, XKB_KEY_m, 1 }, + /*{ "/?", XKB_KEY_slash, 1 },*/ + + { 0 }, /* New row */ + { "⇍ Bksp", 0, XKB_KEY_BackSpace, 2 }, + { "↺", 0, XKB_KEY_Cancel, 1}, + { "", 0, XKB_KEY_space, 2 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, +}; + +static Key keys_symbols[KEYS] = { + { "1", "!", XKB_KEY_1, 1 }, + { "2", "@", XKB_KEY_2, 1 }, + { "3", "#", XKB_KEY_3, 1 }, + { "4", "$", XKB_KEY_4, 1 }, + { "5", "%", XKB_KEY_5, 1 }, + { "6", "^", XKB_KEY_6, 1 }, + { "7", "&", XKB_KEY_7, 1 }, + { "8", "*", XKB_KEY_8, 1 }, + { "9", "(", XKB_KEY_9, 1 }, + { "0", ")", XKB_KEY_0, 1 }, + + { 0 }, /* New row */ + + { "'", "\"", XKB_KEY_apostrophe, 1 }, + { "`", "~", XKB_KEY_grave, 1 }, + { "-", "_", XKB_KEY_minus, 1 }, + { "=", "+", XKB_KEY_plus, 1 }, + { "[", "{", XKB_KEY_bracketleft, 1 }, + { "]", "}", XKB_KEY_bracketright, 1 }, + { ",", "<", XKB_KEY_comma, 1 }, + { ".", ">", XKB_KEY_period, 1 }, + { "/", "?", XKB_KEY_slash, 1 }, + { "\\", "|", XKB_KEY_backslash, 1 }, + + { 0 }, /* New row */ + + { "", 0, XKB_KEY_Shift_L|XKB_KEY_bar, 1 }, + { "⇍ Bksp", 0, XKB_KEY_BackSpace, 2 }, + + { 0 }, /* New row */ + { "↺", 0, XKB_KEY_Cancel, 1}, + { "Shft", 0, XKB_KEY_Shift_L, 1 }, + { "", 0, XKB_KEY_space, 2 }, + { "↲ Enter", 0, XKB_KEY_Return, 2 }, +}; + +#define OVERLAYS 1 +static Key overlay[OVERLAYS] = { + { 0, 0, XKB_KEY_Cancel }, +}; + +#define LAYERS 2 +static char* layer_names[LAYERS] = { + "en", + "symbols", +}; + +static Key* available_layers[LAYERS] = { + keys_en, + keys_symbols, +}; diff --git a/protocol/virtual-keyboard-unstable-v1.xml b/protocol/virtual-keyboard-unstable-v1.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="virtual_keyboard_unstable_v1"> + <copyright> + Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2013 Intel Corporation + Copyright © 2012-2013 Collabora, Ltd. + Copyright © 2018 Purism SPC + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + + <interface name="zwp_virtual_keyboard_v1" version="1"> + <description summary="virtual keyboard"> + The virtual keyboard provides an application with requests which emulate + the behaviour of a physical keyboard. + + This interface can be used by clients on its own to provide raw input + events, or it can accompany the input method protocol. + </description> + + <request name="keymap"> + <description summary="keyboard mapping"> + Provide a file descriptor to the compositor which can be + memory-mapped to provide a keyboard mapping description. + + Format carries a value from the keymap_format enumeration. + </description> + <arg name="format" type="uint" summary="keymap format"/> + <arg name="fd" type="fd" summary="keymap file descriptor"/> + <arg name="size" type="uint" summary="keymap size, in bytes"/> + </request> + + <enum name="error"> + <entry name="no_keymap" value="0" summary="No keymap was set"/> + </enum> + + <request name="key"> + <description summary="key event"> + A key was pressed or released. + The time argument is a timestamp with millisecond granularity, with an + undefined base. All requests regarding a single object must share the + same clock. + + Keymap must be set before issuing this request. + + State carries a value from the key_state enumeration. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="key" type="uint" summary="key that produced the event"/> + <arg name="state" type="uint" summary="physical state of the key"/> + </request> + + <request name="modifiers"> + <description summary="modifier and group state"> + Notifies the compositor that the modifier and/or group state has + changed, and it should update state. + + The client should use wl_keyboard.modifiers event to synchronize its + internal state with seat state. + + Keymap must be set before issuing this request. + </description> + <arg name="mods_depressed" type="uint" summary="depressed modifiers"/> + <arg name="mods_latched" type="uint" summary="latched modifiers"/> + <arg name="mods_locked" type="uint" summary="locked modifiers"/> + <arg name="group" type="uint" summary="keyboard layout"/> + </request> + + <request name="destroy" type="destructor" since="1"> + <description summary="destroy the virtual keyboard keyboard object"/> + </request> + </interface> + + <interface name="zwp_virtual_keyboard_manager_v1" version="1"> + <description summary="virtual keyboard manager"> + A virtual keyboard manager allows an application to provide keyboard + input events as if they came from a physical keyboard. + </description> + + <enum name="error"> + <entry name="unauthorized" value="0" summary="client not authorized to use the interface"/> + </enum> + + <request name="create_virtual_keyboard"> + <description summary="Create a new virtual keyboard"> + Creates a new virtual keyboard associated to a seat. + + If the compositor enables a keyboard to perform arbitrary actions, it + should present an error when an untrusted client requests a new + keyboard. + </description> + <arg name="seat" type="object" interface="wl_seat"/> + <arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/> + </request> + </interface> +</protocol> diff --git a/svkbd.c b/svkbd.c @@ -1,8 +1,9 @@ /* See LICENSE file for copyright and license details. */ -#include <sys/select.h> +#include <poll.h> #include <sys/time.h> #include <ctype.h> +#include <float.h> #include <locale.h> #include <signal.h> #include <stdarg.h> @@ -12,27 +13,21 @@ #include <time.h> #include <unistd.h> -#include <X11/keysym.h> -#include <X11/keysymdef.h> -#include <X11/XF86keysym.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xproto.h> -#include <X11/extensions/XTest.h> -#include <X11/Xft/Xft.h> -#include <X11/Xresource.h> -#ifdef XINERAMA -#include <X11/extensions/Xinerama.h> -#endif +#include <wayland-client.h> +#include <wld/wayland.h> +#include <wld/wld.h> +#include <swc.h> +#include <xkbcommon/xkbcommon.h> +#include <linux/input-event-codes.h> #include "drw.h" #include "util.h" +#include "swc-client-protocol.h" /* macros */ -#define LENGTH(x) (sizeof x / sizeof x[0]) -#define STRINGTOKEYSYM(X) (XStringToKeySym(X)) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X))) +#define LENGTH(x) (sizeof x / sizeof x[0]) +#define STRINGTOKEYSYM(X) (XStringToxkb_keysym_t(X)) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X))) /* enums */ enum { @@ -40,77 +35,59 @@ enum { SchemePressShift, SchemeHighlight, SchemeHighlightShift, SchemeOverlay, SchemeOverlayShift, SchemeLast }; -enum { NetWMWindowType, NetLast }; /* typedefs */ typedef struct { char *label; char *label2; - KeySym keysym; + xkb_keysym_t keysym; unsigned int width; - KeySym modifier; + char *str; + xkb_keysym_t modifier; int x, y, w, h; - Bool pressed; - Bool highlighted; - Bool isoverlay; + bool pressed; + bool highlighted; + bool isoverlay; } Key; typedef struct { - KeySym mod; + xkb_keysym_t mod; unsigned int button; } Buttonmod; /* function declarations */ static void printdbg(const char *fmt, ...); -static void motionnotify(XEvent *e); -static void buttonpress(XEvent *e); -static void buttonrelease(XEvent *e); static void cleanup(void); -static void configurenotify(XEvent *e); static void countrows(); static int countkeys(Key *layer); static void drawkeyboard(void); static void drawkey(Key *k); -static void expose(XEvent *e); static Key *findkey(int x, int y); -static void leavenotify(XEvent *e); -static void press(Key *k, KeySym mod); +static void press(Key *k); static double get_press_duration(); static void run(void); static void setup(void); -static void simulate_keypress(KeySym keysym); -static void simulate_keyrelease(KeySym keysym); +static void simulate_keypress(xkb_keysym_t keysym); +static void simulate_keyrelease(xkb_keysym_t keysym); static void showoverlay(int idx); static void hideoverlay(); static void cyclelayer(); static void setlayer(); static void togglelayer(); -static void unpress(Key *k, KeySym mod); +static void unpress(Key *k); static void updatekeys(); -static void printkey(Key *k, KeySym mod); +static void printkey(Key *k, xkb_keysym_t mod); /* variables */ -static int screen; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ButtonRelease] = buttonrelease, - [ConfigureNotify] = configurenotify, - [Expose] = expose, - [LeaveNotify] = leavenotify, - [MotionNotify] = motionnotify -}; -static Atom netatom[NetLast]; -static Display *dpy; static Drw *drw; -static Window root, win; static Clr* scheme[SchemeLast]; -static Bool running = True, isdock = False; +static bool running = true, isdock = false; static struct timeval pressbegin; static int currentlayer = 0; static int enableoverlays = 1; static int currentoverlay = -1; /* -1 = no overlay */ static int pressonrelease = 1; -static KeySym overlaykeysym = 0; /* keysym for which the overlay is presented */ +static xkb_keysym_t overlaykeysym = 0; /* keysym for which the overlay is presented */ static int releaseprotect = 0; /* set to 1 after overlay is shown, protecting against immediate release */ static int tmp_keycode = 1; static int rows = 0, ww = 0, wh = 0, wx = 0, wy = 0; @@ -124,10 +101,31 @@ static int numkeys = 0; static char *colors[10][2]; /* 10 schemes, 2 colors each */ static char *fonts[] = { 0 }; -static KeySym ispressingkeysym; +static xkb_keysym_t ispressingkeysym; + +bool ispressing = false; +bool sigtermd = false; + +static struct { + int x, y; +} ptrstate; -Bool ispressing = False; -Bool sigtermd = False; +/* we assume that the slot id is at maximum the number of fingers on the screen */ +static struct { + int x, y; + Key *k; +} touchstate[32]; + +static int mon = -1; +static struct wl_display *dpy; +static struct wl_compositor *compositor; +static struct wl_pointer *pointer; +static struct wl_touch *touch; +static struct wl_seat *seat; +static struct wl_surface *surface; +static struct wl_registry *reg; +static struct swc_panel_manager *panelman; +static struct swc_panel *panel; /* configuration, allows nested code to access above variables */ #include "config.h" @@ -140,105 +138,6 @@ static Key keys[KEYS] = { NULL }; static Key* layers[LAYERS]; void -motionnotify(XEvent *e) -{ - XPointerMovedEvent *ev = &e->xmotion; - int i; - int lostfocus = -1; - int gainedfocus = -1; - - for (i = 0; i < numkeys; i++) { - if (keys[i].keysym && ev->x > keys[i].x - && ev->x < keys[i].x + keys[i].w - && ev->y > keys[i].y - && ev->y < keys[i].y + keys[i].h) { - if (keys[i].highlighted != True) { - if (ispressing) { - gainedfocus = i; - } else { - keys[i].highlighted = True; - } - drawkey(&keys[i]); - } - continue; - } else if (keys[i].highlighted == True) { - keys[i].highlighted = False; - drawkey(&keys[i]); - } - } - - for (i = 0; i < numkeys; i++) { - if (!IsModifierKey(keys[i].keysym) && keys[i].pressed == True && lostfocus != gainedfocus) { - printdbg("Pressed key lost focus: %ld\n", keys[i].keysym); - lostfocus = i; - ispressingkeysym = 0; - keys[i].pressed = 0; - drawkey(&keys[i]); - } - } - - if ((lostfocus != -1) && (gainedfocus != -1) && (lostfocus != gainedfocus)) { - printdbg("Clicking new key that gained focus\n"); - press(&keys[gainedfocus], 0); - keys[gainedfocus].pressed = True; - keys[gainedfocus].highlighted = True; - } -} - -void -buttonpress(XEvent *e) -{ - XButtonPressedEvent *ev = &e->xbutton; - Key *k; - KeySym mod = 0; - int i; - - ispressing = True; - - if (!(k = findkey(ev->x, ev->y))) - return; - - if (k->modifier) { - mod = k->modifier; - } else { - for (i = 0; i < LENGTH(buttonmods); i++) { - if (ev->button == buttonmods[i].button) { - mod = buttonmods[i].mod; - break; - } - } - } - press(k, mod); -} - -void -buttonrelease(XEvent *e) -{ - XButtonPressedEvent *ev = &e->xbutton; - Key *k; - KeySym mod = 0; - int i; - - ispressing = False; - - for (i = 0; i < LENGTH(buttonmods); i++) { - if (ev->button == buttonmods[i].button) { - mod = buttonmods[i].mod; - break; - } - } - - if (ev->x < 0 || ev->y < 0) { - unpress(NULL, mod); - } else if ((k = findkey(ev->x, ev->y))) { - if (k->modifier) - unpress(k, k->modifier); - else - unpress(k, mod); - } -} - -void cleanup(void) { int i; @@ -247,23 +146,6 @@ cleanup(void) free(scheme[i]); drw_sync(drw); drw_free(drw); - XSync(dpy, False); - XDestroyWindow(dpy, win); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); -} - -void -configurenotify(XEvent *e) -{ - XConfigureEvent *ev = &e->xconfigure; - - if (ev->window == win && (ev->width != ww || ev->height != wh)) { - ww = ev->width; - wh = ev->height; - drw_resize(drw, ww, wh); - updatekeys(); - } } void @@ -302,11 +184,14 @@ void drawkeyboard(void) { int i; + warn("drawing keyboard..."); + wld_set_target_surface(drw->renderer, drw->surface); for (i = 0; i < numkeys; i++) { if (keys[i].keysym != 0) drawkey(&keys[i]); } + drw_map(drw, surface, 0, 0, ww, wh); } void @@ -315,6 +200,7 @@ drawkey(Key *k) int x, y, w, h; const char *l; + wld_set_target_surface(drw->renderer, drw->surface); int use_scheme = SchemeNorm; if (k->pressed) @@ -323,9 +209,9 @@ drawkey(Key *k) use_scheme = SchemeHighlight; else if (k->isoverlay) use_scheme = SchemeOverlay; - else if ((k->keysym == XK_Return) || - ((k->keysym >= XK_a) && (k->keysym <= XK_z)) || - ((k->keysym >= XK_Cyrillic_io) && (k->keysym <= XK_Cyrillic_hardsign))) + else if ((k->keysym == XKB_KEY_Return) || + ((k->keysym >= XKB_KEY_a) && (k->keysym <= XKB_KEY_z)) || + ((k->keysym >= XKB_KEY_Cyrillic_io) && (k->keysym <= XKB_KEY_Cyrillic_hardsign))) use_scheme = SchemeNormABC; else use_scheme = SchemeNorm; @@ -333,7 +219,7 @@ drawkey(Key *k) drw_setscheme(drw, scheme[use_scheme]); drw_rect(drw, k->x, k->y, k->w, k->h, 1, 1); - if (k->keysym == XK_KP_Insert) { + if (k->keysym == XKB_KEY_KP_Insert) { if (enableoverlays) { l = "≅"; } else { @@ -342,9 +228,9 @@ drawkey(Key *k) } else if (k->label) { l = k->label; } else { - l = XKeysymToString(k->keysym); + warn("key missing label"); } - h = fontsize * 2; + h = drw->fonts[0].wld->height + 10; y = k->y + (k->h / 2) - (h / 2); w = TEXTW(l); x = k->x + (k->w / 2) - (w / 2); @@ -362,21 +248,11 @@ drawkey(Key *k) use_scheme = SchemeOverlayShift; drw_setscheme(drw, scheme[use_scheme]); x += w; - y -= 15; + //y -= 15; l = k->label2; w = TEXTW(l); drw_text(drw, x, y, w, h, 0, l, 0); } - drw_map(drw, win, k->x, k->y, k->w, k->h); -} - -void -expose(XEvent *e) -{ - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (ev->window == win)) - drawkeyboard(); } Key * @@ -394,13 +270,13 @@ findkey(int x, int y) { } int -hasoverlay(KeySym keysym) +hasoverlay(xkb_keysym_t keysym) { int begin, i; begin = 0; for (i = 0; i < OVERLAYS; i++) { - if (overlay[i].keysym == XK_Cancel) { + if (overlay[i].keysym == XKB_KEY_Cancel) { begin = i + 1; } else if (overlay[i].keysym == keysym) { return begin + 1; @@ -410,142 +286,65 @@ hasoverlay(KeySym keysym) } void -leavenotify(XEvent *e) -{ - if (currentoverlay != -1) - hideoverlay(); - ispressingkeysym = 0; - unpress(NULL, 0); -} - -void -record_press_begin(KeySym ks) +record_press_begin(xkb_keysym_t ks) { /* record the begin of the press, don't simulate the actual keypress yet */ gettimeofday(&pressbegin, NULL); ispressingkeysym = ks; } -void -press(Key *k, KeySym buttonmod) -{ - int i; - int overlayidx = -1; - - k->pressed = !k->pressed; - printdbg("Begin click: %ld\n", k->keysym); - pressbegin.tv_sec = 0; - pressbegin.tv_usec = 0; - ispressingkeysym = 0; - - if (!IsModifierKey(k->keysym)) { - if (enableoverlays && currentoverlay == -1) - overlayidx = hasoverlay(k->keysym); - if ((pressonrelease) || (enableoverlays && overlayidx != -1)) { - /*record the begin of the press, don't simulate the actual keypress yet */ - record_press_begin(k->keysym); - } else { - printdbg("Simulating press: %ld (mod %ld)\n", k->keysym, buttonmod); - for (i = 0; i < numkeys; i++) { - if (keys[i].pressed && IsModifierKey(keys[i].keysym)) { - simulate_keypress(keys[i].keysym); - } - } - if (buttonmod) - simulate_keypress(buttonmod); - simulate_keypress(k->keysym); - if (printoutput) - printkey(k, buttonmod); - - for (i = 0; i < numkeys; i++) { - if (keys[i].pressed && IsModifierKey(keys[i].keysym)) { - simulate_keyrelease(keys[i].keysym); - } - } - } - } - drawkey(k); +/* TODO replace with something saner */ +bool +IsModifierKey(int ks) +{ + return (ks >= XKB_KEY_Shift_L && ks <= XKB_KEY_Hyper_R); } -int -tmp_remap(KeySym keysym) +void +press(Key *k) { - XChangeKeyboardMapping(dpy, tmp_keycode, 1, &keysym, 1); - XSync(dpy, False); - - return tmp_keycode; + fprintf(stderr, "pressed key %s\n", k->label); + k->pressed = true; } void -printkey(Key *k, KeySym mod) +printkey(Key *k, xkb_keysym_t mod) { int i, shift; - shift = (mod == XK_Shift_L) || (mod == XK_Shift_R) || (mod == XK_Shift_Lock); + shift = (mod == XKB_KEY_Shift_L) || (mod == XKB_KEY_Shift_R) || (mod == XKB_KEY_Shift_Lock); if (!shift) { for (i = 0; i < numkeys; i++) { - if ((keys[i].pressed) && ((keys[i].keysym == XK_Shift_L) || - (keys[i].keysym == XK_Shift_R) || (keys[i].keysym == XK_Shift_Lock))) { - shift = True; + if ((keys[i].pressed) && ((keys[i].keysym == XKB_KEY_Shift_L) || + (keys[i].keysym == XKB_KEY_Shift_R) || (keys[i].keysym == XKB_KEY_Shift_Lock))) { + shift = true; break; } } } printdbg("Printing key %ld (shift=%d)\n", k->keysym, shift); - if (k->keysym == XK_Cancel) + if (k->keysym == XKB_KEY_Cancel) return; - KeySym *keysym = &(k->keysym); - XIM xim = XOpenIM(dpy, 0, 0, 0); - XIC xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); - - XKeyPressedEvent event; - event.type = KeyPress; - event.display = dpy; - event.state = shift ? ShiftMask : 0; - event.keycode = XKeysymToKeycode(dpy, *keysym); - if (event.keycode == 0) - event.keycode = tmp_remap(*keysym); + xkb_keysym_t *keysym = &(k->keysym); char buffer[32]; - KeySym ignore; - Status return_status; - int l = Xutf8LookupString(xic, &event, buffer, sizeof(buffer), &ignore, &return_status); + xkb_keysym_t ignore; + int l = xkb_keysym_get_name(*keysym, buffer, sizeof(buffer)); buffer[l] = '\0'; printdbg("Print buffer: [%s] (length=%d)\n", &buffer, l); printf("%s", buffer); - - XDestroyIC(xic); - XCloseIM(xim); } void -simulate_keypress(KeySym keysym) +simulate_keypress(xkb_keysym_t keysym) { - KeyCode code; - - if (!simulateoutput) - return; - - code = XKeysymToKeycode(dpy, keysym); - if (code == 0) - code = tmp_remap(keysym); - XTestFakeKeyEvent(dpy, code, True, 0); } void -simulate_keyrelease(KeySym keysym) +simulate_keyrelease(xkb_keysym_t keysym) { - KeyCode code; - - if (!simulateoutput) - return; - - code = XKeysymToKeycode(dpy, keysym); - if (code == 0) - code = tmp_remap(keysym); - XTestFakeKeyEvent(dpy, code, False, 0); } double @@ -561,113 +360,251 @@ get_press_duration(void) } void -unpress(Key *k, KeySym buttonmod) +unpress(Key *k) { + warn("sending...\n"); int i; if (k != NULL) { switch(k->keysym) { - case XK_Cancel: + case XKB_KEY_Cancel: cyclelayer(); break; - case XK_script_switch: + case XKB_KEY_script_switch: togglelayer(); break; - case XK_KP_Insert: + case XKB_KEY_KP_Insert: enableoverlays = !enableoverlays; break; - case XK_Break: - running = False; + case XKB_KEY_Break: + running = false; break; default: break; } + k->pressed = false; } - if ((pressbegin.tv_sec || pressbegin.tv_usec) && (enableoverlays || pressonrelease) && k && k->keysym == ispressingkeysym) { - printdbg("Delayed simulation of press after release: %ld\n", k->keysym); - /* simulate the press event, as we postponed it earlier in press() */ - for (i = 0; i < numkeys; i++) { - if (keys[i].pressed && IsModifierKey(keys[i].keysym)) { - simulate_keypress(keys[i].keysym); + fprintf(stderr, "unpress of %s\n", k->label); +} + +static void +regglobal(void *d, struct wl_registry *r, uint32_t name, const char *interface, uint32_t version) +{ + if (strcmp(interface, "wl_compositor") == 0) + compositor = wl_registry_bind(r, name, &wl_compositor_interface, 1); + else if (strcmp(interface, "wl_seat") == 0) + seat = wl_registry_bind(r, name, &wl_seat_interface, 1); + else if (strcmp(interface, "swc_panel_manager") == 0) + panelman = wl_registry_bind(r, name, &swc_panel_manager_interface, 1); +} + +static void +regglobalremove(void *d, struct wl_registry *reg, uint32_t name) +{ +} + +static const struct wl_registry_listener reglistener = { regglobal, regglobalremove }; + +static void +pointerenter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy) +{ + ptrstate.x = wl_fixed_to_int(sx); + ptrstate.y = wl_fixed_to_int(sy); +} + +static void +pointerleave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) +{ + if (currentoverlay != -1) + hideoverlay(); + ispressingkeysym = 0; + unpress(NULL); +} + +static void +pointermotion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + ptrstate.x = wl_fixed_to_int(sx); + ptrstate.y = wl_fixed_to_int(sy); + int i; + int lostfocus = -1; + int gainedfocus = -1; + + for (i = 0; i < numkeys; i++) { + if (keys[i].keysym && ptrstate.x > keys[i].x + && ptrstate.x < keys[i].x + keys[i].w + && ptrstate.y > keys[i].y + && ptrstate.y < keys[i].y + keys[i].h) { + if (!keys[i].highlighted) { + if (ispressing) { + gainedfocus = i; + } else { + keys[i].highlighted = true; + drawkeyboard(); + } } + continue; + } else if (keys[i].highlighted) { + keys[i].highlighted = false; + drawkeyboard(); } - if (buttonmod) { - simulate_keypress(buttonmod); - } - simulate_keypress(k->keysym); - pressbegin.tv_sec = 0; - pressbegin.tv_usec = 0; } - if (k) - printdbg("Simulation of release: %ld\n", k->keysym); - else - printdbg("Simulation of release (all keys)\n"); - for (i = 0; i < numkeys; i++) { - if (keys[i].pressed && !IsModifierKey(keys[i].keysym)) { - simulate_keyrelease(keys[i].keysym); - if (printoutput) - printkey(&keys[i], buttonmod); - keys[i].pressed = 0; - drawkey(&keys[i]); + if (!IsModifierKey(keys[i].keysym) && keys[i].pressed && lostfocus != gainedfocus) { + printdbg("Pressed key lost focus: %ld\n", keys[i].keysym); + lostfocus = i; + ispressingkeysym = 0; + keys[i].pressed = false; } } - if (buttonmod) { - simulate_keyrelease(buttonmod); + if ((lostfocus != -1) && (gainedfocus != -1) && (lostfocus != gainedfocus)) { + printdbg("Clicking new key that gained focus\n"); + press(&keys[gainedfocus]); + keys[gainedfocus].pressed = true; + keys[gainedfocus].highlighted = true; } +} - if ((k == NULL) || (!IsModifierKey(k->keysym))) { - for (i = 0; i < numkeys; i++) { - if (keys[i].pressed && IsModifierKey(keys[i].keysym)) { - simulate_keyrelease(keys[i].keysym); - keys[i].pressed = 0; - drawkey(&keys[i]); - } - } +void +pointerbutton(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) +{ + Key *k; + int i; + + ispressing = true; + + switch (state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + if ((k = findkey(ptrstate.x, ptrstate.y))) + press(k); + + break; + + case WL_POINTER_BUTTON_STATE_RELEASED: + if ((k = findkey(ptrstate.x, ptrstate.y))) + unpress(k); + break; } +} - if (enableoverlays && currentoverlay != -1 && !IsModifierKey(k->keysym)) { - if (releaseprotect) { - releaseprotect = 0; - } else { - hideoverlay(); - } + +static const struct wl_pointer_listener pointerlistener = { pointerenter, pointerleave, pointermotion, pointerbutton }; + +void +touchdown(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + Key *k; + + ispressing = true; + touchstate[id].x = wl_fixed_to_double(x); + touchstate[id].y = wl_fixed_to_double(y); + + if ((k = findkey(touchstate[id].x, touchstate[id].y))) + press(k); + + touchstate[id].k = k; +} + +void +touchup(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) +{ + /* + Key *k; + if ((k = findkey(touchstate[id].x, touchstate[id].y))) + unpress(k); + touchstate[id].x = DBL_MIN; + touchstate[id].y = DBL_MIN; + touchstate[id].k = NULL; + */ + unpress(touchstate[id].k); + touchstate[id].x = DBL_MIN; + touchstate[id].y = DBL_MIN; + touchstate[id].k = NULL; +} + +void +touchmotion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + Key *k; + touchstate[id].x = wl_fixed_to_double(x); + touchstate[id].y = wl_fixed_to_double(y); + + int i; + int lostfocus = -1; + int gainedfocus = -1; + + if ((k = findkey(touchstate[id].x, touchstate[id].y))) { + if (k == touchstate[id].k) + return; + + if (touchstate[id].k) + touchstate[id].k->pressed = false; + + press(k); + touchstate[id].k = k; + } else if (touchstate[id].k) { + touchstate[id].k->pressed = false; + touchstate[id].k = NULL; } } void +touchframe(void *data, struct wl_touch *wl_touch) +{ + drawkeyboard(); +} + +void +touchcancel(void *data, struct wl_touch *wl_touch) +{ + fprintf(stderr, "cancel!\n"); +} + +static const struct wl_touch_listener touchlistener = { touchdown, touchup, touchmotion, touchframe , touchcancel}; + +static void +panel_docked(void *data, struct swc_panel *panel, uint32_t length) +{ + ww = length; +} + +static const struct swc_panel_listener panellistener = { .docked = &panel_docked }; + +void run(void) { - XEvent ev; - int xfd; - fd_set fds; + struct pollfd fds[2]; struct timeval tv; double duration = 0.0; int overlayidx = -1; int i, r; - xfd = ConnectionNumber(dpy); + fds[0].fd = wl_display_get_fd(dpy); + fds[0].events = POLLIN; + + /* TODO use timer_create to create timer for long presses */ + fds[1].fd = -1; + fds[1].events = POLLIN; tv.tv_sec = 0; tv.tv_usec = scan_rate; - XFlush(dpy); - while (running) { - usleep(100000L); /* 100ms */ - FD_ZERO(&fds); - FD_SET(xfd, &fds); - r = select(xfd + 1, &fds, NULL, NULL, &tv); - if (r) { - while (XPending(dpy)) { - XNextEvent(dpy, &ev); - if (handler[ev.type]) { - (handler[ev.type])(&ev); /* call handler */ - } + if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) { + fprintf(stderr, "poll failed\n"); + break; + } + + if (fds[0].revents & POLLIN) { + if (wl_display_dispatch(dpy) == -1) { + warn("failed to dispatch display:"); + break; } - } else { + } + + if (0) { /* time-out expired without anything interesting happening, check for long-presses */ if (ispressing && ispressingkeysym) { duration = get_press_duration(); @@ -685,7 +622,6 @@ run(void) printdbg("press duration %f, activating repeat\n", duration); simulate_keyrelease(ispressingkeysym); simulate_keypress(ispressingkeysym); - XSync(dpy, False); } } } @@ -698,118 +634,31 @@ run(void) process will be dead before finger lifts - in that case we just trigger out fake up presses for all keys */ printdbg("signal received, releasing all keys"); - for (i = 0; i < numkeys; i++) { - XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), False, 0); - } - running = False; + running = false; } } } void -readxresources(void) -{ - XrmDatabase xdb; - XrmValue xval; - char *type, *xrm; - - XrmInitialize(); - - if ((xrm = XResourceManagerString(drw->dpy))) { - xdb = XrmGetStringDatabase(xrm); - - if (XrmGetResource(xdb, "svkbd.font", "*", &type, &xval) && !fonts[0]) - fonts[0] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.background", "*", &type, &xval) && !colors[SchemeNorm][ColBg]) - colors[SchemeNorm][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.foreground", "*", &type, &xval) && !colors[SchemeNorm][ColFg]) - colors[SchemeNorm][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.shiftforeground", "*", &type, &xval) && !colors[SchemeNormShift][ColFg]) - colors[SchemeNormShift][ColFg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.shiftbackground", "*", &type, &xval) && !colors[SchemeNormShift][ColBg]) - colors[SchemeNormShift][ColBg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.ABCforeground", "*", &type, &xval) && !colors[SchemeNormABC][ColFg]) - colors[SchemeNormABC][ColFg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.ABCbackground", "*", &type, &xval) && !colors[SchemeNormABC][ColBg]) - colors[SchemeNormABC][ColBg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.ABCshiftforeground", "*", &type, &xval) && !colors[SchemeNormShift][ColFg]) - colors[SchemeNormShift][ColFg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.ABCshiftbackground", "*", &type, &xval) && !colors[SchemeNormShift][ColBg]) - colors[SchemeNormShift][ColBg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.pressbackground", "*", &type, &xval) && !colors[SchemePress][ColBg]) - colors[SchemePress][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.pressforeground", "*", &type, &xval) && !colors[SchemePress][ColFg]) - colors[SchemePress][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.pressshiftbackground", "*", &type, &xval) && !colors[SchemePressShift][ColBg]) - colors[SchemePressShift][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.pressshiftforeground", "*", &type, &xval) && !colors[SchemePressShift][ColFg]) - colors[SchemePressShift][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.highlightbackground", "*", &type, &xval) && !colors[SchemeHighlight][ColBg]) - colors[SchemeHighlight][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.highlightforeground", "*", &type, &xval) && !colors[SchemeHighlight][ColFg]) - colors[SchemeHighlight][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.highlightshiftbackground", "*", &type, &xval) && !colors[SchemeHighlightShift][ColBg]) - colors[SchemeHighlightShift][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.highlightshiftforeground", "*", &type, &xval) && !colors[SchemeHighlightShift][ColFg]) - colors[SchemeHighlightShift][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.overlaybackground", "*", &type, &xval) && !colors[SchemeOverlay][ColBg]) - colors[SchemeOverlay][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.overlayforeground", "*", &type, &xval) && !colors[SchemeOverlay][ColFg]) - colors[SchemeOverlay][ColFg] = estrdup(xval.addr); - - if (XrmGetResource(xdb, "svkbd.overlayshiftbackground", "*", &type, &xval) && !colors[SchemeOverlayShift][ColBg]) - colors[SchemeOverlayShift][ColBg] = estrdup(xval.addr); - if (XrmGetResource(xdb, "svkbd.overlayshiftforeground", "*", &type, &xval) && !colors[SchemeOverlayShift][ColFg]) - colors[SchemeOverlayShift][ColFg] = estrdup(xval.addr); - - XrmDestroyDatabase(xdb); - } -} - -void setup(void) { - XSetWindowAttributes wa; - XTextProperty str; - XSizeHints *sizeh = NULL; - XClassHint *ch; - XWMHints *wmh; - Atom atype = -1; - int i, j, sh, sw; - -#ifdef XINERAMA - XineramaScreenInfo *info = NULL; -#endif + int i, j, rh; - /* init screen */ - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - info = XineramaQueryScreens(dpy, &i); - sw = info[0].width; - sh = info[0].height; - XFree(info); - } else -#endif - { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - } - drw = drw_create(dpy, screen, root, sw, sh); + drw = drw_create(dpy); + + if (!compositor || !seat || !panelman) + exit(1); - readxresources(); + pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(pointer, &pointerlistener, NULL); - /* Apply defaults to font and colors*/ + touch = wl_seat_get_touch(seat); + wl_touch_add_listener(touch, &touchlistener, NULL); + + if (!pointer) + exit(1); + + /* Apply defaults to font and colors */ if (!fonts[0]) fonts[0] = estrdup(defaultfonts[0]); for (i = 0; i < SchemeLast; ++i) { @@ -823,34 +672,6 @@ setup(void) die("no fonts could be loaded"); free(fonts[0]); - drw_setscheme(drw, scheme[SchemeNorm]); - - /* find an unused keycode to use as a temporary keycode (derived from source: - https://stackoverflow.com/questions/44313966/c-xtest-emitting-key-presses-for-every-unicode-character) */ - KeySym *keysyms; - int keysyms_per_keycode = 0; - int keycode_low, keycode_high; - Bool key_is_empty; - int symindex; - - XDisplayKeycodes(dpy, &keycode_low, &keycode_high); - keysyms = XGetKeyboardMapping(dpy, keycode_low, keycode_high - keycode_low, &keysyms_per_keycode); - for (i = keycode_low; i <= keycode_high; i++) { - key_is_empty = True; - for (j = 0; j < keysyms_per_keycode; j++) { - symindex = (i - keycode_low) * keysyms_per_keycode + j; - if (keysyms[symindex] != 0) { - key_is_empty = False; - } else { - break; - } - } - if (key_is_empty) { - tmp_keycode = i; - break; - } - } - /* init appearance */ for (j = 0; j < SchemeLast; j++) scheme[j] = drw_scm_create(drw, (const char **) colors[j], 2); @@ -860,76 +681,32 @@ setup(void) free(colors[j][ColBg]); } - /* init atoms */ - if (isdock) { - netatom[NetWMWindowType] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE", False); - atype = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); - } + drw_setscheme(drw, scheme[SchemeNorm]); + + surface = wl_compositor_create_surface(compositor); + panel = swc_panel_manager_create_panel(panelman, surface); + swc_panel_add_listener(panel, &panellistener, NULL); + swc_panel_dock(panel, SWC_PANEL_EDGE_BOTTOM, NULL, 0); + wl_display_roundtrip(dpy); /* init appearance */ countrows(); + /* TODO calculate row height properly */ + rh = drw->fonts[0].wld->height + 15; if (!ww) - ww = sw; + exit(1); if (!wh) - wh = sh * rows / heightfactor; + wh = rh * rows; - if (!wx) - wx = 0; - if (wx < 0) - wx = sw + wx - ww; - if (!wy) - wy = sh - wh; - if (wy < 0) - wy = sh + wy - wh; for (i = 0; i < numkeys; i++) keys[i].pressed = 0; - wa.override_redirect = !wmborder; - wa.border_pixel = scheme[SchemeNorm][ColFg].pixel; - wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - win = XCreateWindow(dpy, root, wx, wy, ww, wh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBorderPixel | - CWBackingPixel, &wa); - XSelectInput(dpy, win, StructureNotifyMask|ButtonReleaseMask| - ButtonPressMask|ExposureMask|LeaveWindowMask| - PointerMotionMask); - - wmh = XAllocWMHints(); - wmh->input = False; - wmh->flags = InputHint; - if (!isdock) { - sizeh = XAllocSizeHints(); - sizeh->flags = PMaxSize | PMinSize; - sizeh->min_width = sizeh->max_width = ww; - sizeh->min_height = sizeh->max_height = wh; - } - XStringListToTextProperty(&name, 1, &str); - ch = XAllocClassHint(); - ch->res_class = name; - ch->res_name = name; - - XSetWMProperties(dpy, win, &str, &str, NULL, 0, sizeh, wmh, ch); - - XFree(keysyms); - XFree(ch); - XFree(wmh); - XFree(str.value); - if (sizeh != NULL) - XFree(sizeh); - - if (isdock) { - XChangeProperty(dpy, win, netatom[NetWMWindowType], XA_ATOM, - 32, PropModeReplace, - (unsigned char *)&atype, 1); - } - - XMapRaised(dpy, win); - drw_resize(drw, ww, wh); + drw_resize(drw, surface, ww, wh); + swc_panel_set_strut(panel, wh, 0, ww); updatekeys(); drawkeyboard(); + wl_display_roundtrip(dpy); } void @@ -960,17 +737,17 @@ usage(char *argv0) { fprintf(stderr, "usage: %s [-hdnovDOR] [-g geometry] [-fn font] [-l layers] [-s initial_layer]\n", argv0); fprintf(stderr, "Options:\n"); - fprintf(stderr, " -d - Set Dock Window Type\n"); - fprintf(stderr, " -D - Enable debug\n"); - fprintf(stderr, " -O - Disable overlays\n"); - fprintf(stderr, " -R - Disable press-on-release\n"); - fprintf(stderr, " -n - Do not simulate key presses for X\n"); - fprintf(stderr, " -o - Print to standard output\n"); - fprintf(stderr, " -l - Comma separated list of layers to enable\n"); - fprintf(stderr, " -s - Layer to select on program start\n"); + fprintf(stderr, " -d - Set Dock Window Type\n"); + fprintf(stderr, " -D - Enable debug\n"); + fprintf(stderr, " -O - Disable overlays\n"); + fprintf(stderr, " -R - Disable press-on-release\n"); + fprintf(stderr, " -n - Do not simulate key presses for X\n"); + fprintf(stderr, " -o - Print to standard output\n"); + fprintf(stderr, " -l - Comma separated list of layers to enable\n"); + fprintf(stderr, " -s - Layer to select on program start\n"); fprintf(stderr, " -H [int] - Height fraction, one key row takes 1/x of the screen height\n"); fprintf(stderr, " -fn [font] - Set font (Xft, e.g: DejaVu Sans:bold:size=20)\n"); - fprintf(stderr, " -g - Set the window position or size using the X geometry format\n"); + fprintf(stderr, " -g - Set the window position or size using the X geometry format\n"); exit(1); } @@ -1019,13 +796,12 @@ showoverlay(int idx) for (i = 0; i < numkeys; i++) { if (keys[i].pressed && !IsModifierKey(keys[i].keysym)) { keys[i].pressed = 0; - drawkey(&keys[i]); break; } } for (i = idx, j=0; i < OVERLAYS; i++, j++) { - if (overlay[i].keysym == XK_Cancel) { + if (overlay[i].keysym == XKB_KEY_Cancel) { break; } while (keys[j].keysym == 0) @@ -1036,14 +812,13 @@ showoverlay(int idx) keys[j].label2 = overlay[i].label2; keys[j].keysym = overlay[i].keysym; keys[j].modifier = overlay[i].modifier; - keys[j].isoverlay = True; + keys[j].isoverlay = true; } currentoverlay = idx; overlaykeysym = ispressingkeysym; releaseprotect = 1; updatekeys(); drawkeyboard(); - XSync(dpy, False); } void @@ -1059,8 +834,8 @@ hideoverlay(void) void sigterm(int signo) { - running = False; - sigtermd = True; + running = false; + sigtermd = true; printdbg("SIGTERM received\n"); } @@ -1103,7 +878,7 @@ init_layers(char *layer_names_list, const char *initial_layer_name) exit(3); } numlayers++; - s = strtok(NULL,","); + s = strtok(NULL, ","); } } setlayer(); @@ -1153,24 +928,12 @@ main(int argc, char *argv[]) if (!strcmp(argv[i], "-v")) { die("svkbd-"VERSION); } else if (!strcmp(argv[i], "-d")) { - isdock = True; + isdock = true; } else if (!strncmp(argv[i], "-g", 2)) { if (i >= argc - 1) usage(argv[0]); - bitm = XParseGeometry(argv[++i], &xr, &yr, &wr, &hr); - if (bitm & XValue) - wx = xr; - if (bitm & YValue) - wy = yr; - if (bitm & WidthValue) - ww = (int)wr; - if (bitm & HeightValue) - wh = (int)hr; - if (bitm & XNegative && wx == 0) - wx = -1; - if (bitm & YNegative && wy == 0) - wy = -1; + /* TODO implement */ } else if (!strcmp(argv[i], "-fn")) { /* font or font set */ if (i >= argc - 1) usage(argv[0]); @@ -1214,14 +977,18 @@ main(int argc, char *argv[]) init_layers(layer_names_list, initial_layer_name); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + if (!setlocale(LC_CTYPE, "")) fprintf(stderr, "warning: no locale support"); - if (!(dpy = XOpenDisplay(0))) + if (!(dpy = wl_display_connect(NULL))) die("cannot open display"); + if (!(reg = wl_display_get_registry(dpy))) + die("cannot get registry"); + wl_registry_add_listener(reg, &reglistener, NULL); + wl_display_roundtrip(dpy); setup(); run(); cleanup(); - XCloseDisplay(dpy); + wl_display_disconnect(dpy); free(layer_names_list); return 0; diff --git a/util.c b/util.c @@ -44,3 +44,20 @@ die(const char *fmt, ...) exit(1); } + +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } +} diff --git a/util.h b/util.h @@ -5,5 +5,6 @@ #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *fmt, ...); +void warn(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); char *estrdup(const char *s);