mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 10:26:59 +00:00
feature(input): implement keyboard layouts and utf-8 input subsystem
* Adding keyboard layout (backend) * Update settings.c with new keyboard tab * Fixing keyboard icon && Fixing long loading time in settings.c * Refactor of key handling for a larger compatibility with the keyboard layout * Adding keyboard handler * Udating ps2.c with the new logic * Updating WM/kernel/userland with the new input system * Fixing keycode range && Updating dead keys handling * Add comments for explanation * Update notepad & vm.c to parse utf-8 * Adding utf-8 parsing utils in libc && Update notepad.c * Adding icon for icon settings * Fixing a warning with double definition * Adding new kb kayout: QWERTZ and DVORAK && Update new layout instrauction * Add documentation for keyboard input subsystem This document outlines the architecture and design of the input subsystem, focusing on keyboard input processing, driver responsibilities, keycode representation, and keymap functionality. --------- Co-authored-by: boreddevnl <chris@boreddev.nl>
This commit is contained in:
@@ -1414,7 +1414,12 @@ static void explorer_handle_click(Window *win, int x, int y) {
|
||||
}
|
||||
}
|
||||
|
||||
static void explorer_handle_key(Window *win, char c, bool pressed) {
|
||||
static void explorer_handle_key(Window *win, int legacy, uint16_t keycode, uint32_t codepoint, uint32_t mods, bool pressed) {
|
||||
(void)keycode;
|
||||
(void)codepoint;
|
||||
(void)mods;
|
||||
char c = (char)legacy;
|
||||
|
||||
if (!pressed) return;
|
||||
ExplorerState *state = (ExplorerState*)win->data;
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
int arg1; // For click: x
|
||||
int arg2; // For click: y
|
||||
int arg3; // For click: button state
|
||||
int arg1; // CLICK: x / KEY: legacy char-or-compat key
|
||||
int arg2; // CLICK: y / KEY: keycode
|
||||
int arg3; // CLICK: button state / KEY: modifier mask
|
||||
int arg4; // KEY: Unicode codepoint (0 if none)
|
||||
} gui_event_t;
|
||||
|
||||
#endif
|
||||
|
||||
43
src/wm/wm.c
43
src/wm/wm.c
@@ -22,6 +22,8 @@
|
||||
#include "../sys/work_queue.h"
|
||||
#include "../sys/smp.h"
|
||||
#include "../core/kconsole.h"
|
||||
#include "../input/keycodes.h"
|
||||
#include "../input/keymap.h"
|
||||
|
||||
|
||||
// Hello developer,
|
||||
@@ -30,7 +32,7 @@
|
||||
// TRUST ME.
|
||||
// If you do decide to hate yourself for some dumb reason,
|
||||
// add a few hours to the counter of despair:
|
||||
// hours wasted: 57
|
||||
// hours wasted: 61
|
||||
// send help
|
||||
|
||||
#include "../sys/spinlock.h"
|
||||
@@ -98,7 +100,7 @@ static char notif_text[256] = {0};
|
||||
static int notif_timer = 0;
|
||||
static int notif_x_offset = 420; // Starts offscreen
|
||||
static bool notif_active = false;
|
||||
extern bool ps2_ctrl_pressed;
|
||||
|
||||
|
||||
static lumos_state_t lumos_state = {0};
|
||||
static bool lumos_index_built = false;
|
||||
@@ -3652,14 +3654,18 @@ void wm_handle_mouse(int dx, int dy, uint8_t buttons, int dz) {
|
||||
// Input Queue
|
||||
#define INPUT_QUEUE_SIZE 128
|
||||
typedef struct {
|
||||
char c;
|
||||
int legacy;
|
||||
uint16_t keycode;
|
||||
uint32_t codepoint;
|
||||
uint32_t mods;
|
||||
bool pressed;
|
||||
} key_event_t;
|
||||
static key_event_t key_queue[INPUT_QUEUE_SIZE];
|
||||
static volatile int key_head = 0;
|
||||
static volatile int key_tail = 0;
|
||||
|
||||
static void wm_dispatch_key(char c, bool pressed) {
|
||||
static void wm_dispatch_key(int legacy, uint16_t keycode, uint32_t codepoint, uint32_t mods, bool pressed) {
|
||||
char c = (char)legacy;
|
||||
if (desktop_dialog_state != 0) {
|
||||
int len = 0; while(desktop_dialog_input[len]) len++;
|
||||
if (c == '\n') {
|
||||
@@ -3721,7 +3727,7 @@ static void wm_dispatch_key(char c, bool pressed) {
|
||||
|
||||
|
||||
if (target->handle_key) {
|
||||
target->handle_key(target, c, pressed);
|
||||
target->handle_key(target, legacy, keycode, codepoint, mods, pressed);
|
||||
}
|
||||
|
||||
// Mark window as needing redraw on next timer tick
|
||||
@@ -3748,18 +3754,20 @@ static void build_file_index_async(void *arg) {
|
||||
file_index_build();
|
||||
}
|
||||
|
||||
void wm_handle_key(char c, bool pressed) {
|
||||
if (pressed && c == 'p' && ps2_ctrl_pressed) {
|
||||
// Called by keyboard interrupt handler
|
||||
void wm_handle_key_event(uint16_t keycode, uint32_t codepoint, uint32_t mods, bool pressed) {
|
||||
int legacy = keymap_legacy_key(keycode, codepoint);
|
||||
char c = (char)legacy;
|
||||
|
||||
if (pressed && keycode == KEY_P && (mods & KB_MOD_CTRL)) {
|
||||
process_create_elf("/bin/screenshot.elf", NULL, false, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressed && c == ' ' && ps2_ctrl_pressed && ps2_shift_pressed()) {
|
||||
|
||||
if (pressed && keycode == KEY_SPACE && (mods & KB_MOD_CTRL) && (mods & KB_MOD_SHIFT)) {
|
||||
lumos_state.visible = !lumos_state.visible;
|
||||
if (lumos_state.visible) {
|
||||
// Check current index status - it may still be building in background
|
||||
lumos_index_built = file_index_is_valid();
|
||||
// Clear search state when opening
|
||||
lumos_state.search_len = 0;
|
||||
lumos_state.search_query[0] = 0;
|
||||
lumos_state.cursor_pos = 0;
|
||||
@@ -3772,15 +3780,18 @@ void wm_handle_key(char c, bool pressed) {
|
||||
force_redraw = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lumos_state.visible && pressed) {
|
||||
|
||||
if (lumos_state.visible && pressed && legacy != 0) {
|
||||
wm_lumos_handle_key(c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int next = (key_head + 1) % INPUT_QUEUE_SIZE;
|
||||
if (next != key_tail) {
|
||||
key_queue[key_head].c = c;
|
||||
key_queue[key_head].legacy = legacy;
|
||||
key_queue[key_head].keycode = keycode;
|
||||
key_queue[key_head].codepoint = codepoint;
|
||||
key_queue[key_head].mods = mods;
|
||||
key_queue[key_head].pressed = pressed;
|
||||
key_head = next;
|
||||
}
|
||||
@@ -3801,7 +3812,7 @@ void wm_process_input(void) {
|
||||
while (key_head != key_tail) {
|
||||
key_event_t ev = key_queue[key_tail];
|
||||
key_tail = (key_tail + 1) % INPUT_QUEUE_SIZE;
|
||||
wm_dispatch_key(ev.c, ev.pressed);
|
||||
wm_dispatch_key(ev.legacy, ev.keycode, ev.codepoint, ev.mods, ev.pressed);
|
||||
}
|
||||
wm_lock_release(rflags);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ struct Window {
|
||||
|
||||
// Callbacks
|
||||
void (*paint)(Window *win);
|
||||
void (*handle_key)(Window *win, char c, bool pressed);
|
||||
void (*handle_key)(Window *win, int legacy, uint16_t keycode, uint32_t codepoint, uint32_t mods, bool pressed);
|
||||
void (*handle_click)(Window *win, int x, int y);
|
||||
void (*handle_right_click)(Window *win, int x, int y);
|
||||
void (*handle_mouse_down)(Window *win, int x, int y);
|
||||
@@ -91,7 +91,7 @@ typedef struct {
|
||||
|
||||
void wm_init(void);
|
||||
void wm_handle_mouse(int dx, int dy, uint8_t buttons, int dz);
|
||||
void wm_handle_key(char c, bool pressed);
|
||||
void wm_handle_key_event(uint16_t keycode, uint32_t codepoint, uint32_t mods, bool pressed);
|
||||
void wm_handle_click(int x, int y);
|
||||
void wm_handle_right_click(int x, int y);
|
||||
void wm_process_input(void);
|
||||
|
||||
Reference in New Issue
Block a user