Skip to content

Commit 4ef618c

Browse files
committed
Support keyboard layouts
1 parent e64cad5 commit 4ef618c

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

keyboard-layouts.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#define _POSIX_C_SOURCE 200809L
2+
#include <stdbool.h>
3+
#include <string.h>
4+
#include "keyboard-layouts.h"
5+
6+
static int
7+
cmp_layouts(const void *a, const void *b)
8+
{
9+
return strcmp(((struct layout *)a)->lang, ((struct layout *)b)->lang);
10+
}
11+
12+
void
13+
keyboard_layouts_init(GList **layouts, const char *filename)
14+
{
15+
bool in_layout_section = false;
16+
char *line = NULL;
17+
size_t len = 0;
18+
FILE *fp = fopen(filename, "r");
19+
20+
if (!fp) {
21+
perror("Error opening file");
22+
exit (EXIT_FAILURE);
23+
}
24+
while (getline(&line, &len, fp) != -1) {
25+
char *p = strrchr(line, '\n');
26+
if (p) {
27+
*p = '\0';
28+
}
29+
if (line[0] == '\0') {
30+
continue;
31+
} else if (line[0] == '!') {
32+
in_layout_section = g_ascii_strncasecmp(line, "! layout", len) == 0;
33+
} else if (in_layout_section) {
34+
char **argv = g_strsplit(g_strstrip(line), " ", 2);
35+
struct layout *layout = calloc(1, sizeof(*layout));
36+
layout->lang = strdup(argv[0]);
37+
layout->description = strdup(g_strstrip(argv[1]));
38+
*layouts = g_list_append(*layouts, layout);
39+
g_strfreev(argv);
40+
}
41+
}
42+
free(line);
43+
fclose(fp);
44+
*layouts = g_list_sort(*layouts, (GCompareFunc)cmp_layouts);
45+
}
46+
47+
void
48+
keyboard_layouts_finish(GList *layouts)
49+
{
50+
GList *iter;
51+
for (iter = layouts; iter; iter = iter->next) {
52+
struct layout *layout = (struct layout *)iter->data;
53+
g_free(layout->lang);
54+
g_free(layout->description);
55+
g_free(layout);
56+
}
57+
g_list_free(layouts);
58+
}
59+

keyboard-layouts.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef KEYBOARD_LAYOUTS_H
2+
#define KEYBOARD_LAYOUTS_H
3+
#include <gtk/gtk.h>
4+
5+
struct layout {
6+
char *lang;
7+
char *description;
8+
};
9+
10+
void keyboard_layouts_init(GList **layouts, const char *filename);
11+
void keyboard_layouts_finish(GList *layouts);
12+
13+
#endif /* KEYBOARD_LAYOUTS_H */

main.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <string.h>
66
#include <strings.h>
77
#include <sys/stat.h>
8+
#include "keyboard-layouts.h"
89
#include "tweaks.h"
910
#include "xml.h"
1011

@@ -15,6 +16,7 @@ static GtkWidget *icon_theme_name;
1516
static GtkWidget *cursor_theme_name;
1617
static GtkWidget *cursor_size;
1718
static GtkWidget *natural_scroll;
19+
static GtkWidget *keyboard_layout;
1820

1921
static struct themes openbox_themes = { 0 };
2022
static struct themes gtk_themes = { 0 };
@@ -35,7 +37,6 @@ spawn_sync(char const *command)
3537
}
3638
}
3739

38-
3940
static void
4041
environment_set(const char *key, const char *value)
4142
{
@@ -94,6 +95,15 @@ set_value_num(GSettings *settings, const char *key, int value)
9495
g_settings_set_value(settings, key, g_variant_new("i", value));
9596
}
9697

98+
const char *first_field(const char *s, char delim)
99+
{
100+
char *p = strchr(s, delim);
101+
if (p) {
102+
*p = '\0';
103+
}
104+
return s;
105+
}
106+
97107
#define COMBO_TEXT(w) gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w))
98108
#define SPIN_BUTTON_VAL(w) gtk_spin_button_get_value(GTK_SPIN_BUTTON(w))
99109
#define SPIN_BUTTON_VAL_INT(w) (int)SPIN_BUTTON_VAL(w)
@@ -116,6 +126,7 @@ update(GtkWidget *widget, gpointer data)
116126
/* ~/.config/labwc/environment */
117127
environment_set("XCURSOR_THEME", COMBO_TEXT(cursor_theme_name));
118128
environment_set_num("XCURSOR_SIZE", SPIN_BUTTON_VAL_INT(cursor_size));
129+
environment_set("XKB_DEFAULT_LAYOUT", first_field(COMBO_TEXT(keyboard_layout), ' '));
119130

120131
if (!g_strcmp0(COMBO_TEXT(openbox_theme_name), "GTK")) {
121132
spawn_sync("labwc-gtktheme.py");
@@ -225,7 +236,7 @@ activate(GtkApplication *app, gpointer user_data)
225236
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cursor_theme_name), theme->name);
226237
}
227238
gtk_combo_box_set_active(GTK_COMBO_BOX(cursor_theme_name), active);
228-
gtk_grid_attach(GTK_GRID(grid),cursor_theme_name, 1, row++, 1, 1);
239+
gtk_grid_attach(GTK_GRID(grid), cursor_theme_name, 1, row++, 1, 1);
229240

230241
/* cursor size spinbutton */
231242
widget = gtk_label_new("cursor size");
@@ -246,6 +257,35 @@ activate(GtkApplication *app, gpointer user_data)
246257
gtk_combo_box_set_active(GTK_COMBO_BOX(natural_scroll), xml_get_bool_text("/labwc_config/libinput/device/naturalscroll"));
247258
gtk_grid_attach(GTK_GRID(grid), natural_scroll, 1, row++, 1, 1);
248259

260+
261+
/* keyboard layout */
262+
GList *keyboard_layouts = NULL;
263+
keyboard_layouts_init(&keyboard_layouts, "/usr/share/X11/xkb/rules/evdev.lst");
264+
265+
widget = gtk_label_new("keyboard layout");
266+
gtk_widget_set_halign(widget, GTK_ALIGN_START);
267+
gtk_grid_attach(GTK_GRID(grid), widget, 0, row, 1, 1);
268+
keyboard_layout = gtk_combo_box_text_new();
269+
270+
active_id = "gb";
271+
active = -1;
272+
273+
GList *iter;
274+
int i = 0;
275+
for (iter = keyboard_layouts; iter; iter = iter->next) {
276+
struct layout *layout = (struct layout *)iter->data;
277+
if (!strcmp(layout->lang, active_id)) {
278+
active = i;
279+
}
280+
char buf[256];
281+
snprintf(buf, sizeof(buf), "%s %s", layout->lang, layout->description);
282+
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(keyboard_layout), buf);
283+
++i;
284+
}
285+
gtk_combo_box_set_active(GTK_COMBO_BOX(keyboard_layout), active);
286+
gtk_grid_attach(GTK_GRID(grid), keyboard_layout, 1, row++, 1, 1);
287+
keyboard_layouts_finish(keyboard_layouts);
288+
249289
/* bottom button box */
250290
hbbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
251291
gtk_box_pack_start(GTK_BOX(vbox), hbbox, TRUE, TRUE, 5);

meson.build

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ gtkdeps = [dependency('gtk+-3.0'), dependency('libxml-2.0'), dependency('gio-2.0
1212

1313
executable(
1414
meson.project_name(),
15-
files('main.c', 'xml.c', 'find-themes.c'),
15+
files(
16+
'main.c',
17+
'xml.c',
18+
'find-themes.c',
19+
'keyboard-layouts.c',
20+
),
1621
dependencies: gtkdeps,
1722
install : true,
1823
)

0 commit comments

Comments
 (0)