Skip to content

Commit

Permalink
1.00: Init release
Browse files Browse the repository at this point in the history
  • Loading branch information
zvezdochiot committed Jun 1, 2019
1 parent 2b8fed6 commit eaf2922
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 0 deletions.
43 changes: 43 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Simple X11 1-key Keyboard layout switcher

(c) Alexey Korop, 2014. Mailto: [email protected].
This is free software under GNU GPLv3.

Installation

Unpack archive and copy the s1kls file to the any location that is suitable for programs.

Command line

xkbs1kls keycode1 keycode2 ...

The key with keycode 'keycode1' sets the layout 1,
the key with keycode 'keycode2' sets the layout 2 ...

Features

Only LockGroup switch type supported (each key select the own layout). No layout indicator supported.
Key codes you can find out by calling this program in the terminal without parameters.

Backgrownd

Standard X11 layout switcher is activated immediately by pressing the keys and therefore conflicts with the application shortcuts.
This switcher is activated by releasing the keys, but only under the condition that no other key is pressed. For example, You were asked to switch to the layout 2 by RCtrl. Then if You press and release RCtrl, the layout will be switched. But if You pressed in a text editor RCtrl-Right, then the editor performs jump forward a word and layout will not be switched.

If You need a layout indicator, You can use a standard X11 LED indicator or any tray indicator as xxkb.

Example

I use 3 layouts: (us,ru,ua), LED "ScrollLock" as indicator and keys following: RShift sets "us", RCtrl sets "ru" and RWin sets "ua". On the pc105 keyboard these keys have the keycodes 62, 105 and 134.

In the X11 keyboard config (in my ArchLinux it is the file /etc/X11/xorg.conf.d/01-keyboard-layout.conf) I define:

Option "XkbLayout" "us, ru, ua"
Option "XkbOptions" "grp_led:scroll"

In the autostart I call this program:

xkbs1kls 62 105 134 &


https://sourceforge.net/projects/s1kls/
1 change: 1 addition & 0 deletions build
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gcc -lX11 s1kls.c -O2 -o xkbs1kls
157 changes: 157 additions & 0 deletions s1kls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
Simple X11 1-key Keyboard layout switcher.
Only LockGroup switch type supported (each key select the own layout).
No indicator supported.
To switch layout You must press and realease the corresponding key;
layout will be switched when the key is released,
but only yf no other key(s) has been pressed.
Developed by Alexey Korop, 2014
Compile:
gcc -lX11 s1kls.c -o xkbs1kls
This program is free software, under the GNU General Public License
version 3.
*/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

//#define TRACE

static int switcher[16];
/* some keycodes on the pc105 keyboard:
62 rshift
105 rctrl
108 ralt
134 rwin
50 lshift
37 lctrl
64 lalt
133 lwin
*/

typedef unsigned char bool;

int main(int argc, char *argv[]) {
Display *display;
char keys_cur[32], keys_prev[32];
unsigned char diff, cur;
int n_keys_pressed;
int keycode = 0;
int i;
int byte, bit;
int n;
bool view_codes = 0;
int layout = -1;/*
-2 - Awaiting release all keys;
-1 - all keys are released;
0... - the key that selects this layout is pressed; expect its release */

for (n=0; n<argc-1; n++){
sscanf(argv[n+1], "%d", &switcher[n]);
if (switcher[n] <= 0)
goto help;
}
if (n < 2){
help:
printf("Simple X11 1-key Keyboard layout switcher. Version 1.00.\n");
printf("(c) Alexey Korop, 2014. Free software under GNU GPLv3\n\n");
printf("Command line: s1kls keycode1 keycode2 ...\n\n");
printf("The key with keycode 'keycode1' sets the layout 1, \n");
printf("the key with keycode 'keycode2' sets the layout 2 ... \n\n");
printf("Now You may press the desired keys and see their keycodes.\n");
view_codes = 1;
}

display = XOpenDisplay(NULL);
if (display == NULL){
fprintf(stderr, "XOpenDisplay error \n");
}

XkbIgnoreExtension(False);
XQueryKeymap(display, keys_prev);
while(1) {
XQueryKeymap(display, keys_cur);
n_keys_pressed = 0;
for (byte=0; byte<32; byte++) {
cur = keys_cur[byte];
diff = keys_prev[byte] ^ cur;
if (diff | cur) {
keys_prev[byte] = cur;
for (bit = 0; bit<8; bit++){
if (diff & 0x01){
if (!view_codes || (cur & 0x01))
keycode = byte*8 + bit;
#ifdef TRACE
printf("key %d", keycode);
if (cur & 0x01)
printf(" press\n");
else
printf(" release\n");
#endif
}
if (cur & 0x01)
n_keys_pressed++;
diff >>= 1;
cur >>= 1;
}
}
}

if (view_codes){
if (n_keys_pressed == 0){
if (keycode){
printf(" %4d \n", keycode);
keycode = 0;
}
}
}
else { // normal work
if (n_keys_pressed == 0){
if (layout >= 0){
#ifdef TRACE
printf("new layout %d\n", layout);
#endif
if (!XkbLockGroup(display, XkbUseCoreKbd, layout)){
fprintf(stderr, "XkbLockGroup error \n");
return(1);
}
}
layout = -1;
}
else if (layout == -2)
;
else if ((n_keys_pressed == 1) && (keycode == switcher[layout]))
; //hold the key
else if ((n_keys_pressed == 1) && (layout == -1)){
layout = -2;
for (i=0; i<n; ++i)
if (keycode == switcher[i]){
layout = i;
#ifdef TRACE
printf("wait for release the key %d\n", switcher[layout]);
#endif
break;
}
}
else{
#ifdef TRACE
if (layout >= 0)
printf("reject waiting\n");
#endif
layout = -2;
}
}
usleep(20000);
}
// XCloseDisplay(display);
}

0 comments on commit eaf2922

Please sign in to comment.