diff --git a/.cache/clangd/index/keymap.h.ABBD7372264C183C.idx b/.cache/clangd/index/keymap.h.ABBD7372264C183C.idx new file mode 100644 index 0000000..ea89c80 Binary files /dev/null and b/.cache/clangd/index/keymap.h.ABBD7372264C183C.idx differ diff --git a/.cache/clangd/index/main.c.8CF723096C569150.idx b/.cache/clangd/index/main.c.8CF723096C569150.idx new file mode 100644 index 0000000..3193f7c Binary files /dev/null and b/.cache/clangd/index/main.c.8CF723096C569150.idx differ diff --git a/.gitignore b/.gitignore index f603704..ddb306f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -osk +*osk *.o *.env +build/* diff --git a/Makefile b/Makefile deleted file mode 100644 index 8323e4f..0000000 --- a/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# Variables for compiler and flags -CC = gcc -PKG_CONFIG = pkg-config -PACKAGES = gtk4 libevdev gtk4-layer-shell-0 - -# Fetch flags and libs using pkg-config -CFLAGS = $(shell $(PKG_CONFIG) --cflags $(PACKAGES)) -LIBS = $(shell $(PKG_CONFIG) --libs $(PACKAGES)) - -# Target executable name -TARGET = osk - -# Source files -SRC = main.c resources.c -OBJ = $(SRC:.c=.o) - -# Default rule: build the target -all: $(TARGET) - -# Rule to link the final executable -$(TARGET): resources.c $(OBJ) - $(CC) -o $(TARGET) $(OBJ) $(LIBS) - -# Rule to compile .c files to .o files -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - -# Rule to generate resources.c from XML -resources.c: resources.xml - glib-compile-resources resources.xml --target=resources.c --generate-source - -# Clean up generated files -clean: - rm -f $(TARGET) $(OBJ) resources.c - -.PHONY: all clean diff --git a/README.md b/README.md index 8650548..4ffb073 100644 --- a/README.md +++ b/README.md @@ -32,17 +32,17 @@ Run the following commands: ``` git clone https://github.com/weave-space/oskeyboard cd oskeyboard -make -./osk +meson compile -C build +./build/osk ``` -## Customization -There are two ways to customize `oskeyboard`: editing `keymap.h` and `styles.css`. Currently there is a limitation of custom layouts, as the number of rows and the number of keys per row are hardcoded in `main.c`. That will be remedied in the near future. +## Customization +There is now only one way to customize `oskeyboard`: editing `keymap.h`. Currently there is a limitation of custom layouts, as the number of rows and the number of keys per row are hardcoded in `main.c`. That will be remedied in the near future. -Any changes to `keymap.h` or `styles.css` require you to recompile, simply run `make` to do so. +Any changes to `keymap.h` require you to recompile, simply run `meson compile -C build` to do so. ## TODO -- [ ] Responsive design sizes +- [x] Responsive design sizes - [ ] CLI flags - [ ] Man page - [ ] Documentation diff --git a/keyboard.ui b/keyboard.ui deleted file mode 100644 index 55c8b36..0000000 --- a/keyboard.ui +++ /dev/null @@ -1,84 +0,0 @@ - - - - OSKeyboard - - - - 15 - center - center - - - - - - 0 - 0 - - 15 - - center - - - - - - - - - 1 - 0 - - 15 - - center - - - - - - - - - 2 - 0 - - 15 - - center - - - - - - - - - 3 - 0 - - 15 - - center - - - - - - - - - 4 - 0 - - 15 - - center - - - - - - - diff --git a/keymap.h b/keymap.h deleted file mode 100644 index 459133b..0000000 --- a/keymap.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef KEYMAP_H -#define KEYMAP_H - -#include - -typedef struct { -const char *label; -const char *shift_label; -int key_code; -} KeyMapping; - -static const KeyMapping key_map[] = { - /* Row 0 */ - {"`", "~", KEY_GRAVE}, {"1", "!", KEY_1}, {"2", "#", KEY_2}, {"3", "#", KEY_3}, {"4", "$", KEY_4}, - {"5", "%", KEY_5}, {"6", "^", KEY_6}, {"7", "&", KEY_7}, {"8", "*", KEY_8}, {"9", "(", KEY_9}, - {"0", ")", KEY_0}, {"-", "_", KEY_MINUS}, {"=", "+", KEY_EQUAL}, {"Backspace", "Delete", KEY_BACKSPACE}, - - /* Row 1 */ - {"Tab", "Tab", KEY_TAB}, {"q", "Q", KEY_Q}, {"w", "W", KEY_W}, {"e", "E", KEY_E}, {"r", "R", KEY_R}, - {"t", "T", KEY_T}, {"y", "Y", KEY_Y}, {"u", "U", KEY_U}, {"i", "I", KEY_I}, {"o", "O", KEY_O}, - {"p", "P", KEY_P}, {"[", "{", KEY_LEFTBRACE}, {"]", "}", KEY_RIGHTBRACE}, {"\\", "|", KEY_BACKSLASH}, - - /* Row 2 */ - {"Escape", "Escape", KEY_ESC}, {"a", "A", KEY_A}, {"s", "S", KEY_S}, {"d", "D", KEY_D}, - {"f", "F", KEY_F}, {"g", "G", KEY_G}, {"h", "H", KEY_H}, {"j", "J", KEY_J}, {"k", "K", KEY_K}, - {"l", "L", KEY_L}, {";", ":", KEY_SEMICOLON}, {"'", "\"", KEY_APOSTROPHE}, {"Enter", "Enter", KEY_ENTER}, - - /* Row 3 */ - {"Shift", "Shift", KEY_LEFTSHIFT}, {"z", "Z", KEY_Z}, {"x", "X", KEY_X}, {"c", "C", KEY_C}, - {"v", "V", KEY_V}, {"b", "B", KEY_B}, {"n", "N", KEY_N}, {"m", "M", KEY_M}, {",", "<", KEY_COMMA}, - {".", ">", KEY_DOT}, {"/", "?", KEY_SLASH}, {"Shift", "Shift", KEY_RIGHTSHIFT}, - - /* Row 4 */ - {"Ctrl", "Ctrl", KEY_LEFTCTRL}, {"Super", "Super", KEY_LEFTMETA}, {"Alt", "Alt", KEY_LEFTALT}, - {"Space", "Space", KEY_SPACE}, {"Alt", "Alt", KEY_RIGHTALT}, {"Ctrl", "Ctrl", KEY_RIGHTCTRL} -}; - -#define KEY_MAP_SIZE (sizeof(key_map) / sizeof(KeyMapping)) - -#endif diff --git a/main.c b/main.c deleted file mode 100644 index 293b91b..0000000 --- a/main.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "keymap.h" - -GtkWidget *window = NULL; -struct libevdev *dev; -struct libevdev_uinput *uidev; -bool shift_active = false; -GList *key_buttons = NULL; - -static void apply_css() { - GtkCssProvider *provider = gtk_css_provider_new(); - gtk_css_provider_load_from_resource(provider, "/org/spaces/oskeyboard/style.css"); - gtk_style_context_add_provider_for_display( - gdk_display_get_default(), - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - ); - g_object_unref(provider); -} - -void press_key(int key_code) { - if (!uidev) return; - libevdev_uinput_write_event(uidev, EV_KEY, key_code, 1); - libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); - libevdev_uinput_write_event(uidev, EV_KEY, key_code, 0); - libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); -} - -static void update_labels() { - for (GList *l = key_buttons; l != NULL; l = l->next) { - GtkButton *btn = GTK_BUTTON(l->data); - const char *current = gtk_button_get_label(btn); - - for (int i = 0; i < KEY_MAP_SIZE; i++) { - if (shift_active && g_strcmp0(current, key_map[i].label) == 0) { - gtk_button_set_label(btn, key_map[i].shift_label); - break; - } else if (!shift_active && g_strcmp0(current, key_map[i].shift_label) == 0) { - gtk_button_set_label(btn, key_map[i].label); - break; - } - } - } -} - -static void on_key_clicked(GtkButton *button, gpointer user_data) { - const char *label = gtk_button_get_label(button); - - if (g_strcmp0(label, "Shift") == 0) { - shift_active = !shift_active; - update_labels(); - return; - } - - for (int i = 0; i < KEY_MAP_SIZE; i++) { - if (g_strcmp0(label, key_map[i].label) == 0 || g_strcmp0(label, key_map[i].shift_label) == 0) { - if (shift_active) { - libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTSHIFT, 1); - libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); - } - - press_key(key_map[i].key_code); - - if (shift_active) { - libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTSHIFT, 0); - libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); - shift_active = false; - update_labels(); - } - return; - } - } -} - -void add_key(GtkGrid *grid, const char *label, int col, int width) { - GtkWidget *button = gtk_button_new_with_label(label); - gtk_widget_set_hexpand(button, TRUE); - gtk_widget_set_halign(button, GTK_ALIGN_FILL); - gtk_widget_set_size_request(button, 94 * width, 94); - - g_signal_connect(button, "clicked", G_CALLBACK(on_key_clicked), NULL); - gtk_grid_attach(grid, button, col, 0, width, 1); - key_buttons = g_list_append(key_buttons, button); -} - -void init_evdev_keyboard() { - dev = libevdev_new(); - libevdev_set_name(dev, "OSKeyboard"); - libevdev_enable_event_type(dev, EV_KEY); - - for (int i = 0; i < KEY_MAP_SIZE; i++) { - libevdev_enable_event_code(dev, EV_KEY, key_map[i].key_code, NULL); - } - - int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); - if (fd < 0) { - fprintf(stderr, "Failed to open /dev/uinput: %s\n", strerror(errno)); - return; - } - - int err = libevdev_uinput_create_from_device(dev, fd, &uidev); - if (err != 0) { - fprintf(stderr, "Failed to create uinput device: %s\n", strerror(-err)); - close(fd); - return; - } -} - -static void activate(GtkApplication *app, gpointer user_data) { - if (window) { - if (gtk_widget_get_visible(window)) { - gtk_widget_set_visible(window, FALSE); - } else { - gtk_window_present(GTK_WINDOW(window)); - } - return; - } - - apply_css(); - - GtkBuilder *builder = gtk_builder_new_from_resource("/org/spaces/oskeyboard/keyboard.ui"); - window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window")); - - gtk_layer_init_for_window(GTK_WINDOW(window)); - gtk_layer_set_layer(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_BOTTOM); - gtk_layer_auto_exclusive_zone_enable(GTK_WINDOW(window)); - gtk_layer_set_keyboard_mode(GTK_WINDOW(window), FALSE); - gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); - gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); - gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); - - gtk_window_set_application(GTK_WINDOW(window), app); - - GtkGrid *rows[] = { - GTK_GRID(gtk_builder_get_object(builder, "kbd_row_0")), - GTK_GRID(gtk_builder_get_object(builder, "kbd_row_1")), - GTK_GRID(gtk_builder_get_object(builder, "kbd_row_2")), - GTK_GRID(gtk_builder_get_object(builder, "kbd_row_3")), - GTK_GRID(gtk_builder_get_object(builder, "kbd_row_4")) - }; - - int current_key = 0; - int row_counts[] = {14, 14, 13, 12, 6}; - - for (int r = 0; r < 5; r++) { - int current_col = 0; - for (int c = 0; c < row_counts[r]; c++) { - if (current_key >= KEY_MAP_SIZE) break; - - const char *label = key_map[current_key].label; - int width = 1; - - if (g_strcmp0(label, "Space") == 0) width = 7; - else if (g_strcmp0(label, "Backspace") == 0) width = 2; - else if (g_strcmp0(label, "Enter") == 0) width = 3; - else if (g_strcmp0(label, "Shift") == 0) width = 3; - else if (g_strcmp0(label, "Alt") == 0) width = 2; - else if (g_strcmp0(label, "Ctrl") == 0) width = 3; - else if (g_strcmp0(label, "Caps Lock") == 0) width = 2; - - add_key(rows[r], label, current_col, width); - current_col += width; - current_key++; - } - } - - init_evdev_keyboard(); - gtk_window_present(GTK_WINDOW(window)); - g_object_unref(builder); -} - -int main(int argc, char **argv) { - GtkApplication *app = gtk_application_new("org.spaces.oskeyboard", G_APPLICATION_DEFAULT_FLAGS); - g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); - int status = g_application_run(G_APPLICATION(app), argc, argv); - g_object_unref(app); - return status; -} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..4ed821e --- /dev/null +++ b/meson.build @@ -0,0 +1,12 @@ +project('oskeyboard', 'c', + version : '0.1', + default_options : ['warning_level=0']) + +# Import the GNOME module to handle GResources +gnome = import('gnome') + +gtk_dep = dependency('gtk4') +libevdev_dep = dependency('libevdev') +layer_shell_dep = dependency('gtk4-layer-shell-0') + +subdir('src') diff --git a/src/keyboard.ui b/src/keyboard.ui new file mode 100644 index 0000000..2d58fd9 --- /dev/null +++ b/src/keyboard.ui @@ -0,0 +1,13 @@ + + + + OSKeyboard + + + + FALSE + TRUE + + + + diff --git a/src/keymap.h b/src/keymap.h new file mode 100644 index 0000000..842e896 --- /dev/null +++ b/src/keymap.h @@ -0,0 +1,97 @@ +#ifndef KEYMAP_H +#define KEYMAP_H + +#include + +typedef struct { + const char *label; + const char *shift_label; + int key_code; + float weight; +} KeyDef; + +typedef struct { + KeyDef *keys; + int key_count; + float total_weight; +} RowDef; + +static const RowDef keys[] = { + // Top Row (0) + {(KeyDef[]){{"`", "~", KEY_GRAVE, 1.0}, + {"1", "!", KEY_1, 1.0}, + {"2", "@", KEY_2, 1.0}, + {"3", "#", KEY_3, 1.0}, + {"4", "$", KEY_4, 1.0}, + {"5", "%", KEY_5, 1.0}, + {"6", "^", KEY_6, 1.0}, + {"7", "&", KEY_7, 1.0}, + {"8", "*", KEY_8, 1.0}, + {"9", "(", KEY_9, 1.0}, + {"0", ")", KEY_0, 1.0}, + {"-", "_", KEY_MINUS, 1.0}, + {"=", "+", KEY_EQUAL, 1.0}, + {"Backspace", "Backspace", KEY_BACKSPACE, 1.5}}, + 14, 14.5}, + + // Row 1 + {(KeyDef[]){{"Tab", "Tab", KEY_TAB, 1.5}, + {"q", "Q", KEY_Q, 1.0}, + {"w", "W", KEY_W, 1.0}, + {"e", "E", KEY_E, 1.0}, + {"r", "R", KEY_R, 1.0}, + {"t", "T", KEY_T, 1.0}, + {"y", "Y", KEY_Y, 1.0}, + {"u", "U", KEY_U, 1.0}, + {"i", "I", KEY_I, 1.0}, + {"o", "O", KEY_O, 1.0}, + {"p", "P", KEY_P, 1.0}, + {"[", "{", KEY_LEFTBRACE, 1.0}, + {"]", "}", KEY_RIGHTBRACE, 1.0}, + {"\\", "|", KEY_BACKSLASH, 1.0}}, + 14, 14.5}, + + // Row 2 + {(KeyDef[]){{"Escape", "Escape", KEY_ESC, 2.0}, + {"a", "A", KEY_A, 1.0}, + {"s", "S", KEY_S, 1.0}, + {"d", "D", KEY_D, 1.0}, + {"f", "F", KEY_F, 1.0}, + {"g", "G", KEY_G, 1.0}, + {"h", "H", KEY_H, 1.0}, + {"j", "J", KEY_J, 1.0}, + {"k", "K", KEY_K, 1.0}, + {"l", "L", KEY_L, 1.0}, + {";", ":", KEY_SEMICOLON, 1.0}, + {"'", "\"", KEY_APOSTROPHE, 1.0}, + {"Enter", "Enter", KEY_ENTER, 2.0}}, + 13, 15.0}, + + // Row 3 + {(KeyDef[]){{"Shift", "Shift", KEY_LEFTSHIFT, 2.5}, + {"z", "Z", KEY_Z, 1.0}, + {"x", "X", KEY_X, 1.0}, + {"c", "C", KEY_C, 1.0}, + {"v", "V", KEY_V, 1.0}, + {"b", "B", KEY_B, 1.0}, + {"n", "N", KEY_N, 1.0}, + {"m", "M", KEY_M, 1.0}, + {",", "<", KEY_COMMA, 1.0}, + {".", ">", KEY_DOT, 1.0}, + {"/", "?", KEY_SLASH, 1.0}, + {"Shift", "Shift", KEY_RIGHTSHIFT, 2.0}}, + 12, 14.5}, + + // Row 4 + {(KeyDef[]){{"Ctrl", "Ctrl", KEY_LEFTCTRL, 2.0}, + {"Super", "Super", KEY_LEFTMETA, 1.0}, + {"Alt", "Alt", KEY_LEFTALT, 1.0}, + {"Space", "Space", KEY_SPACE, 6.0}, + {"Alt", "Alt", KEY_RIGHTALT, 1.0}, + {"Ctrl", "Ctrl", KEY_RIGHTCTRL, 1.0}}, + 6, 12.0}, +}; + +#define KEY_MAP_SIZE (sizeof(keys) / sizeof(RowDef)) + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..4006d7a --- /dev/null +++ b/src/main.c @@ -0,0 +1,235 @@ +#include "cairo.h" +#include "glib-object.h" +#include "keymap.h" +#include +#include +#include +#include +#include +#include + +GtkWidget *window = NULL; +GtkDrawingArea *area = NULL; + +struct libevdev *dev; +struct libevdev_uinput *uidev; + +static gboolean shift_active = FALSE; +static gboolean alt_active = FALSE; +static gboolean ctrl_active = FALSE; + +void send_keypress(int key_code) { + if (!uidev) + return; + libevdev_uinput_write_event(uidev, EV_KEY, key_code, 1); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + libevdev_uinput_write_event(uidev, EV_KEY, key_code, 0); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); +} + +static void on_click_pressed(GtkGestureClick *gesture, int n_press, double x, + double y, gpointer data) { + GtkWidget *widget = + gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); + int width = gtk_widget_get_width(widget); + int height = gtk_widget_get_height(widget); + + int row_height = height / 5; + int row_index = (int)(y / row_height); + if (row_index < 0 || row_index >= 5) + return; + + RowDef row = keys[row_index]; + double unit_width = (double)width / row.total_weight; + + double current_x = 0; + for (int i = 0; i < row.key_count; i++) { + double next_x = current_x + (row.keys[i].weight * unit_width); + + if (x >= current_x && x <= next_x) { + KeyDef *clicked_key = &row.keys[i]; + + if (clicked_key->key_code == KEY_LEFTSHIFT || + clicked_key->key_code == KEY_RIGHTSHIFT) { + shift_active = !shift_active; + gtk_widget_queue_draw(GTK_WIDGET(area)); + return; + } + + if (clicked_key->key_code == KEY_LEFTALT || + clicked_key->key_code == KEY_RIGHTALT) { + alt_active = !alt_active; + return; + } + + if (clicked_key->key_code == KEY_LEFTCTRL || + clicked_key->key_code == KEY_RIGHTCTRL) { + ctrl_active = !ctrl_active; + return; + } + + if (shift_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTSHIFT, 1); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + } + + if (alt_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTALT, 1); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + } + + if (ctrl_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTCTRL, 1); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + } + + send_keypress(clicked_key->key_code); + + if (shift_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTSHIFT, 0); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + + shift_active = FALSE; + gtk_widget_queue_draw(GTK_WIDGET(area)); + } + + if (alt_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTALT, 0); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + + alt_active = FALSE; + } + + if (ctrl_active) { + libevdev_uinput_write_event(uidev, EV_KEY, KEY_LEFTCTRL, 0); + libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); + + ctrl_active = FALSE; + } + + break; + } + current_x = next_x; + } +} + +static void draw_key(cairo_t *ct, KeyDef key, int x, int y, int key_width, + int key_height) { + cairo_set_source_rgba(ct, 1.0, 1.0, 1.0, 1.0); + cairo_set_line_width(ct, 3.0); + cairo_rectangle(ct, x, y, key_width, key_height); + cairo_stroke(ct); + + cairo_select_font_face(ct, "Hack Nerd Font Mono", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(ct, key_height * 0.17); + + const char *label_text = shift_active ? key.shift_label : key.label; + + cairo_text_extents_t extents; + cairo_text_extents(ct, label_text, &extents); + + double tx = x + (key_width - extents.width) / 2.0 - extents.x_bearing; + double ty = y + (key_height - extents.height) / 2.0 - extents.y_bearing; + + cairo_set_source_rgba(ct, 1.0, 1.0, 1.0, 1.0); + cairo_move_to(ct, tx, ty); + cairo_show_text(ct, label_text); +} + +static void draw_row(cairo_t *ct, RowDef row, int row_i, int width, + int height) { + int key_count = row.key_count; + float total_weight = row.total_weight; + + double key_width = width / total_weight; + int key_height = height / 5; + double y = key_height * row_i; + + double x = 0; + for (int i = 0; i < key_count; i++) { + double weighted_key_width = key_width * row.keys[i].weight; + draw_key(ct, row.keys[i], x, y, weighted_key_width, key_height); + x += weighted_key_width; + } +} + +static void draw_keyboard(GtkDrawingArea *area, cairo_t *ct, int width, + int height, gpointer data) { + cairo_set_source_rgba(ct, 0.0, 0.0, 0.0, 1.0); + cairo_paint(ct); + for (int i = 0; i < 5; i++) { + draw_row(ct, keys[i], i, width, height); + } +} + +void init_evdev_keyboard() { + dev = libevdev_new(); + libevdev_set_name(dev, "OSKeyboard"); + libevdev_enable_event_type(dev, EV_KEY); + + for (int r = 0; r < 5; r++) { + for (int k = 0; k < keys[r].key_count; k++) { + libevdev_enable_event_code(dev, EV_KEY, keys[r].keys[k].key_code, NULL); + } + } + + int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (fd < 0) { + fprintf(stderr, "Failed to open /dev/uinput: %s\n", strerror(errno)); + return; + } + + int err = libevdev_uinput_create_from_device(dev, fd, &uidev); + if (err != 0) { + fprintf(stderr, "Failed to create uinput device: %s\n", strerror(-err)); + close(fd); + return; + } +} + +static void activate(GtkApplication *app, gpointer user_data) { + if (window) { + if (gtk_widget_get_visible(window)) { + gtk_widget_set_visible(window, FALSE); + } else { + gtk_window_present(GTK_WINDOW(window)); + } + return; + } + + GtkBuilder *builder = + gtk_builder_new_from_resource("/org/spaces/oskeyboard/keyboard.ui"); + window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window")); + + gtk_layer_init_for_window(GTK_WINDOW(window)); + gtk_layer_set_layer(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_BOTTOM); + gtk_layer_auto_exclusive_zone_enable(GTK_WINDOW(window)); + gtk_layer_set_keyboard_mode(GTK_WINDOW(window), FALSE); + gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor(GTK_WINDOW(window), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_widget_set_size_request(window, 1000, 500); + gtk_window_set_application(GTK_WINDOW(window), app); + + area = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "drawing_area")); + gtk_drawing_area_set_draw_func(area, draw_keyboard, NULL, NULL); + + GtkGesture *gesture = gtk_gesture_click_new(); + g_signal_connect(gesture, "pressed", G_CALLBACK(on_click_pressed), NULL); + gtk_widget_add_controller(GTK_WIDGET(area), GTK_EVENT_CONTROLLER(gesture)); + + init_evdev_keyboard(); + gtk_window_present(GTK_WINDOW(window)); + g_object_unref(builder); +} + +int main(int argc, char **argv) { + GtkApplication *app = + gtk_application_new("org.spaces.oskeyboard", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + + int status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + return status; +} diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..4fb6466 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,12 @@ +# Compile the resources into a C file +res = gnome.compile_resources( + 'oskeyboard-resources', + 'resources.xml', + source_dir: '.', # Look for .ui and .css in the current directory +) + +executable('osk', + 'main.c', + res, # Add the compiled resource file to the sources + dependencies : [gtk_dep, libevdev_dep, layer_shell_dep], + install : true) diff --git a/resources.xml b/src/resources.xml similarity index 100% rename from resources.xml rename to src/resources.xml diff --git a/style.css b/src/style.css similarity index 100% rename from style.css rename to src/style.css