Introduction
Introduction Statistics Contact Development Disclaimer Help
Added overlays (appearing on long press), multiple layer support (rather than j…
git clone git://git.suckless.org/svkbd
Log
Files
Refs
README
LICENSE
---
commit 48994f125e2fdaee15f0724e4f97c24443f9eb96
parent b488ae6410567d64a48eb676f7038c68f3eb0cc2
Author: Maarten van Gompel <[email protected]>
Date: Sun, 2 Aug 2020 15:46:14 +0200
Added overlays (appearing on long press), multiple layer support (rather than j…
Diffstat:
M config.def.h | 9 +++++----
M layout.sxmo.h | 291 +++++++++++++++++++++++++++++…
M svkbd.c | 338 +++++++++++++++++++++++++++--…
3 files changed, 582 insertions(+), 56 deletions(-)
---
diff --git a/config.def.h b/config.def.h
@@ -1,11 +1,12 @@
static const Bool wmborder = True;
-static int fontsize = 16;
+static int fontsize = 20;
+static double overlay_delay = 1.0;
static const char *fonts[] = {
- "monospace:size=16"
+ "DejaVu Sans:bold:size=20"
};
static const char *colors[SchemeLast][2] = {
/* fg bg */
- [SchemeNorm] = { "#58a7c6", "#14313d" },
- [SchemePress] = { "#ffffff", "#005577" },
+ [SchemeNorm] = { "#ffffff", "#14313d" },
+ [SchemePress] = { "#ffffff", "#000000" },
[SchemeHighlight] = { "#58a7c6", "#005577" },
};
diff --git a/layout.sxmo.h b/layout.sxmo.h
@@ -1,6 +1,7 @@
-static Key keys[40] = { NULL };
+#define KEYS 40
+static Key keys[KEYS] = { NULL };
-static Key keys_en[40] = {
+static Key keys_en[KEYS] = {
{ 0, XK_q, 1 },
{ 0, XK_w, 1 },
{ 0, XK_e, 1 },
@@ -23,7 +24,7 @@ static Key keys_en[40] = {
{ 0, XK_j, 1 },
{ 0, XK_k, 1 },
{ 0, XK_l, 1 },
- { ";:", XK_colon, 1 },
+ { "/?", XK_slash, 1 },
/*{ "'", XK_apostrophe, 2 },*/
{ 0 }, /* New row */
@@ -37,7 +38,7 @@ static Key keys_en[40] = {
{ 0, XK_m, 1 },
/*{ "/?", XK_slash, 1 },*/
{ "Tab", XK_Tab, 1 },
- { "⇍ Bksp", XK_BackSpace, 2 },
+ { "⌫Bksp", XK_BackSpace, 2 },
{ 0 }, /* New row */
{ "↺", XK_Cancel, 1},
@@ -53,7 +54,214 @@ static Key keys_en[40] = {
{ "↲ Enter", XK_Return, 2 },
};
-static Key keys_symbols[40] = {
+#define OVERLAYS 165
+static Key overlay[OVERLAYS] = {
+ { 0, XK_a }, //Overlay for a
+ //---
+ { "à", XK_agrave },
+ { "á", XK_aacute },
+ { "â", XK_acircumflex },
+ { "ä", XK_adiaeresis },
+ { "ą", XK_aogonek },
+ { "ã", XK_atilde },
+ { "ā", XK_amacron },
+ { "ă", XK_abreve },
+ { "å", XK_aring },
+ { "æ", XK_ae },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_e }, //Overlay for e
+ //---
+ { "è", XK_egrave },
+ { "é", XK_eacute },
+ { "ê", XK_ecircumflex },
+ { "ë", XK_ediaeresis },
+ { "ę", XK_eogonek },
+ { "ē", XK_emacron },
+ { "ė", XK_eabovedot },
+ { 0, XK_Cancel },
+ //--
+ { 0, XK_y }, //New overlay
+ //---
+ { "ỳ", XK_ygrave },
+ { "ý", XK_yacute },
+ { "ŷ", XK_ycircumflex },
+ { "ÿ", XK_ydiaeresis },
+ { 0, XK_Cancel },
+ //--
+ { 0, XK_u }, //New overlay
+ //---
+ { "ù", XK_ugrave },
+ { "ú", XK_uacute },
+ { "û", XK_ucircumflex },
+ { "ü", XK_udiaeresis },
+ { "ų", XK_uogonek },
+ { "ū", XK_umacron },
+ { "ů", XK_uring},
+ { "ŭ", XK_ubreve},
+ { "ű", XK_udoubleacute },
+ { 0, XK_Cancel },
+ //--
+ { 0, XK_i }, //New overlay
+ //---
+ { "ì", XK_igrave },
+ { "í", XK_iacute },
+ { "î", XK_icircumflex },
+ { "ï", XK_idiaeresis },
+ { "į", XK_iogonek },
+ { "ī", XK_imacron },
+ { "ı", XK_idotless },
+ { 0, XK_Cancel },
+ //--
+ { 0, XK_o }, //New overlay
+ //---
+ { "ò", XK_ograve },
+ { "ó", XK_oacute },
+ { "ô", XK_ocircumflex },
+ { "ö", XK_odiaeresis },
+ { "ǫ", XK_ogonek },
+ { "õ", XK_otilde },
+ { "ō", XK_omacron },
+ { "ø", XK_oslash },
+ { "ő", XK_odoubleacute },
+ { "œ", XK_oe },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_d }, //New overlay
+ //---
+ { "ď", XK_dcaron },
+ { "ð", XK_eth },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_c }, //New overlay
+ //---
+ { "ç", XK_ccedilla },
+ { "ĉ", XK_ccircumflex },
+ { "č", XK_ccaron },
+ { "ć", XK_cacute },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_s }, //New overlay
+ //---
+ { "ş", XK_scedilla },
+ { "ŝ", XK_scircumflex },
+ { "š", XK_scaron },
+ { "ś", XK_sacute },
+ { "ß", XK_ssharp },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //---
+ { 0, XK_z }, //New overlay
+ //---
+ { "ž", XK_zcaron },
+ { "ż", XK_zabovedot },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_n }, //New overlay
+ //---
+ { "ñ", XK_ntilde },
+ { "ń", XK_nacute },
+ { "ň", XK_ncaron },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //
+ { 0, XK_t }, //New overlay
+ //---
+ { "ț", XK_tcedilla },
+ { "ť", XK_tcaron },
+ { "þ", XK_thorn },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //----
+ { 0, XK_g }, //New overlay
+ //---
+ { "ĝ", XK_gcircumflex },
+ { "ğ", XK_gbreve },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //
+ { 0, XK_h }, //New overlay
+ //---
+ { "ĥ", XK_hcircumflex },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //
+ { 0, XK_j }, //New overlay
+ //---
+ { "ĵ", XK_jcircumflex },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_l }, //New overlay
+ //---
+ { "ł", XK_lstroke },
+ { "ľ", XK_lcaron },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { 0, XK_r }, //New overlay
+ //---
+ { "ř", XK_rcaron },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //---
+ { "🙂", 0x101f642 }, //emoji overlay
+ //---
+ { "😀", 0x101f600 },
+ { "😁", 0x101f601 },
+ { "😂", 0x101f602 },
+ { "😃", 0x101f603 },
+ { "😄", 0x101f604 },
+ { "😅", 0x101f605 },
+ { "😆", 0x101f606 },
+ { "😇", 0x101f607 },
+ { "😈", 0x101f608 },
+ { "😉", 0x101f609 },
+ { "😊", 0x101f60a },
+ { "😋", 0x101f60b },
+ { "😌", 0x101f60c },
+ { "😍", 0x101f60d },
+ { "😎", 0x101f60e },
+ { "😏", 0x101f60f },
+ { "😐", 0x101f610 },
+ { "😒", 0x101f612 },
+ { "😓", 0x101f613 },
+ { "😛", 0x101f61b },
+ { "😮", 0x101f62e },
+ { "😟", 0x101f61f },
+ { "😟", 0x101f620 },
+ { "😢", 0x101f622 },
+ { "😭", 0x101f62d },
+ { "😳", 0x101f633 },
+ { "😴", 0x101f634 },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+ //--
+ { "/?", XK_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 },
+ { "¡", XK_exclamdown, 1 },
+ { "?", XK_questiondown, 1 },
+ { "°", XK_degree, 1 },
+ { "£", XK_sterling, 1 },
+ { "€", XK_EuroSign, 1 },
+ { "¥", XK_yen, 1 },
+ { ";:", XK_colon, 1 },
+ { 0, XK_Cancel }, /* XK_Cancel signifies overlay boundary */
+};
+
+
+static Key keys_symbols[KEYS] = {
{ "1!", XK_1, 1 },
{ "2@", XK_2, 1 },
{ "3#", XK_3, 1 },
@@ -80,7 +288,55 @@ static Key keys_symbols[40] = {
{ 0 }, /* New row */
- { "", XK_Shift_L|XK_bar, 1 },
+ { "☺", 0x101f642, 1 },
+ { "⇤", XK_Home, 1 },
+ { "←", XK_Left, 1 },
+ { "→", XK_Right, 1 },
+ { "⇥", XK_End, 1 },
+ { "⇊", XK_Next, 1 },
+ { ";:", XK_colon, 1 },
+ { "Tab", XK_Tab, 1 },
+ { "⌫Bksp", XK_BackSpace, 2 },
+
+ { 0 }, /* New row */
+ { "↺", XK_Cancel, 1},
+ { "Shft", XK_Shift_L, 1 },
+ { "↓", XK_Down, 1 },
+ { "↑", XK_Up, 1 },
+ { "", XK_space, 2 },
+ { "Esc", XK_Escape, 1 },
+ { "Ctrl", XK_Control_L, 1 },
+ { "↲ Enter", XK_Return, 2 },
+};
+
+static Key keys_functions[KEYS] = {
+ { "F1", XK_F1, 1 },
+ { "F2", XK_F2, 1 },
+ { "F3", XK_F3, 1 },
+ { "F4", XK_F4, 1 },
+ { "F5", XK_F5, 1 },
+ { "F6", XK_F6, 1 },
+ { "F7", XK_F7, 1 },
+ { "F8", XK_F8, 1 },
+ { "F9", XK_F9, 1 },
+ { "F10", XK_F10, 1 },
+
+ { 0 }, /* New row */
+
+ { "▶", XF86XK_AudioPlay, 1 },
+ { "●", XF86XK_AudioRecord, 1 },
+ { "■", XF86XK_AudioStop, 1 },
+ { "◂◂", XF86XK_AudioPrev, 1 },
+ { "▸▸", XF86XK_AudioNext, 1 },
+ { "♫M", XF86XK_AudioMute, 1 },
+ { "♫-", XF86XK_AudioLowerVolume, 1 },
+ { "♫+", XF86XK_AudioRaiseVolume, 1 },
+ { "☀-", XF86XK_MonBrightnessDown, 1 },
+ { "☀+", XF86XK_MonBrightnessUp, 1 },
+
+ { 0 }, /* New row */
+
+ { "Del", XK_Delete, 1 },
{ "⇤", XK_Home, 1 },
{ "←", XK_Left, 1 },
{ "→", XK_Right, 1 },
@@ -88,22 +344,37 @@ static Key keys_symbols[40] = {
{ "⇊", XK_Next, 1 },
{ "⇈", XK_Prior, 1 },
{ "Tab", XK_Tab, 1 },
- { "⇍ Bksp", XK_BackSpace, 2 },
+ { "⌫Bksp", XK_BackSpace, 2 },
{ 0 }, /* New row */
{ "↺", XK_Cancel, 1},
{ "Shft", XK_Shift_L, 1 },
- /*{ "L", XK_Left, 1 },*/
{ "↓", XK_Down, 1 },
{ "↑", XK_Up, 1 },
- /*{ "R", XK_Right, 1 },*/
{ "", XK_space, 2 },
{ "Esc", XK_Escape, 1 },
{ "Ctrl", XK_Control_L, 1 },
- /*{ "Alt", XK_Alt_L, 1 },*/
{ "↲ Enter", XK_Return, 2 },
};
+
+#define LAYERS 3
+static Key* layers[LAYERS] = {
+ keys_en,
+ keys_symbols,
+ keys_functions,
+};
+
+
+#define CYCLEMODKEY (KEYS - 3) //third last key (Escape)
+#define CYCLEMODS 3
+static Key cyclemods[CYCLEMODS] = {
+ { "Esc", XK_Escape, 1 },
+ { "Alt", XK_Alt_L, 1 },
+ { "AGr", XK_ISO_Level3_Shift, 1 },
+};
+
+
Buttonmod buttonmods[] = {
{ XK_Shift_L, Button2 },
{ XK_Alt_L, Button3 },
diff --git a/svkbd.c b/svkbd.c
@@ -8,6 +8,8 @@
#include <string.h>
#include <stdlib.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>
@@ -18,16 +20,19 @@
#include <X11/extensions/Xinerama.h>
#endif
#include <signal.h>
+#include <time.h>
+#include <unistd.h>
#include <sys/select.h>
+#include <sys/time.h>
#include "drw.h"
#include "util.h"
-
/* macros */
#define LENGTH(x) (sizeof x / sizeof x[0])
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)))
+#define STRINGTOKEYSYM(X) (XStringToKeySym(X))
/* enums */
enum { SchemeNorm, SchemePress, SchemeHighlight, SchemeLast };
@@ -62,11 +67,18 @@ static void drawkeyboard(void);
static void drawkey(Key *k);
static void expose(XEvent *e);
static Key *findkey(int x, int y);
+static int iscyclemod(KeySym keysym);
static void leavenotify(XEvent *e);
static void press(Key *k, KeySym mod);
+static double get_press_duration();
static void run(void);
static void setup(void);
-static void togglelayer();
+static void simulate_keypress(KeySym keysym);
+static void simulate_keyrelease(KeySym keysym);
+static void showoverlay(int idx);
+static void cyclemod();
+static void hideoverlay();
+static void cyclelayer();
static void unpress(Key *k, KeySym mod);
static void updatekeys();
@@ -87,11 +99,20 @@ static Window root, win;
static Clr* scheme[SchemeLast];
static Bool running = True, isdock = False;
static KeySym pressedmod = 0;
+static struct timeval pressbegin;
+static int currentlayer = 0;
+static int currentoverlay = -1; // -1 = no overlay
+static int currentcyclemod = 0;
+static KeySym overlaykeysym = 0; //keysym for which the overlay is presented
+static int releaseprotect = 0; //set to 1 after overlay is shown, protecting a…
+static int tmp_keycode = 1;
static int rows = 0, ww = 0, wh = 0, wx = 0, wy = 0;
static char *name = "svkbd";
+static int debug = 0;
+
+static KeySym ispressingkeysym;
Bool ispressing = False;
-Bool baselayer = True;
Bool sigtermd = False;
/* configuration, allows nested code to access above variables */
@@ -287,43 +308,126 @@ findkey(int x, int y) {
}
+int
+hasoverlay(KeySym keysym) {
+ int begin, i;
+ begin = 0;
+ for(i = 0; i < OVERLAYS; i++) {
+ if(overlay[i].keysym == XK_Cancel) {
+ begin = i+1;
+ } else if(overlay[i].keysym == keysym) {
+ return begin+1;
+ }
+ }
+ return -1;
+}
+
+int
+iscyclemod(KeySym keysym) {
+ int i;
+ for(i = 0; i < CYCLEMODS; i++) {
+ if(cyclemods[i].keysym == keysym) {
+ return i;
+ }
+ }
+ return -1;
+}
void
leavenotify(XEvent *e) {
+ if (currentoverlay != -1) {
+ hideoverlay();
+ }
unpress(NULL, 0);
}
+void record_press_begin(KeySym ks) {
+ //record the begin of the press, don't simulate the actual keypress yet
+ gettimeofday(&pressbegin, NULL);
+ ispressingkeysym = ks;
+}
+
void
press(Key *k, KeySym mod) {
int i;
+ int overlayidx = -1;
k->pressed = !k->pressed;
- if(!IsModifierKey(k->keysym)) {
- for(i = 0; i < LENGTH(keys); i++) {
- if(keys[i].pressed && IsModifierKey(keys[i].keysym)) {
- XTestFakeKeyEvent(dpy,
- XKeysymToKeycode(dpy, keys[i].keysym),
- True, 0);
- }
- }
- pressedmod = mod;
- if(pressedmod) {
- XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, mod),
- True, 0);
+ if (debug) { printf("Begin press: %ld\n", k->keysym); fflush(stdout); }
+ pressbegin.tv_sec = 0;
+ pressbegin.tv_usec = 0;
+ ispressingkeysym = 0;
+
+ int cm = iscyclemod(k->keysym);
+ if (cm != -1) {
+ if (!pressbegin.tv_sec && !pressbegin.tv_usec) {
+ //record the begin of the press, don't simulate the ac…
+ record_press_begin(k->keysym);
}
- XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, k->keysym), True,…
+ } else if(!IsModifierKey(k->keysym)) {
+ if (currentoverlay == -1)
+ overlayidx = hasoverlay(k->keysym);
+ if (overlayidx != -1) {
+ if (!pressbegin.tv_sec && !pressbegin.tv_usec) {
+ //record the begin of the press, don't simulat…
+ record_press_begin(k->keysym);
+ }
+ } else {
+ if (debug) { printf("Simulating press: %ld\n", k->keys…
+ for(i = 0; i < LENGTH(keys); i++) {
+ if(keys[i].pressed && IsModifierKey(keys[i].ke…
+ simulate_keypress(keys[i].keysym);
+ }
+ }
+ pressedmod = mod;
+ if(pressedmod) {
+ simulate_keypress(mod);
+ }
+ simulate_keypress(k->keysym);
- for(i = 0; i < LENGTH(keys); i++) {
- if(keys[i].pressed && IsModifierKey(keys[i].keysym)) {
- XTestFakeKeyEvent(dpy,
- XKeysymToKeycode(dpy, keys[i].keysym),
- False, 0);
+ for(i = 0; i < LENGTH(keys); i++) {
+ if(keys[i].pressed && IsModifierKey(keys[i].ke…
+ simulate_keyrelease(keys[i].keysym);
+ }
}
}
}
drawkey(k);
}
+
+
+
+
+int tmp_remap(KeySym keysym) {
+ XChangeKeyboardMapping(dpy, tmp_keycode, 1, &keysym, 1);
+ XSync(dpy, False);
+ return tmp_keycode;
+}
+
+void
+simulate_keypress(KeySym keysym) {
+ KeyCode code = XKeysymToKeycode(dpy, keysym);
+ if (code == 0)
+ code = tmp_remap(keysym);
+ XTestFakeKeyEvent(dpy, code, True, 0);
+}
+
+void
+simulate_keyrelease(KeySym keysym) {
+ KeyCode code = XKeysymToKeycode(dpy, keysym);
+ if (code == 0)
+ code = tmp_remap(keysym);
+ XTestFakeKeyEvent(dpy, code, False, 0);
+}
+
+
+double get_press_duration() {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return (double) ((now.tv_sec * 1000000L + now.tv_usec) - (pressbegin.t…
+}
+
void
unpress(Key *k, KeySym mod) {
int i;
@@ -331,7 +435,7 @@ unpress(Key *k, KeySym mod) {
if(k != NULL) {
switch(k->keysym) {
case XK_Cancel:
- togglelayer();
+ cyclelayer();
break;
case XK_Break:
running = False;
@@ -340,11 +444,42 @@ unpress(Key *k, KeySym mod) {
}
}
+
+ if ((pressbegin.tv_sec || pressbegin.tv_usec) && k && k->keysym == isp…
+ if (currentoverlay == -1) {
+ 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++) {
+ if(keys[i].pressed && IsModifierKey(ke…
+ simulate_keypress(keys[i].keys…
+ }
+ }
+ pressedmod = mod;
+ if(pressedmod) {
+ simulate_keypress(mod);
+ }
+ simulate_keypress(k->keysym);
+ pressbegin.tv_sec = 0;
+ pressbegin.tv_usec = 0;
+ } else {
+ return;
+ }
+ }
+ }
+
+ if (debug) {
+ if (k) {
+ printf("Simulation of release: %ld\n", k->keysym); ffl…
+ } else {
+ printf("Simulation of release (all keys)"); fflush(std…
+ }
+ }
+
+
for(i = 0; i < LENGTH(keys); i++) {
if(keys[i].pressed && !IsModifierKey(keys[i].keysym)) {
- XTestFakeKeyEvent(dpy,
- XKeysymToKeycode(dpy, keys[i].keysym),
- False, 0);
+ simulate_keyrelease(keys[i].keysym);
keys[i].pressed = 0;
drawkey(&keys[i]);
break;
@@ -352,22 +487,26 @@ unpress(Key *k, KeySym mod) {
}
if(i != LENGTH(keys)) {
if(pressedmod) {
- XTestFakeKeyEvent(dpy,
- XKeysymToKeycode(dpy, pressedmod),
- False, 0);
+ simulate_keyrelease(mod);
}
pressedmod = 0;
for(i = 0; i < LENGTH(keys); i++) {
if(keys[i].pressed) {
- XTestFakeKeyEvent(dpy,
- XKeysymToKeycode(dpy,
- keys[i].keysym), False, 0);
+ simulate_keyrelease(keys[i].keysym);
keys[i].pressed = 0;
drawkey(&keys[i]);
}
}
}
+
+ if (currentoverlay != -1) {
+ if (releaseprotect) {
+ releaseprotect = 0;
+ } else {
+ hideoverlay();
+ }
+ }
}
void
@@ -376,11 +515,14 @@ run(void) {
int xfd;
fd_set fds;
struct timeval tv;
+ double duration = 0.0;
+ int cyclemodidx;
xfd = ConnectionNumber(dpy);
tv.tv_usec = 0;
- tv.tv_sec = 2;
+ tv.tv_sec = 1;
+
//XSync(dpy, False);
XFlush(dpy);
@@ -395,7 +537,25 @@ run(void) {
(handler[ev.type])(&ev); /* call handl…
}
}
+ } else {
+ if (ispressing && ispressingkeysym) {
+ duration = get_press_duration();
+ if (debug == 2) { printf("%f\n", duration); ff…
+ if (get_press_duration() >= overlay_delay) {
+ if (debug) { printf("press duration %f…
+ cyclemodidx = iscyclemod(ispressingkey…
+ if (cyclemodidx != -1) {
+ cyclemod();
+ } else {
+ showoverlay(hasoverlay(ispress…
+ }
+ pressbegin.tv_sec = 0;
+ pressbegin.tv_usec = 0;
+ ispressingkeysym = 0;
+ }
+ }
}
+ usleep(100000L);
}
}
@@ -428,10 +588,34 @@ setup(void) {
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
}
- drw = drw_create(dpy, screen, root, sw, sh);
+ drw = drw_create(dpy, screen, root, sw, sh);
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
- drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+
+ //find an unused keycode to use as a temporary keycode (derived from s…
+ KeySym *keysyms = NULL;
+ 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…
+ 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++)
@@ -467,9 +651,9 @@ setup(void) {
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);
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWBorderPixel |
+ CWBackingPixel, &wa);
XSelectInput(dpy, win, StructureNotifyMask|ButtonReleaseMask|
ButtonPressMask|ExposureMask|LeaveWindowMask|
PointerMotionMask);
@@ -491,6 +675,7 @@ setup(void) {
XSetWMProperties(dpy, win, &str, &str, NULL, 0, sizeh, wmh,
ch);
+ XFree(keysyms);
XFree(ch);
XFree(wmh);
XFree(str.value);
@@ -534,18 +719,84 @@ updatekeys() {
void
usage(char *argv0) {
- fprintf(stderr, "usage: %s [-hdv] [-g geometry]\n", argv0);
+ fprintf(stderr, "usage: %s [-hdvD] [-g geometry] [-fn font]\n", argv0);
exit(1);
}
void
-togglelayer() {
- memcpy(&keys, baselayer ? &keys_symbols : &keys_en, sizeof(keys_en));
+cyclelayer() {
+ currentlayer++;
+ if (currentlayer >= LAYERS)
+ currentlayer = 0;
+ if (debug) { printf("Cycling to layer %d\n", currentlayer); fflush(std…
+ memcpy(&keys, layers[currentlayer], sizeof(keys_en));
+ updatekeys();
+ drawkeyboard();
+}
+
+void
+cyclemod() {
+ int i;
+ //unpress all pressed keys
+ for(i = 0; i < LENGTH(keys); i++) {
+ if(keys[i].pressed) {
+ keys[i].pressed = 0;
+ drawkey(&keys[i]);
+ }
+ }
+ pressedmod = 0;
+ pressbegin.tv_sec = 0;
+ pressbegin.tv_usec = 0;
+ ispressingkeysym = 0;
+ currentcyclemod++;
+ if (currentcyclemod >= CYCLEMODS)
+ currentcyclemod = 0;
+ if (debug) { printf("Cycling modifier to %d\n", currentcyclemod); fflu…
+ keys[CYCLEMODKEY].label = cyclemods[currentcyclemod].label;
+ keys[CYCLEMODKEY].keysym = cyclemods[currentcyclemod].keysym;
+ drawkey(&keys[CYCLEMODKEY]);
+ XSync(dpy, False);
+}
+
+void
+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++) {
+ 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) {
+ break;
+ }
+ while (keys[j].keysym == 0) j++;
+ keys[j].label = overlay[i].label;
+ keys[j].keysym = overlay[i].keysym;
+ }
+ currentoverlay = idx;
+ overlaykeysym = ispressingkeysym;
+ releaseprotect = 1;
updatekeys();
drawkeyboard();
- baselayer = !baselayer;
+ XSync(dpy, False);
+}
+
+void
+hideoverlay() {
+ if (debug) { printf("Hiding overlay %d\n", currentoverlay); fflush(std…
+ currentoverlay = -1;
+ overlaykeysym = 0;
+ currentlayer = -1;
+ cyclelayer();
}
+
void
sigterm(int sig)
{
@@ -585,6 +836,10 @@ main(int argc, char *argv[]) {
if(bitm & YNegative && wy == 0)
wy = -1;
i++;
+ } else if (!strcmp(argv[i], "-fn")) { /* font or font set */
+ fonts[0] = argv[++i];
+ } else if(!strcmp(argv[i], "-D")) {
+ debug = 1;
} else if(!strcmp(argv[i], "-h")) {
usage(argv[0]);
}
@@ -600,4 +855,3 @@ main(int argc, char *argv[]) {
XCloseDisplay(dpy);
return 0;
}
-
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.