mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
feat: add kernel clipboard manager
Adds a global kernel clipboard with write/read/len syscalls (IDs 54-56). Exposes sys_clipboard_write/read/len() in userland libc and ui_clipboard_set/get() in libui. Includes cliptest app for runtime verification (PASS confirmed in QEMU). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
85c93cbcfa
commit
e8a77054db
7 changed files with 139 additions and 0 deletions
|
|
@ -27,6 +27,7 @@
|
||||||
#include "app_metadata.h"
|
#include "app_metadata.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "mkfs_fat32.h"
|
#include "mkfs_fat32.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
#define SYSTEM_CMD_DISK_GET_COUNT 100
|
#define SYSTEM_CMD_DISK_GET_COUNT 100
|
||||||
#define SYSTEM_CMD_DISK_GET_INFO 101
|
#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();
|
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 {
|
typedef struct {
|
||||||
char devname[16];
|
char devname[16];
|
||||||
char label[32];
|
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_PARALLEL_RUN] = sys_cmd_parallel_run,
|
||||||
[SYSTEM_CMD_SET_KEYBOARD_LAYOUT] = sys_cmd_set_keyboard_layout,
|
[SYSTEM_CMD_SET_KEYBOARD_LAYOUT] = sys_cmd_set_keyboard_layout,
|
||||||
[SYSTEM_CMD_GET_KEYBOARD_LAYOUT] = sys_cmd_get_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_SET_MOUSE_CURSOR_SCALE] = sys_cmd_set_mouse_cursor_scale,
|
||||||
[SYSTEM_CMD_GET_MOUSE_CURSOR_SCALE] = sys_cmd_get_mouse_cursor_scale,
|
[SYSTEM_CMD_GET_MOUSE_CURSOR_SCALE] = sys_cmd_get_mouse_cursor_scale,
|
||||||
[SYSTEM_CMD_TTY_CREATE] = sys_cmd_tty_create,
|
[SYSTEM_CMD_TTY_CREATE] = sys_cmd_tty_create,
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,10 @@ typedef struct {
|
||||||
#define SYSTEM_CMD_GET_ELF_METADATA 76
|
#define SYSTEM_CMD_GET_ELF_METADATA 76
|
||||||
#define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77
|
#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);
|
void syscall_init(void);
|
||||||
uint64_t syscall_handler_c(registers_t *regs);
|
uint64_t syscall_handler_c(registers_t *regs);
|
||||||
|
|
||||||
|
|
|
||||||
61
src/userland/gui/cliptest.c
Normal file
61
src/userland/gui/cliptest.c
Normal file
|
|
@ -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 <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
void ui_set_font(ui_window_t win, const char *path) {
|
||||||
syscall3(SYS_GUI, GUI_CMD_SET_FONT, (uint64_t)win, (uint64_t)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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_window_set_resizable(ui_window_t win, bool resizable);
|
||||||
void ui_set_font(ui_window_t win, const char *path);
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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) {
|
int sys_open(const char *path, const char *mode) {
|
||||||
return (int)syscall3(SYS_FS, FS_CMD_OPEN, (uint64_t)path, (uint64_t)mode);
|
return (int)syscall3(SYS_FS, FS_CMD_OPEN, (uint64_t)path, (uint64_t)mode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,10 @@
|
||||||
#define SYSTEM_CMD_GET_ELF_METADATA 76
|
#define SYSTEM_CMD_GET_ELF_METADATA 76
|
||||||
#define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77
|
#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_TERMINAL 0x1
|
||||||
#define SPAWN_FLAG_INHERIT_TTY 0x2
|
#define SPAWN_FLAG_INHERIT_TTY 0x2
|
||||||
#define SPAWN_FLAG_TTY_ID 0x4
|
#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_rescan(const char *devname);
|
||||||
int sys_disk_replace_kernel(const char *src_path, const char *esp_mountpoint);
|
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
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue