Added a dialer/numpad keyboard, added the ability to handle layouts with less k… | |
git clone git://git.suckless.org/svkbd | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 4dab556580d2249e3f1597219b9c65bf8660f5e8 | |
parent 99935775afce355bd16964b9a1b96ec35247292a | |
Author: Maarten van Gompel <[email protected]> | |
Date: Sun, 2 Aug 2020 15:46:16 +0200 | |
Added a dialer/numpad keyboard, added the ability to handle layouts with less k… | |
Diffstat: | |
M README | 7 +++++++ | |
M config.def.h | 1 + | |
M layout.sxmo.h | 39 +++++++++++++++++++++++++++++… | |
M svkbd.c | 107 +++++++++++++++++++++++------… | |
4 files changed, 125 insertions(+), 29 deletions(-) | |
--- | |
diff --git a/README b/README | |
@@ -53,6 +53,13 @@ overlay functionality with the ``-O`` flag or by setting the… | |
also a key on the function layer of the keyboard itself to enable/disable this… | |
``≅`` when the overlay functionality is enabled and ``≇`` when not. | |
+Notes | |
+--------- | |
+ | |
+This virtual keyboard does not actually modify the X keyboard layout, it simpl… | |
+(setxkbmap us) being activated. If you use another XKB layout you will get unp… | |
+labels on the virtual keycaps. | |
+ | |
Repository | |
---------- | |
diff --git a/config.def.h b/config.def.h | |
@@ -1,6 +1,7 @@ | |
static const Bool wmborder = True; | |
static int fontsize = 20; | |
static double overlay_delay = 1.0; | |
+static int heightfactor = 16; //one row of keys takes up 1/x of the screen hei… | |
static const char *fonts[] = { | |
"DejaVu Sans:bold:size=20" | |
}; | |
diff --git a/layout.sxmo.h b/layout.sxmo.h | |
@@ -68,7 +68,7 @@ static Key overlay[OVERLAYS] = { | |
{ "æ", XK_ae }, | |
{ 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */ | |
//-- | |
- { 0, XK_e }, //Overlay for e | |
+ { 0, XK_e }, //Overlay for e (first item after boundary defines the tr… | |
//--- | |
{ "è", XK_egrave }, | |
{ "é", XK_eacute }, | |
@@ -465,11 +465,45 @@ static Key keys_ru[KEYS] = { | |
{ "↲ Enter", XK_Return, 2 }, | |
}; | |
-#define LAYERS 4 | |
+static Key keys_dialer[KEYS] = { | |
+ { "Esc", XK_Escape, 1 }, | |
+ { "1!", XK_1, 1 }, | |
+ { "2@", XK_2, 1 }, | |
+ { "3#", XK_3, 1 }, | |
+ { "⌫Bksp", XK_BackSpace, 2 }, | |
+ { 0 }, /* New row */ | |
+ | |
+ { "Shift", XK_Shift_L, 1 }, | |
+ { "4$", XK_4, 1 }, | |
+ { "5%", XK_5, 1 }, | |
+ { "6^", XK_6, 1 }, | |
+ { "-_", XK_minus, 1 }, | |
+ { ",<", XK_comma, 1 }, | |
+ { 0 }, /* New row */ | |
+ | |
+ { "abc", XK_Mode_switch, 1 }, | |
+ { "7&", XK_7, 1 }, | |
+ { "8*", XK_8, 1 }, | |
+ { "9(", XK_9, 1 }, | |
+ { "=+", XK_equal, 1 }, | |
+ { "/?", XK_slash, 1 }, | |
+ { 0 }, /* New row */ | |
+ | |
+ { "↺", XK_Cancel, 1}, | |
+ { "", XK_space, 1 }, | |
+ { "0)", XK_0, 1 }, | |
+ { ".>", XK_period, 1 }, | |
+ { "↲ Enter", XK_Return, 2}, | |
+ { 0 }, /* New row */ | |
+ { 0 }, /* Last item (double 0) */ | |
+}; | |
+ | |
+#define LAYERS 5 | |
static char* layer_names[LAYERS] = { | |
"en", | |
"symbols", | |
"functions", | |
+ "dialer", | |
"ru", | |
}; | |
@@ -477,6 +511,7 @@ static Key* available_layers[LAYERS] = { | |
keys_en, | |
keys_symbols, | |
keys_functions, | |
+ keys_dialer, | |
keys_ru | |
}; | |
diff --git a/svkbd.c b/svkbd.c | |
@@ -63,6 +63,7 @@ static void buttonrelease(XEvent *e); | |
static void cleanup(void); | |
static void configurenotify(XEvent *e); | |
static void countrows(); | |
+static int countkeys(Key *k); | |
static void drawkeyboard(void); | |
static void drawkey(Key *k); | |
static void expose(XEvent *e); | |
@@ -77,6 +78,7 @@ static void simulate_keyrelease(KeySym 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 updatekeys(); | |
@@ -109,6 +111,7 @@ static int rows = 0, ww = 0, wh = 0, wx = 0, wy = 0; | |
static char *name = "svkbd"; | |
static int debug = 0; | |
static int numlayers = 0; | |
+static int numkeys = 0; | |
static KeySym ispressingkeysym; | |
@@ -130,7 +133,7 @@ motionnotify(XEvent *e) | |
XPointerMovedEvent *ev = &e->xmotion; | |
int i; | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ 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 | |
@@ -221,7 +224,7 @@ cleanup(void) { | |
} | |
} | |
if (debug) { printf("Cleanup: simulating key release\n"); fflu… | |
- for (i = 0; i < LENGTH(keys); i++) { | |
+ for (i = 0; i < numkeys; i++) { | |
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].k… | |
} | |
} | |
@@ -253,18 +256,34 @@ void | |
countrows() { | |
int i = 0; | |
- for(i = 0, rows = 1; i < LENGTH(keys); i++) { | |
+ for(i = 0, rows = 1; i < numkeys; i++) { | |
if(keys[i].keysym == 0) | |
rows++; | |
} | |
} | |
+int | |
+countkeys(Key * layer) { | |
+ int keys = 0; | |
+ int i; | |
+ | |
+ for(i = 0; i < KEYS; i++) { | |
+ if (i > 0 && layer[i].keysym == 0 && layer[i-1].keysym == 0) { | |
+ keys--; | |
+ break; | |
+ } | |
+ keys++; | |
+ } | |
+ | |
+ return keys; | |
+} | |
+ | |
void | |
drawkeyboard(void) { | |
int i; | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].keysym != 0) | |
drawkey(&keys[i]); | |
} | |
@@ -315,7 +334,7 @@ Key * | |
findkey(int x, int y) { | |
int i; | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].keysym && x > keys[i].x && | |
x < keys[i].x + keys[i].w && | |
y > keys[i].y && y < keys[i].y + keys[i].h) { | |
@@ -375,7 +394,7 @@ press(Key *k, KeySym mod) { | |
} | |
} else { | |
if (debug) { printf("Simulating press: %ld\n", k->keys… | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed && IsModifierKey(keys[i].ke… | |
simulate_keypress(keys[i].keysym); | |
} | |
@@ -386,7 +405,7 @@ press(Key *k, KeySym mod) { | |
} | |
simulate_keypress(k->keysym); | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed && IsModifierKey(keys[i].ke… | |
simulate_keyrelease(keys[i].keysym); | |
} | |
@@ -457,7 +476,7 @@ unpress(Key *k, KeySym mod) { | |
if (get_press_duration() < overlay_delay) { | |
if (debug) { printf("Delayed simulation of pre… | |
//simulate the press event, as we postponed it… | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed && IsModifierKey(ke… | |
simulate_keypress(keys[i].keys… | |
} | |
@@ -484,7 +503,7 @@ unpress(Key *k, KeySym mod) { | |
} | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed && !IsModifierKey(keys[i].keysym)) { | |
simulate_keyrelease(keys[i].keysym); | |
keys[i].pressed = 0; | |
@@ -492,13 +511,13 @@ unpress(Key *k, KeySym mod) { | |
break; | |
} | |
} | |
- if(i != LENGTH(keys)) { | |
+ if(i != numkeys) { | |
if(pressedmod) { | |
simulate_keyrelease(mod); | |
} | |
pressedmod = 0; | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed) { | |
simulate_keyrelease(keys[i].keysym); | |
keys[i].pressed = 0; | |
@@ -634,7 +653,7 @@ setup(void) { | |
if(!ww) | |
ww = sw; | |
if(!wh) | |
- wh = sh * rows / 32; | |
+ wh = sh * rows / heightfactor; | |
if(!wx) | |
wx = 0; | |
@@ -645,7 +664,7 @@ setup(void) { | |
if(wy < 0) | |
wy = sh + wy - wh; | |
- for(i = 0; i < LENGTH(keys); i++) | |
+ for(i = 0; i < numkeys; i++) | |
keys[i].pressed = 0; | |
wa.override_redirect = !wmborder; | |
@@ -702,10 +721,10 @@ updatekeys() { | |
int x = 0, y = 0, h, base, r = rows; | |
h = (wh - 1) / rows; | |
- for(i = 0; i < LENGTH(keys); i++, r--) { | |
- for(j = i, base = 0; j < LENGTH(keys) && keys[j].keysym != 0; … | |
+ for(i = 0; i < numkeys; i++, r--) { | |
+ for(j = i, base = 0; j < numkeys && keys[j].keysym != 0; j++) | |
base += keys[j].width; | |
- for(x = 0; i < LENGTH(keys) && keys[i].keysym != 0; i++) { | |
+ for(x = 0; i < numkeys && keys[i].keysym != 0; i++) { | |
keys[i].x = x; | |
keys[i].y = y; | |
keys[i].w = keys[i].width * (ww - 1) / base; | |
@@ -720,23 +739,30 @@ updatekeys() { | |
void | |
usage(char *argv0) { | |
- fprintf(stderr, "usage: %s [-hdvDOl] [-g geometry] [-fn font]\n", argv… | |
+ fprintf(stderr, "usage: %s [-hdvDO] [-g geometry] [-fn font] [-l layer… | |
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, " -l - Comma separated list of layers to enab… | |
+ fprintf(stderr, " -s - Layer to select on program start\n"); | |
+ fprintf(stderr, " -H [int] - Height fraction, one key row tak… | |
fprintf(stderr, " -fn [font] - Set font (Xft, e.g: DejaVu Sans:bold:s… | |
exit(1); | |
} | |
+void setlayer() { | |
+ numkeys = countkeys(layers[currentlayer]); | |
+ memcpy(&keys, layers[currentlayer], sizeof(Key) * numkeys); | |
+} | |
+ | |
void | |
cyclelayer() { | |
currentlayer++; | |
if (currentlayer >= numlayers) | |
currentlayer = 0; | |
if (debug) { printf("Cycling to layer %d\n", currentlayer); fflush(std… | |
- memcpy(&keys, layers[currentlayer], sizeof(keys_en)); | |
+ setlayer(); | |
updatekeys(); | |
drawkeyboard(); | |
} | |
@@ -749,7 +775,7 @@ togglelayer() { | |
currentlayer = 1; | |
} | |
if (debug) { printf("Toggling layer %d\n", currentlayer); fflush(stdou… | |
- memcpy(&keys, layers[currentlayer], sizeof(keys_en)); | |
+ setlayer(); | |
updatekeys(); | |
drawkeyboard(); | |
} | |
@@ -760,7 +786,7 @@ showoverlay(int idx) { | |
if (debug) { printf("Showing overlay %d\n", idx); fflush(stdout); } | |
int i,j; | |
//unpress existing key (visually only) | |
- for(i = 0; i < LENGTH(keys); i++) { | |
+ for(i = 0; i < numkeys; i++) { | |
if(keys[i].pressed && !IsModifierKey(keys[i].keysym)) { | |
keys[i].pressed = 0; | |
drawkey(&keys[i]); | |
@@ -804,21 +830,32 @@ sigterm(int sig) | |
void | |
-init_layers(char * layer_names_list) { | |
+init_layers(char * layer_names_list, const char * initial_layer_name) { | |
+ int j; | |
if (layer_names_list == NULL) { | |
numlayers = LAYERS; | |
memcpy(&layers, &available_layers, sizeof(available_layers)); | |
+ if (initial_layer_name != NULL) { | |
+ for (j = 0; j < LAYERS; j++) { | |
+ if (strcmp(layer_names[j], initial_layer_name)… | |
+ currentlayer = j; | |
+ break; | |
+ } | |
+ } | |
+ } | |
} else { | |
char * s; | |
- int j; | |
s = strtok(layer_names_list, ","); | |
while (s != NULL) { | |
if (numlayers+1 > LAYERS) die("too many layers specifi… | |
int found = 0; | |
for (j = 0; j < LAYERS; j++) { | |
if (strcmp(layer_names[j], s) == 0) { | |
+ fprintf(stderr, "Adding layer %s\n", s… | |
layers[numlayers] = available_layers[j… | |
- printf("Adding layer %s\n", s); | |
+ if (initial_layer_name != NULL && strc… | |
+ currentlayer = numlayers; | |
+ } | |
found = 1; | |
break; | |
} | |
@@ -831,17 +868,19 @@ init_layers(char * layer_names_list) { | |
s = strtok(NULL,","); | |
} | |
} | |
+ setlayer(); | |
} | |
int | |
main(int argc, char *argv[]) { | |
int i, xr, yr, bitm; | |
unsigned int wr, hr; | |
+ char * initial_layer_name = NULL; | |
char * layer_names_list = NULL; | |
- memcpy(&keys, &keys_en, sizeof(keys_en)); | |
signal(SIGTERM, sigterm); | |
+ //parse environment variables | |
const char* enableoverlays_env = getenv("SVKBD_ENABLEOVERLAYS"); | |
if (enableoverlays_env != NULL) enableoverlays = atoi(enableoverlays_e… | |
const char* layers_env = getenv("SVKBD_LAYERS"); | |
@@ -849,8 +888,11 @@ main(int argc, char *argv[]) { | |
layer_names_list = malloc(128); | |
strcpy(layer_names_list, layers_env); | |
} | |
+ const char* heightfactor_s = getenv("SVKBD_HEIGHTFACTOR"); | |
+ if (heightfactor_s != NULL) | |
+ heightfactor = atoi(heightfactor_s); | |
- | |
+ //parse command line arguments | |
for (i = 1; argv[i]; i++) { | |
if(!strcmp(argv[i], "-v")) { | |
die("svkbd-"VERSION", © 2006-2020 svkbd engineers," | |
@@ -888,11 +930,22 @@ main(int argc, char *argv[]) { | |
if(i >= argc - 1) | |
continue; | |
if (layer_names_list == NULL) layer_names_list = mallo… | |
- strcpy(layer_names_list, argv[i+1]); | |
+ strcpy(layer_names_list, argv[++i]); | |
+ } else if(!strcmp(argv[i], "-s")) { | |
+ if(i >= argc - 1) | |
+ continue; | |
+ initial_layer_name = argv[++i]; | |
+ } else if(!strcmp(argv[i], "-H")) { | |
+ if(i >= argc - 1) | |
+ continue; | |
+ heightfactor = atoi(argv[++i]); | |
+ } else { | |
+ fprintf(stderr, "Invalid argument: %s\n", argv[i]); | |
+ exit(2); | |
} | |
} | |
- init_layers(layer_names_list); | |
+ init_layers(layer_names_list, initial_layer_name); | |
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) | |
fprintf(stderr, "warning: no locale support\n"); |