---
 README        |  63 ++++++++++++++++---
 layout.sxmo.h | 168 ++++++++++++++++++++++++++++++++++++++++----------
 svkbd.c       | 165 ++++++++++++++++++++++++++++++++-----------------
 3 files changed, 297 insertions(+), 99 deletions(-)

diff --git a/README b/README
index f1f2b82..fd0e4d9 100644
--- a/README
+++ b/README
@@ -1,5 +1,6 @@
-SVKBD
-=====
+SVKBD: Simple Virtual Keyboard
+=================================
+
 This is a simple virtual keyboard, intended to be used in environments,
 where no keyboard is available.
 
@@ -9,34 +10,76 @@ Installation
        $ make
        $ make install
 
-This will create by default `svkbd-en`, which is svkbd using an English
-keyboard layout. You can create svkbd for additional layouts by doing:
+This will create by default `svkbd-intl`, which is svkbd using an international
+layout with multiple layers and overlays, and optimised for mobile devices.
+
+You can create svkbd for additional layouts by doing:
 
        $ make LAYOUT=$layout
 
 This will take the file `layout.$layout.h` and create `svkbd-$layout`.
 `make install` will then pick up the new file and install it accordingly.
 
+Layouts
+---------
+
+The following layouts are available:
+
+* **Mobile Layouts:**
+    * ``intl`` - A small international layout optimised for mobile devices. 
This layout consists of multiple layers which
+        can be switched on the fly, and overlays that appear on long-press of 
certain keys, adding input ability for
+        diacritics and other variants, as well as some emoji. The layers are:
+        * a basic qwerty layer
+        * a layer for numeric input, arrows, and punctuation
+        * a layer for function keys, media keys, and arrows
+        * a cyrillic layer (ЙЦУКЕН)
+        * a dialer/numeric layer
+    * ``sxmo`` - This is the original English layout for 
[sxmo](https://sr.ht/~mil/Sxmo) with only a qwerty layer and 
numeric/punctuation layer.
+* **Traditional layouts**:
+    * ``en`` - An english layout without layers (QWERTY)
+    * ``de`` - A german layout (QWERTZ)
+    * ``ru`` - A russian layout (ЙЦУКЕН)
+    * ``sh`` - A serbo-croatian layout using latin script (QWERTZ)
+
 Usage
 -----
 
-       $ svkbd-en
+       $ svkbd-intl
 
 This will open svkbd at the bottom of the screen, showing the default
-English layout.
+international layout.
 
-       $ svkbd-en -d
+       $ svkbd-intl -d
 
-This tells svkbd-en to announce itself being a dock window, which then
+This tells svkbd to announce itself being a dock window, which then
 is managed differently between different window managers. If using dwm
 and the dock patch, then this will make svkbd being managed by dwm and
 some space of the screen being reserved for it.
 
-       $ svkbd-en -g 400x200+1+1
+       $ svkbd-intl -g 400x200+1+1
 
-This will start svkbd-en with a size of 400x200 and at the upper left
+This will start svkbd-intl with a size of 400x200 and at the upper left
 window corner.
 
+For layouts that consist of multiple layers, you can enable layers on program 
start through either the ``-l`` flag or
+through the ``SVKBD_LAYERS`` environment variable.  They both take a comma 
separated list of layer names (as defined in
+your ``layout.*.h``). Use the ``↺`` button in the bottom-left to cycle through 
all the layers.
+
+Some layouts come with overlays that will show when certain keys are hold 
pressed for a longer time. For
+example, a long press on the ``a`` key will enable an overview showing all 
kinds of diacritic combinations for ``a``.
+
+Overlay functionality interferes with the ability to hold a key and have it 
outputted repeatedly.  You can disable
+overlay functionality with the ``-O`` flag or by setting the environment 
variable ``SVKBD_ENABLEOVERLAYS=0``. There is
+also a key on the function layer of the keyboard itself to enable/disable this 
behaviour on the fly. Its label shows
+``≅`` when the overlay functionality is enabled and ``≇`` when not.
+
+Notes
+---------
+
+This virtual keyboard does not actually modify the X keyboard layout, the 
``intl``, ``sxmo`` and ``en`` layouts simply rely on a standard US QWERTY 
layout (setxkbmap us) being activated, the other layouts (``de``, ``ru``, 
``sh``) require their respective XKB keymaps to be active.
+
+If you use another XKB layout you will get unpredictable output that does not 
match the labels on the virtual keycaps!
+
 Repository
 ----------
 
diff --git a/layout.sxmo.h b/layout.sxmo.h
index 2ca0727..f036fd6 100644
--- a/layout.sxmo.h
+++ b/layout.sxmo.h
@@ -1,7 +1,8 @@
-#define KEYS 40
+#define KEYS 43
 static Key keys[KEYS] = { NULL };
 
 static Key keys_en[KEYS] = {
+        { "Esc", XK_Escape, 1 },
         { 0, XK_q, 1 },
         { 0, XK_w, 1 },
         { 0, XK_e, 1 },
@@ -15,6 +16,7 @@ static Key keys_en[KEYS] = {
 
         { 0 }, /* New row */
 
+        { "'\"", XK_apostrophe, 1 },
         { 0, XK_a, 1 },
         { 0, XK_s, 1 },
         { 0, XK_d, 1 },
@@ -25,10 +27,10 @@ static Key keys_en[KEYS] = {
         { 0, XK_k, 1 },
         { 0, XK_l, 1 },
         { "/?", XK_slash, 1 },
-        /*{ "'", XK_apostrophe, 2 },*/
 
         { 0 }, /* New row */
 
+        { "123", XK_Mode_switch, 1 },
         { 0, XK_z, 1 },
         { 0, XK_x, 1 },
         { 0, XK_c, 1 },
@@ -36,25 +38,21 @@ static Key keys_en[KEYS] = {
         { 0, XK_b, 1 },
         { 0, XK_n, 1 },
         { 0, XK_m, 1 },
-        /*{ "/?", XK_slash, 1 },*/
         { "Tab", XK_Tab, 1 },
         { "⌫Bksp", XK_BackSpace, 2 },
 
         { 0 }, /* New row */
         { "↺", XK_Cancel, 1},
-        { "Shft", XK_Shift_L, 1 },
-        /*{ "L", XK_Left, 1 },*/
+        { "Shift", XK_Shift_L, 2 },
+        { "Ctrl", XK_Control_L, 1 },
+        { "Alt", XK_Alt_L, 1 },
+        { "", XK_space, 2 },
         { "↓", 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 OVERLAYS 165
+#define OVERLAYS 197
 static Key overlay[OVERLAYS] = {
         { 0, XK_a }, //Overlay for a
         //---
@@ -195,6 +193,58 @@ static Key overlay[OVERLAYS] = {
         { 0, XK_r }, //New overlay
         //---
         { "ř", XK_rcaron },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+        //---
+        { 0, XK_Cyrillic_softsign }, //New overlay
+        //---
+        { "ъ", XK_Cyrillic_hardsign },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+        //---
+        { 0, XK_Cyrillic_ie }, //New overlay
+        //---
+        { "ё", XK_Cyrillic_io },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+        //---
+        { 0, XK_Cyrillic_e }, //New overlay
+        //---
+        { "Є", XK_Ukrainian_ie },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+        //---
+        { 0, XK_Cyrillic_i }, //New overlay
+        //---
+        { "і", XK_Ukrainian_i },
+        { "ї", XK_Ukrainian_yi },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+        //---
+        { 0, XK_Cyrillic_u }, //New overlay
+        //---
+        { "ў", XK_Byelorussian_shortu },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+               //---
+        { 0, XK_Cyrillic_shorti }, //New overlay
+        //---
+        { "ј", XK_Cyrillic_je },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+               //---
+        { 0, XK_Cyrillic_el }, //New overlay
+        //---
+        { "љ", XK_Cyrillic_lje },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+               //---
+        { 0, XK_Cyrillic_en }, //New overlay
+        //---
+        { "њ", XK_Cyrillic_nje },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+               //---
+        { 0, XK_Cyrillic_tse }, //New overlay
+        //---
+        { "џ", XK_Cyrillic_dzhe },
+        { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
+               //---
+        { 0, XK_Cyrillic_che }, //New overlay
+        //---
+        { "ћ", XK_Serbian_tshe },
+        { "ђ", XK_Serbian_dje },
         { 0, XK_Cancel }, /* XK_Cancel signifies  overlay boundary */
                //---
         { "🙂", 0x101f642 }, //emoji overlay
@@ -262,6 +312,7 @@ static Key overlay[OVERLAYS] = {
 
 
 static Key keys_symbols[KEYS] = {
+  { "Esc", XK_Escape, 1 },
   { "1!", XK_1, 1 },
   { "2@", XK_2, 1 },
   { "3#", XK_3, 1 },
@@ -285,31 +336,34 @@ static Key keys_symbols[KEYS] = {
   { ".>", XK_period, 1 },
   { "/?", XK_slash, 1 },
   { "\\|", XK_backslash, 1 },
+  { ";:", XK_colon, 1 },
 
   { 0 }, /* New row */
 
+  { "abc", XK_Mode_switch, 1 },
   { "☺", 0x101f642, 1 },
   { "⇤", XK_Home, 1 },
   { "←", XK_Left, 1 },
   { "→", XK_Right, 1 },
   { "⇥", XK_End, 1 },
   { "⇊", XK_Next, 1 },
-  { ";:", XK_colon, 1 },
+  { "⇈", XK_Prior, 1 },
   { "Tab", XK_Tab, 1 },
   { "⌫Bksp", XK_BackSpace, 2 },
 
   { 0 }, /* New row */
   { "↺", XK_Cancel, 1},
-  { "Shft", XK_Shift_L, 1 },
+  { "Shift", XK_Shift_L, 2 },
+  { "Ctrl", XK_Control_L, 1 },
+  { "Alt", XK_Alt_L, 1 },
+  { "", XK_space, 2 },
   { "↓", 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] = {
+  { "Esc", XK_Escape, 1 },
   { "F1", XK_F1, 1 },
   { "F2", XK_F2, 1 },
   { "F3", XK_F3, 1 },
@@ -323,6 +377,7 @@ static Key keys_functions[KEYS] = {
 
   { 0 }, /* New row */
 
+  { "≅", XK_KP_Insert, 1 },
   { "▶", XF86XK_AudioPlay, 1 },
   { "●", XF86XK_AudioRecord, 1 },
   { "■", XF86XK_AudioStop, 1 },
@@ -336,6 +391,7 @@ static Key keys_functions[KEYS] = {
 
   { 0 }, /* New row */
 
+  { "abc", XK_Mode_switch, 1 },
   { "Del", XK_Delete, 1 },
   { "⇤", XK_Home, 1 },
   { "←", XK_Left, 1 },
@@ -348,30 +404,80 @@ static Key keys_functions[KEYS] = {
 
   { 0 }, /* New row */
   { "↺", XK_Cancel, 1},
-  { "Shft", XK_Shift_L, 1 },
+  { "Shift", XK_Shift_L, 2 },
+  { "Ctrl", XK_Control_L, 1 },
+  { "Alt", XK_Alt_L, 1 },
+  { "", XK_space, 2 },
   { "↓", XK_Down, 1 },
   { "↑", XK_Up, 1 },
-  { "", XK_space, 2 },
-  { "Esc", XK_Escape, 1 },
-  { "Ctrl", XK_Control_L, 1 },
   { "↲ Enter", XK_Return, 2 },
 };
 
 
-#define LAYERS 3
-static Key* layers[LAYERS] = {
-    keys_en,
-    keys_symbols,
-    keys_functions,
+static Key keys_ru[KEYS] = {
+        { "и", XK_Cyrillic_shorti, 1 },
+        { "ц", XK_Cyrillic_tse, 1 },
+        { "у", XK_Cyrillic_u, 1 },
+        { "к", XK_Cyrillic_ka, 1 },
+        { "е", XK_Cyrillic_ie, 1 },
+        { "н", XK_Cyrillic_en, 1 },
+        { "г", XK_Cyrillic_ghe, 1 },
+        { "ш", XK_Cyrillic_sha, 1 },
+        { "щ", XK_Cyrillic_shcha, 1 },
+        { "з", XK_Cyrillic_ze, 1 },
+        { "х", XK_Cyrillic_ha, 1 },
+
+        { 0 }, /* New row */
+
+        { "ф", XK_Cyrillic_ef, 1 },
+        { "ы", XK_Cyrillic_yeru, 1 },
+        { "в", XK_Cyrillic_ve, 1 },
+        { "а", XK_Cyrillic_a, 1 },
+        { "п", XK_Cyrillic_pe, 1 },
+        { "о", XK_Cyrillic_o, 1 },
+        { "л", XK_Cyrillic_el, 1 },
+        { "д", XK_Cyrillic_de, 1 },
+        { "ж", XK_Cyrillic_zhe, 1 },
+        { "э", XK_Cyrillic_e, 1 },
+        { "ю", XK_Cyrillic_yu, 1 },
+
+        { 0 }, /* New row */
+
+        { "123", XK_Mode_switch, 1 },
+        { "я", XK_Cyrillic_ya, 1 },
+        { "ч", XK_Cyrillic_che, 1 },
+        { "с", XK_Cyrillic_es, 1 },
+        { "м", XK_Cyrillic_em, 1 },
+        { "и", XK_Cyrillic_i, 1 },
+        { "т", XK_Cyrillic_te, 1 },
+        { "ь", XK_Cyrillic_softsign, 1 },
+        { "б", XK_Cyrillic_be, 1 },
+        { "⌫Bksp", XK_BackSpace, 2 },
+
+        { 0 }, /* New row */
+        { "↺", XK_Cancel, 1},
+        { "Shift", XK_Shift_L, 2 },
+        { "Ctrl", XK_Control_L, 1 },
+        { "Alt", XK_Alt_L, 1 },
+        { "", XK_space, 2 },
+        { "↓", XK_Down, 1 },
+        { "↑", XK_Up, 1 },
+        { "↲ Enter", XK_Return, 2 },
 };
 
+#define LAYERS 4
+static char* layer_names[LAYERS] = {
+    "en",
+    "symbols",
+    "functions",
+    "ru",
+};
 
-#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 },
+static Key* available_layers[LAYERS] = {
+    keys_en,
+    keys_symbols,
+    keys_functions,
+    keys_ru
 };
 
 
diff --git a/svkbd.c b/svkbd.c
index 6044732..746af77 100644
--- a/svkbd.c
+++ b/svkbd.c
@@ -67,7 +67,6 @@ 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();
@@ -76,9 +75,9 @@ static void setup(void);
 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 togglelayer();
 static void unpress(Key *k, KeySym mod);
 static void updatekeys();
 
@@ -101,14 +100,15 @@ static Bool running = True, isdock = False;
 static KeySym pressedmod = 0;
 static struct timeval pressbegin;
 static int currentlayer = 0;
+static int enableoverlays = 1;
 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 
against immediate release
 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 int numlayers = 0;
 
 static KeySym ispressingkeysym;
 
@@ -122,6 +122,8 @@ Bool sigtermd = False;
 #endif
 #include LAYOUT
 
+static Key* layers[LAYERS];
+
 void
 motionnotify(XEvent *e)
 {
@@ -210,6 +212,15 @@ cleanup(void) {
        //      process will be dead before finger lifts - in that case we
        //      just trigger out fake up presses for all keys
        if (sigtermd) {
+               //handle last pending events
+               XEvent ev;
+               while (XPending(dpy)) {
+                       XNextEvent(dpy, &ev);
+                       if(handler[ev.type]) {
+                               (handler[ev.type])(&ev); /* call handler */
+                       }
+               }
+               if (debug) { printf("Cleanup: simulating key release\n"); 
fflush(stdout); }
                for (i = 0; i < LENGTH(keys); i++) {
                        XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, 
keys[i].keysym), False, 0);
                }
@@ -217,8 +228,8 @@ cleanup(void) {
 
        for (i = 0; i < SchemeLast; i++)
                free(scheme[i]);
-       drw_free(drw);
        drw_sync(drw);
+       drw_free(drw);
        XSync(dpy, False);
        XDestroyWindow(dpy, win);
        XSync(dpy, False);
@@ -272,7 +283,13 @@ drawkey(Key *k) {
        drw_rect(drw, k->x, k->y, k->w, k->h, 1, 1);
        drw_rect(drw, k->x, k->y, k->w, k->h, 0, 0);
 
-       if(k->label) {
+       if (k->keysym == XK_KP_Insert) {
+               if (enableoverlays) {
+                       l = "≅";
+               } else {
+                       l = "≇";
+               }
+       } else if(k->label) {
                l = k->label;
        } else {
                l = XKeysymToString(k->keysym);
@@ -322,17 +339,6 @@ hasoverlay(KeySym keysym) {
        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) {
@@ -358,16 +364,10 @@ press(Key *k, KeySym mod) {
        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 
actual keypress yet
-                       record_press_begin(k->keysym);
-               }
-       } else if(!IsModifierKey(k->keysym)) {
-               if (currentoverlay == -1)
+       if(!IsModifierKey(k->keysym)) {
+               if (enableoverlays && currentoverlay == -1)
                        overlayidx = hasoverlay(k->keysym);
-               if (overlayidx != -1) {
+               if (enableoverlays && overlayidx != -1) {
                        if (!pressbegin.tv_sec && !pressbegin.tv_usec) {
                                //record the begin of the press, don't simulate 
the actual keypress yet
                                record_press_begin(k->keysym);
@@ -437,6 +437,12 @@ unpress(Key *k, KeySym mod) {
                case XK_Cancel:
                        cyclelayer();
                        break;
+               case XK_script_switch:
+                       togglelayer();
+                       break;
+               case XK_KP_Insert:
+                       enableoverlays = !enableoverlays;
+                       break;
                case XK_Break:
                  running = False;
                default:
@@ -445,7 +451,7 @@ unpress(Key *k, KeySym mod) {
        }
 
 
-       if ((pressbegin.tv_sec || pressbegin.tv_usec) && k && k->keysym == 
ispressingkeysym) {
+       if ((pressbegin.tv_sec || pressbegin.tv_usec) && enableoverlays && k && 
k->keysym == ispressingkeysym) {
                if (currentoverlay == -1) {
                        if (get_press_duration() < overlay_delay) {
                                if (debug) { printf("Delayed simulation of 
press after release: %ld\n", k->keysym); fflush(stdout); }
@@ -472,7 +478,7 @@ unpress(Key *k, KeySym mod) {
                if (k) {
                        printf("Simulation of release: %ld\n", k->keysym); 
fflush(stdout);
                } else {
-                       printf("Simulation of release (all keys)"); 
fflush(stdout);
+                       printf("Simulation of release (all keys)\n"); 
fflush(stdout);
                }
        }
 
@@ -500,7 +506,7 @@ unpress(Key *k, KeySym mod) {
                }
        }
 
-       if (currentoverlay != -1) {
+       if (enableoverlays && currentoverlay != -1) {
                if (releaseprotect) {
                        releaseprotect = 0;
                } else {
@@ -516,7 +522,6 @@ run(void) {
        fd_set fds;
        struct timeval tv;
        double duration = 0.0;
-       int cyclemodidx;
 
 
        xfd = ConnectionNumber(dpy);
@@ -528,6 +533,7 @@ run(void) {
        XFlush(dpy);
 
        while (running) {
+               usleep(100000L);
                FD_ZERO(&fds);
                FD_SET(xfd, &fds);
                if (select(xfd + 1, &fds, NULL, NULL, &tv)) {
@@ -543,19 +549,13 @@ run(void) {
                                if (debug == 2) { printf("%f\n", duration); 
fflush(stdout); }
                                if (get_press_duration() >= overlay_delay) {
                                        if (debug) { printf("press duration 
%f\n", duration); fflush(stdout); }
-                                       cyclemodidx = 
iscyclemod(ispressingkeysym);
-                                       if (cyclemodidx != -1) {
-                                               cyclemod();
-                                       } else {
-                                               
showoverlay(hasoverlay(ispressingkeysym));
-                                       }
+                                       
showoverlay(hasoverlay(ispressingkeysym));
                                        pressbegin.tv_sec = 0;
                                        pressbegin.tv_usec = 0;
                                        ispressingkeysym = 0;
                                }
                        }
                }
-               usleep(100000L);
        }
 }
 
@@ -719,14 +719,20 @@ updatekeys() {
 
 void
 usage(char *argv0) {
-       fprintf(stderr, "usage: %s [-hdvD] [-g geometry] [-fn font]\n", argv0);
+       fprintf(stderr, "usage: %s [-hdvDOl] [-g geometry] [-fn font]\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, "  -l         - Comma separated list of layers to 
enable\n");
+       fprintf(stderr, "  -fn [font] - Set font (Xft, e.g: DejaVu 
Sans:bold:size=20)\n");
        exit(1);
 }
 
 void
 cyclelayer() {
        currentlayer++;
-       if (currentlayer >= LAYERS)
+       if (currentlayer >= numlayers)
                currentlayer = 0;
        if (debug) { printf("Cycling to layer %d\n", currentlayer); 
fflush(stdout); }
        memcpy(&keys, layers[currentlayer], sizeof(keys_en));
@@ -735,29 +741,19 @@ cyclelayer() {
 }
 
 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]);
-               }
+togglelayer() {
+       if (currentlayer > 0) {
+               currentlayer = 0;
+       } else if (numlayers > 1) {
+               currentlayer = 1;
        }
-       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); 
fflush(stdout); }
-       keys[CYCLEMODKEY].label = cyclemods[currentcyclemod].label;
-       keys[CYCLEMODKEY].keysym = cyclemods[currentcyclemod].keysym;
-       drawkey(&keys[CYCLEMODKEY]);
-       XSync(dpy, False);
+       if (debug) { printf("Toggling layer %d\n", currentlayer); 
fflush(stdout); }
+       memcpy(&keys, layers[currentlayer], sizeof(keys_en));
+       updatekeys();
+       drawkeyboard();
 }
 
+
 void
 showoverlay(int idx) {
        if (debug) { printf("Showing overlay %d\n", idx); fflush(stdout); }
@@ -802,15 +798,58 @@ sigterm(int sig)
 {
        running = False;
        sigtermd = True;
+       if (debug) { printf("Sigterm received\n"); fflush(stdout); }
+}
+
+
+void
+init_layers(char * layer_names_list) {
+       if (layer_names_list == NULL) {
+               numlayers = LAYERS;
+               memcpy(&layers, &available_layers, sizeof(available_layers));
+       } else {
+               char * s;
+               int j;
+               s = strtok(layer_names_list, ",");
+               while (s != NULL) {
+                       if (numlayers+1 > LAYERS) die("too many layers 
specified");
+                       int found = 0;
+                       for (j = 0; j < LAYERS; j++) {
+                               if (strcmp(layer_names[j], s) == 0) {
+                                       layers[numlayers] = available_layers[j];
+                                       printf("Adding layer %s\n", s);
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found) {
+                               fprintf(stderr, "Undefined layer: %s\n", s);
+                               exit(3);
+                       }
+                       numlayers++;
+                       s = strtok(NULL,",");
+               }
+       }
 }
 
 int
 main(int argc, char *argv[]) {
        int i, xr, yr, bitm;
        unsigned int wr, hr;
+       char * layer_names_list = NULL;
 
        memcpy(&keys, &keys_en, sizeof(keys_en));
        signal(SIGTERM, sigterm);
+
+       const char* enableoverlays_env = getenv("SVKBD_ENABLEOVERLAYS");
+       if (enableoverlays_env != NULL) enableoverlays = 
atoi(enableoverlays_env);
+       const char* layers_env = getenv("SVKBD_LAYERS");
+       if (layers_env != NULL) {
+               layer_names_list = malloc(128);
+               strcpy(layer_names_list, layers_env);
+       }
+
+
        for (i = 1; argv[i]; i++) {
                if(!strcmp(argv[i], "-v")) {
                        die("svkbd-"VERSION", © 2006-2020 svkbd engineers,"
@@ -842,9 +881,18 @@ main(int argc, char *argv[]) {
                        debug = 1;
                } else if(!strcmp(argv[i], "-h")) {
                        usage(argv[0]);
+               } else if(!strcmp(argv[i], "-O")) {
+                       enableoverlays = 0;
+               } else if(!strcmp(argv[i], "-l")) {
+                       if(i >= argc - 1)
+                               continue;
+                       if (layer_names_list == NULL) layer_names_list = 
malloc(128);
+                       strcpy(layer_names_list, argv[i+1]);
                }
        }
 
+       init_layers(layer_names_list);
+
        if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
                fprintf(stderr, "warning: no locale support\n");
        if(!(dpy = XOpenDisplay(0)))
@@ -853,5 +901,6 @@ main(int argc, char *argv[]) {
        run();
        cleanup();
        XCloseDisplay(dpy);
+       if (layer_names_list != NULL) free(layer_names_list);
        return 0;
 }
-- 
2.27.0


Reply via email to