diff --git a/src/sys/syscall.c b/src/sys/syscall.c index 951683b..e856be4 100644 --- a/src/sys/syscall.c +++ b/src/sys/syscall.c @@ -27,6 +27,7 @@ #include "app_metadata.h" #include "disk.h" #include "mkfs_fat32.h" +#include "spinlock.h" #define SYSTEM_CMD_DISK_GET_COUNT 100 #define SYSTEM_CMD_DISK_GET_INFO 101 @@ -2207,6 +2208,39 @@ static uint64_t sys_cmd_get_keyboard_layout(const syscall_args_t *args) { return (uint64_t)keymap_get_current(); } +#define CLIPBOARD_MAX_SIZE 4096 +static char g_clipboard[CLIPBOARD_MAX_SIZE]; +static int g_clipboard_len = 0; +static spinlock_t g_clipboard_lock = SPINLOCK_INIT; + +static uint64_t sys_cmd_clipboard_write(const syscall_args_t *args) { + const char *buf = (const char *)args->arg2; + int len = (int)args->arg3; + if (!buf || len <= 0) return 0; + if (len > CLIPBOARD_MAX_SIZE) len = CLIPBOARD_MAX_SIZE; + uint64_t flags = spinlock_acquire_irqsave(&g_clipboard_lock); + for (int i = 0; i < len; i++) g_clipboard[i] = buf[i]; + g_clipboard_len = len; + spinlock_release_irqrestore(&g_clipboard_lock, flags); + return (uint64_t)len; +} + +static uint64_t sys_cmd_clipboard_read(const syscall_args_t *args) { + char *buf = (char *)args->arg2; + int max_len = (int)args->arg3; + if (!buf || max_len <= 0) return 0; + uint64_t flags = spinlock_acquire_irqsave(&g_clipboard_lock); + int n = g_clipboard_len < max_len ? g_clipboard_len : max_len; + for (int i = 0; i < n; i++) buf[i] = g_clipboard[i]; + spinlock_release_irqrestore(&g_clipboard_lock, flags); + return (uint64_t)n; +} + +static uint64_t sys_cmd_clipboard_len(const syscall_args_t *args) { + (void)args; + return (uint64_t)g_clipboard_len; +} + typedef struct { char devname[16]; char label[32]; @@ -2484,6 +2518,9 @@ static const syscall_handler_fn sys_cmd_table[SYS_CMD_TABLE_SIZE] = { [SYSTEM_CMD_PARALLEL_RUN] = sys_cmd_parallel_run, [SYSTEM_CMD_SET_KEYBOARD_LAYOUT] = sys_cmd_set_keyboard_layout, [SYSTEM_CMD_GET_KEYBOARD_LAYOUT] = sys_cmd_get_keyboard_layout, + [SYSTEM_CMD_CLIPBOARD_WRITE] = sys_cmd_clipboard_write, + [SYSTEM_CMD_CLIPBOARD_READ] = sys_cmd_clipboard_read, + [SYSTEM_CMD_CLIPBOARD_LEN] = sys_cmd_clipboard_len, [SYSTEM_CMD_SET_MOUSE_CURSOR_SCALE] = sys_cmd_set_mouse_cursor_scale, [SYSTEM_CMD_GET_MOUSE_CURSOR_SCALE] = sys_cmd_get_mouse_cursor_scale, [SYSTEM_CMD_TTY_CREATE] = sys_cmd_tty_create, diff --git a/src/sys/syscall.h b/src/sys/syscall.h index 210ed86..702f0ca 100644 --- a/src/sys/syscall.h +++ b/src/sys/syscall.h @@ -127,6 +127,10 @@ typedef struct { #define SYSTEM_CMD_GET_ELF_METADATA 76 #define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77 +#define SYSTEM_CMD_CLIPBOARD_WRITE 54 +#define SYSTEM_CMD_CLIPBOARD_READ 55 +#define SYSTEM_CMD_CLIPBOARD_LEN 56 + void syscall_init(void); uint64_t syscall_handler_c(registers_t *regs); diff --git a/src/userland/gui/cliptest.c b/src/userland/gui/cliptest.c new file mode 100644 index 0000000..603a38a --- /dev/null +++ b/src/userland/gui/cliptest.c @@ -0,0 +1,61 @@ +// Copyright (c) 2026 BoredOS Contributors +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in any file it is present in, as per the GPL license terms. +// BOREDOS_APP_DESC: Clipboard integration test. +// BOREDOS_APP_ICONS: /Library/images/icons/colloid/copyq.png +#include "libc/syscall.h" +#include "libc/libui.h" +#include "libc/string.h" +#include +#include + +#define WIN_W 400 +#define WIN_H 200 +#define BG 0xFF1E1E2E +#define WHITE 0xFFCDD6F4 +#define GREEN 0xFFA6E3A1 +#define RED 0xFFF38BA8 +#define GREY 0xFF45475A + +static void draw(ui_window_t win, const char *written, const char *read_back, bool match) { + ui_draw_rect(win, 0, 0, WIN_W, WIN_H, BG); + + ui_draw_string(win, 10, 20, "Clipboard Test", WHITE); + + ui_draw_string(win, 10, 60, "Written:", GREY); + ui_draw_string(win, 90, 60, written, WHITE); + + ui_draw_string(win, 10, 90, "Read back:", GREY); + ui_draw_string(win, 90, 90, read_back, WHITE); + + ui_draw_string(win, 10, 130, "Result:", GREY); + if (match) + ui_draw_string(win, 90, 130, "PASS - write/read match", GREEN); + else + ui_draw_string(win, 90, 130, "FAIL - mismatch!", RED); + + ui_mark_dirty(win, 0, 0, WIN_W, WIN_H); +} + +int main(void) { + const char *test_str = "Hello, Clipboard!"; + char read_buf[64] = {0}; + + ui_clipboard_set(test_str); + int n = ui_clipboard_get(read_buf, sizeof(read_buf)); + + bool match = (n > 0) && (strcmp(test_str, read_buf) == 0); + + ui_window_t win = ui_window_create("Clipboard Test", 100, 100, WIN_W, WIN_H); + + draw(win, test_str, read_buf, match); + + gui_event_t ev; + while (1) { + if (!ui_get_event(win, &ev)) { sys_yield(); continue; } + if (ev.type == GUI_EVENT_CLOSE) break; + if (ev.type == GUI_EVENT_PAINT) draw(win, test_str, read_buf, match); + } + + return 0; +} diff --git a/src/userland/libc/libui.c b/src/userland/libc/libui.c index 3a87672..098b95c 100644 --- a/src/userland/libc/libui.c +++ b/src/userland/libc/libui.c @@ -102,3 +102,15 @@ void ui_window_set_resizable(ui_window_t win, bool resizable) { void ui_set_font(ui_window_t win, const char *path) { syscall3(SYS_GUI, GUI_CMD_SET_FONT, (uint64_t)win, (uint64_t)path); } + +void ui_clipboard_set(const char *text) { + if (!text) return; + int len = 0; + while (text[len]) len++; + sys_clipboard_write(text, len + 1); +} + +int ui_clipboard_get(char *buf, int max_len) { + if (!buf || max_len <= 0) return 0; + return sys_clipboard_read(buf, max_len); +} diff --git a/src/userland/libc/libui.h b/src/userland/libc/libui.h index 38d92e4..112bd1e 100644 --- a/src/userland/libc/libui.h +++ b/src/userland/libc/libui.h @@ -75,4 +75,8 @@ void ui_window_set_title(ui_window_t win, const char *title); void ui_window_set_resizable(ui_window_t win, bool resizable); void ui_set_font(ui_window_t win, const char *path); +// Clipboard API — text only, null-terminated strings +void ui_clipboard_set(const char *text); +int ui_clipboard_get(char *buf, int max_len); + #endif diff --git a/src/userland/libc/syscall.c b/src/userland/libc/syscall.c index e4f4272..ba754f8 100644 --- a/src/userland/libc/syscall.c +++ b/src/userland/libc/syscall.c @@ -89,6 +89,18 @@ int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t ar return (int)syscall5(SYS_SYSTEM, (uint64_t)cmd, arg1, arg2, arg3, arg4); } +int sys_clipboard_write(const char *buf, int len) { + return sys_system(SYSTEM_CMD_CLIPBOARD_WRITE, (uint64_t)buf, (uint64_t)len, 0, 0); +} + +int sys_clipboard_read(char *buf, int max_len) { + return sys_system(SYSTEM_CMD_CLIPBOARD_READ, (uint64_t)buf, (uint64_t)max_len, 0, 0); +} + +int sys_clipboard_len(void) { + return sys_system(SYSTEM_CMD_CLIPBOARD_LEN, 0, 0, 0, 0); +} + int sys_open(const char *path, const char *mode) { return (int)syscall3(SYS_FS, FS_CMD_OPEN, (uint64_t)path, (uint64_t)mode); } diff --git a/src/userland/libc/syscall.h b/src/userland/libc/syscall.h index 476262c..105a39c 100644 --- a/src/userland/libc/syscall.h +++ b/src/userland/libc/syscall.h @@ -108,6 +108,10 @@ #define SYSTEM_CMD_GET_ELF_METADATA 76 #define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77 +#define SYSTEM_CMD_CLIPBOARD_WRITE 54 +#define SYSTEM_CMD_CLIPBOARD_READ 55 +#define SYSTEM_CMD_CLIPBOARD_LEN 56 + #define SPAWN_FLAG_TERMINAL 0x1 #define SPAWN_FLAG_INHERIT_TTY 0x2 #define SPAWN_FLAG_TTY_ID 0x4 @@ -309,4 +313,9 @@ int sys_disk_sync(const char *mountpoint); int sys_disk_rescan(const char *devname); int sys_disk_replace_kernel(const char *src_path, const char *esp_mountpoint); +// Clipboard API +int sys_clipboard_write(const char *buf, int len); +int sys_clipboard_read(char *buf, int max_len); +int sys_clipboard_len(void); + #endif