From bf17f07bc3b472601c2cbdd96ec48c1e165eff63 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sun, 12 Jan 2020 04:39:14 +0100 Subject: [PATCH] Add initial support for differing keyboard layouts This is plain ugly though. It will have to be re-designed. --- src/keyboard.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++--- src/keyboard.h | 1 + src/main.c | 9 +- 3 files changed, 231 insertions(+), 16 deletions(-) diff --git a/src/keyboard.c b/src/keyboard.c index c30395b..7b7247e 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -33,9 +33,11 @@ static char const _license[] = +#include #include #include #include +#include #include #include #include @@ -55,6 +57,10 @@ static char const _license[] = #define _(string) gettext(string) #define N_(string) (string) +#ifndef PROGNAME_KEYBOARD +# define PROGNAME_KEYBOARD "keyboard" +#endif + /* Keyboard */ /* private */ @@ -104,6 +110,21 @@ typedef struct _KeyboardLayoutDefinition KeyboardKeyDefinition const * keys; } KeyboardLayoutDefinition; +typedef enum _KeyboardLayoutType +{ + KLT_QWERTY = 0, + KLT_QWERTZ, + KLT_AZERTY +} KeyboardLayoutType; +#define KLT_LAST KLT_AZERTY +#define KLT_COUNT (KLT_LAST + 1) + +typedef struct _KeyboardLayoutTypeName +{ + KeyboardLayoutType type; + char const * name; +} KeyboardLayoutTypeName; + /* constants */ static char const * _authors[] = @@ -112,6 +133,13 @@ static char const * _authors[] = NULL }; +static const KeyboardLayoutTypeName _keyboard_layout_type_name[] = +{ + { KLT_QWERTY, "us" }, + { KLT_QWERTZ, "de" }, + { KLT_AZERTY, "fr" } +}; + static const DesktopMenu _keyboard_menu_file[] = { { N_("_Quit"), G_CALLBACK(on_file_quit), GTK_STOCK_QUIT, @@ -146,7 +174,7 @@ static const DesktopMenubar _keyboard_menubar[] = /* variables */ -static KeyboardKeyDefinition const _keyboard_layout_letters[] = +static KeyboardKeyDefinition const _keyboard_layout_letters_qwerty[] = { { 0, 2, 0, XK_q, "q" }, { 0, 0, XK_Shift_L, XK_Q, "Q" }, @@ -216,6 +244,153 @@ static KeyboardKeyDefinition const _keyboard_layout_letters[] = { 0, 0, 0, 0, NULL } }; +static KeyboardKeyDefinition const _keyboard_layout_letters_qwertz[] = +{ + { 0, 2, 0, XK_q, "q" }, + { 0, 0, XK_Shift_L, XK_Q, "Q" }, + { 0, 2, 0, XK_w, "w" }, + { 0, 0, XK_Shift_L, XK_W, "W" }, + { 0, 2, 0, XK_e, "e" }, + { 0, 0, XK_Shift_L, XK_E, "E" }, + { 0, 2, 0, XK_r, "r" }, + { 0, 0, XK_Shift_L, XK_R, "R" }, + { 0, 2, 0, XK_t, "t" }, + { 0, 0, XK_Shift_L, XK_T, "T" }, + { 0, 2, 0, XK_z, "z" }, + { 0, 0, XK_Shift_L, XK_Z, "Z" }, + { 0, 2, 0, XK_u, "u" }, + { 0, 0, XK_Shift_L, XK_U, "U" }, + { 0, 2, 0, XK_i, "i" }, + { 0, 0, XK_Shift_L, XK_I, "I" }, + { 0, 2, 0, XK_o, "o" }, + { 0, 0, XK_Shift_L, XK_O, "O" }, + { 0, 2, 0, XK_p, "p" }, + { 0, 0, XK_Shift_L, XK_P, "P" }, + { 1, 1, 0, 0, NULL }, + { 1, 2, 0, XK_a, "a" }, + { 1, 0, XK_Shift_L, XK_A, "A" }, + { 1, 2, 0, XK_s, "s" }, + { 1, 0, XK_Shift_L, XK_S, "S" }, + { 1, 2, 0, XK_d, "d" }, + { 1, 0, XK_Shift_L, XK_D, "D" }, + { 1, 2, 0, XK_f, "f" }, + { 1, 0, XK_Shift_L, XK_F, "F" }, + { 1, 2, 0, XK_g, "g" }, + { 1, 0, XK_Shift_L, XK_G, "G" }, + { 1, 2, 0, XK_h, "h" }, + { 1, 0, XK_Shift_L, XK_H, "H" }, + { 1, 2, 0, XK_j, "j" }, + { 1, 0, XK_Shift_L, XK_J, "J" }, + { 1, 2, 0, XK_k, "k" }, + { 1, 0, XK_Shift_L, XK_K, "K" }, + { 1, 2, 0, XK_l, "l" }, + { 1, 0, XK_Shift_L, XK_L, "L" }, + { 2, 2, 0, XK_Shift_L, "\xe2\x87\xa7" }, + { 2, 2, 0, XK_y, "y" }, + { 2, 0, XK_Shift_L, XK_Y, "Y" }, + { 2, 2, 0, XK_x, "x" }, + { 2, 0, XK_Shift_L, XK_X, "X" }, + { 2, 2, 0, XK_c, "c" }, + { 2, 0, XK_Shift_L, XK_C, "C" }, + { 2, 2, 0, XK_v, "v" }, + { 2, 0, XK_Shift_L, XK_V, "V" }, + { 2, 2, 0, XK_b, "b" }, + { 2, 0, XK_Shift_L, XK_B, "B" }, + { 2, 2, 0, XK_n, "n" }, + { 2, 0, XK_Shift_L, XK_N, "N" }, + { 2, 2, 0, XK_m, "m" }, + { 2, 0, XK_Shift_L, XK_M, "M" }, + { 2, 2, 0, XK_comma, "," }, + { 2, 0, XK_Shift_L, XK_comma, "<" }, + { 2, 2, 0, XK_period, "." }, + { 2, 0, XK_Shift_L, XK_period, ">" }, + { 3, 3, 0, 0, NULL }, + { 3, 3, 0, XK_Control_L, "Ctrl" }, + { 3, 3, 0, XK_Alt_L, "Alt" }, + { 3, 5, 0, XK_space, " " }, + { 3, 0, XK_Shift_L, XK_space, " " }, + { 3, 3, 0, XK_Return, "\xe2\x86\xb2" }, + { 3, 3, 0, XK_BackSpace, "\xe2\x8c\xab" }, + { 0, 0, 0, 0, NULL } +}; + +static KeyboardKeyDefinition const _keyboard_layout_letters_azerty[] = +{ + { 0, 2, 0, XK_a, "a" }, + { 0, 0, XK_Shift_L, XK_A, "A" }, + { 0, 2, 0, XK_z, "z" }, + { 0, 0, XK_Shift_L, XK_Z, "Z" }, + { 0, 2, 0, XK_e, "e" }, + { 0, 0, XK_Shift_L, XK_E, "E" }, + { 0, 2, 0, XK_r, "r" }, + { 0, 0, XK_Shift_L, XK_R, "R" }, + { 0, 2, 0, XK_t, "t" }, + { 0, 0, XK_Shift_L, XK_T, "T" }, + { 0, 2, 0, XK_y, "y" }, + { 0, 0, XK_Shift_L, XK_Y, "Y" }, + { 0, 2, 0, XK_u, "u" }, + { 0, 0, XK_Shift_L, XK_U, "U" }, + { 0, 2, 0, XK_i, "i" }, + { 0, 0, XK_Shift_L, XK_I, "I" }, + { 0, 2, 0, XK_o, "o" }, + { 0, 0, XK_Shift_L, XK_O, "O" }, + { 0, 2, 0, XK_p, "p" }, + { 0, 0, XK_Shift_L, XK_P, "P" }, + { 1, 1, 0, 0, NULL }, + { 1, 2, 0, XK_q, "q" }, + { 1, 0, XK_Shift_L, XK_Q, "Q" }, + { 1, 2, 0, XK_s, "s" }, + { 1, 0, XK_Shift_L, XK_S, "S" }, + { 1, 2, 0, XK_d, "d" }, + { 1, 0, XK_Shift_L, XK_D, "D" }, + { 1, 2, 0, XK_f, "f" }, + { 1, 0, XK_Shift_L, XK_F, "F" }, + { 1, 2, 0, XK_g, "g" }, + { 1, 0, XK_Shift_L, XK_G, "G" }, + { 1, 2, 0, XK_h, "h" }, + { 1, 0, XK_Shift_L, XK_H, "H" }, + { 1, 2, 0, XK_j, "j" }, + { 1, 0, XK_Shift_L, XK_J, "J" }, + { 1, 2, 0, XK_k, "k" }, + { 1, 0, XK_Shift_L, XK_K, "K" }, + { 1, 2, 0, XK_l, "l" }, + { 1, 0, XK_Shift_L, XK_L, "L" }, + { 2, 2, 0, XK_Shift_L, "\xe2\x87\xa7" }, + { 2, 2, 0, XK_z, "z" }, + { 2, 0, XK_Shift_L, XK_Z, "Z" }, + { 2, 2, 0, XK_x, "x" }, + { 2, 0, XK_Shift_L, XK_X, "X" }, + { 2, 2, 0, XK_c, "c" }, + { 2, 0, XK_Shift_L, XK_C, "C" }, + { 2, 2, 0, XK_v, "v" }, + { 2, 0, XK_Shift_L, XK_V, "V" }, + { 2, 2, 0, XK_b, "b" }, + { 2, 0, XK_Shift_L, XK_B, "B" }, + { 2, 2, 0, XK_n, "n" }, + { 2, 0, XK_Shift_L, XK_N, "N" }, + { 2, 2, 0, XK_m, "m" }, + { 2, 0, XK_Shift_L, XK_M, "M" }, + { 2, 2, 0, XK_comma, "," }, + { 2, 0, XK_Shift_L, XK_comma, "<" }, + { 2, 2, 0, XK_period, "." }, + { 2, 0, XK_Shift_L, XK_period, ">" }, + { 3, 3, 0, 0, NULL }, + { 3, 3, 0, XK_Control_L, "Ctrl" }, + { 3, 3, 0, XK_Alt_L, "Alt" }, + { 3, 5, 0, XK_space, " " }, + { 3, 0, XK_Shift_L, XK_space, " " }, + { 3, 3, 0, XK_Return, "\xe2\x86\xb2" }, + { 3, 3, 0, XK_BackSpace, "\xe2\x8c\xab" }, + { 0, 0, 0, 0, NULL } +}; + +static KeyboardKeyDefinition const * _keyboard_layout_letters_definition[KLT_COUNT] = +{ + _keyboard_layout_letters_qwerty, + _keyboard_layout_letters_qwertz, + _keyboard_layout_letters_azerty +}; + static KeyboardKeyDefinition const _keyboard_layout_keypad[] = { { 0, 3, 0, XK_Num_Lock, "Num" }, @@ -327,19 +502,14 @@ static KeyboardKeyDefinition const _keyboard_layout_special[] = { 0, 0, 0, 0, NULL } }; -static KeyboardLayoutDefinition _keyboard_layout[KLS_COUNT] = -{ - { "Abc", _keyboard_layout_letters }, - { "123", _keyboard_layout_keypad }, - { ",./", _keyboard_layout_special } -}; - /* prototypes */ static GtkWidget * _keyboard_add_layout(Keyboard * keyboard, KeyboardLayoutDefinition * definitions, size_t definitions_cnt, KeyboardLayoutSection section); +static void _keyboard_error(Keyboard * keyboard, char const * format, ...); + /* public */ /* functions */ @@ -365,6 +535,14 @@ Keyboard * keyboard_new(KeyboardPrefs * prefs) GdkColor gray = { 0x90909090, 0x9090, 0x9090, 0x9090 }; #endif unsigned long id; + KeyboardLayoutDefinition layout[KLS_COUNT] = + { + { "Abc", _keyboard_layout_letters_qwerty }, + { "123", _keyboard_layout_keypad }, + { ",./", _keyboard_layout_special } + }; + size_t i; + KeyboardLayoutTypeName const * typename; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); @@ -423,14 +601,31 @@ Keyboard * keyboard_new(KeyboardPrefs * prefs) vbox = widget; } /* layouts */ - if((widget = _keyboard_add_layout(keyboard, _keyboard_layout, - KLS_COUNT, KLS_LETTERS)) != NULL) + if(prefs->layout != NULL) + { + for(i = 0; i < sizeof(_keyboard_layout_type_name) + / sizeof(*_keyboard_layout_type_name); i++) + { + typename = &_keyboard_layout_type_name[i]; + if(strcasecmp(prefs->layout, typename->name) == 0) + { + layout[0].keys = _keyboard_layout_letters_definition[typename->type]; + break; + } + typename = NULL; + } + if(typename == NULL) + _keyboard_error(NULL, "%s: Unsupported layout", + prefs->layout); + } + if((widget = _keyboard_add_layout(keyboard, layout, KLS_COUNT, + KLS_LETTERS)) != NULL) gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 0); - if((widget = _keyboard_add_layout(keyboard, _keyboard_layout, - KLS_COUNT, KLS_KEYPAD)) != NULL) + if((widget = _keyboard_add_layout(keyboard, layout, KLS_COUNT, + KLS_KEYPAD)) != NULL) gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 0); - if((widget = _keyboard_add_layout(keyboard, _keyboard_layout, - KLS_COUNT, KLS_SPECIAL)) != NULL) + if((widget = _keyboard_add_layout(keyboard, layout, KLS_COUNT, + KLS_SPECIAL)) != NULL) gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 0); gtk_widget_show(vbox); if(prefs->mode == KEYBOARD_MODE_EMBEDDED) @@ -814,3 +1009,17 @@ static void _layout_clicked(GtkWidget * widget, gpointer data) break; } } + + +/* keyboard_error */ +static void _keyboard_error(Keyboard * keyboard, char const * format, ...) +{ + va_list ap; + + /* TODO add support for error dialog messages */ + va_start(ap, format); + fprintf(stderr, "%s: ", PROGNAME_KEYBOARD); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); +} diff --git a/src/keyboard.h b/src/keyboard.h index 7219ef6..a0e9741 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -53,6 +53,7 @@ typedef struct _KeyboardPrefs { int monitor; char const * font; + char const * layout; KeyboardMode mode; int wait; } KeyboardPrefs; diff --git a/src/main.c b/src/main.c index e837e5f..25fd8a0 100644 --- a/src/main.c +++ b/src/main.c @@ -89,8 +89,10 @@ static int _error(char const * message, int ret) /* usage */ static int _usage(void) { - fprintf(stderr, _("Usage: %s [-d|-p|-w|-x][-f font][-m monitor][-n]\n" + fprintf(stderr, _("Usage: %s [-d|-p|-w|-x][-f font][-l layout]" +"[-m monitor][-n]\n" " -d Start in docked mode\n" +" -l Select a different layout\n" " -p Start as a popup window\n" " -w Start in windowed mode\n" " -x Start in embedded mode\n" @@ -117,7 +119,7 @@ int main(int argc, char * argv[]) textdomain(PACKAGE); memset(&prefs, 0, sizeof(prefs)); gtk_init(&argc, &argv); - while((o = getopt(argc, argv, "df:m:npwx")) != -1) + while((o = getopt(argc, argv, "df:l:m:npwx")) != -1) switch(o) { case 'd': @@ -126,6 +128,9 @@ int main(int argc, char * argv[]) case 'f': prefs.font = optarg; break; + case 'l': + prefs.layout = optarg; + break; case 'm': prefs.monitor = strtol(optarg, &p, 10); if(optarg[0] == '\0' || *p != '\0')