PTY和更多

This commit is contained in:
2026-04-26 11:57:51 +08:00
parent 32b27cc362
commit 298de5e33f
27 changed files with 3264 additions and 114 deletions

View File

@@ -41,6 +41,16 @@ set(CLEONOS_QEMU_INPUT_ARGS "")
if(CLEONOS_QEMU_ENABLE_USB_TABLET)
list(APPEND CLEONOS_QEMU_INPUT_ARGS -usb -device usb-tablet)
endif()
set(CLEONOS_OPT_LEVEL "" CACHE STRING "Optional C/C++ optimization level, e.g. 2 or O2")
set(CLEONOS_OPT_FLAG "")
if(NOT "${CLEONOS_OPT_LEVEL}" STREQUAL "")
set(_cleonos_opt_level "${CLEONOS_OPT_LEVEL}")
string(REGEX REPLACE "^-?O" "" _cleonos_opt_level "${_cleonos_opt_level}")
if(NOT _cleonos_opt_level MATCHES "^(0|1|2|3|s|z|g|fast)$")
cl_log_error("unsupported CLEONOS_OPT_LEVEL=${CLEONOS_OPT_LEVEL}; use 0/1/2/3/s/z/g/fast or O2-style values")
endif()
set(CLEONOS_OPT_FLAG "-O${_cleonos_opt_level}")
endif()
set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos")
if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
@@ -168,17 +178,28 @@ set(USER_CFLAGS
-ffreestanding
-fno-stack-protector
-fno-builtin
-ffunction-sections
-fdata-sections
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=0
-Wall
-Wextra
-Werror
"-I${CMAKE_SOURCE_DIR}/cleonos/c/include"
)
if(NOT "${CLEONOS_OPT_FLAG}" STREQUAL "")
list(APPEND USER_CFLAGS "${CLEONOS_OPT_FLAG}")
endif()
set(USER_CFLAGS_DOOM
-std=c11
-ffreestanding
-fno-stack-protector
-fno-builtin
-ffunction-sections
-fdata-sections
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=0
-Wall
-Wextra
-Wno-error
@@ -191,12 +212,19 @@ set(USER_CFLAGS_DOOM
"-include"
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/doom_shim.h"
)
if(NOT "${CLEONOS_OPT_FLAG}" STREQUAL "")
list(APPEND USER_CFLAGS_DOOM "${CLEONOS_OPT_FLAG}")
endif()
set(USER_CFLAGS_BROWSER
-std=c11
-ffreestanding
-fno-stack-protector
-fno-builtin
-ffunction-sections
-fdata-sections
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=0
-Wall
-Wextra
-Wno-error
@@ -208,11 +236,15 @@ set(USER_CFLAGS_BROWSER
"-I${CMAKE_SOURCE_DIR}/cleonos/third-party/litehtml/src/gumbo/include"
"-I${CMAKE_SOURCE_DIR}/cleonos/third-party/litehtml/src/gumbo/include/gumbo"
)
if(NOT "${CLEONOS_OPT_FLAG}" STREQUAL "")
list(APPEND USER_CFLAGS_BROWSER "${CLEONOS_OPT_FLAG}")
endif()
set(USER_LDFLAGS
-nostdlib
-z
max-page-size=0x1000
--gc-sections
-T
"${USER_LINKER_SCRIPT}"
)
@@ -240,6 +272,7 @@ set(CLKS_SUBMODULE_CMAKE_ARGS
"-DCLKS_ARCH=${CLKS_ARCH}"
"-DCLKS_BUILD_ROOT=${BUILD_ROOT}"
"-DCLKS_MENUCONFIG_CMAKE=${CMAKE_SOURCE_DIR}/configs/menuconfig/config.cmake"
"-DCLKS_OPT_LEVEL=${CLEONOS_OPT_LEVEL}"
"-DCC=${CC}"
"-DKERNEL_CXX=${KERNEL_CXX}"
"-DLD=${LD}"

View File

@@ -6,6 +6,8 @@ CMAKE_BUILD_DIR ?= build-cmake
CMAKE_BUILD_TYPE ?= Release
CMAKE_GENERATOR ?=
CMAKE_EXTRA_ARGS ?=
OPT_LEVEL ?=
O2 ?= 0
NO_COLOR ?= 0
LIMINE_SKIP_CONFIGURE ?=
LIMINE_REF ?=
@@ -32,7 +34,7 @@ CMAKE_CONFIG_VERBOSE_ARG := -DCMAKE_VERBOSE_MAKEFILE=ON
else
Q := @
CMAKE_BUILD_VERBOSE_ARG :=
CMAKE_CONFIG_VERBOSE_ARG :=
CMAKE_CONFIG_VERBOSE_ARG := -DCMAKE_VERBOSE_MAKEFILE=OFF
endif
ifeq ($(strip $(CMAKE_GENERATOR)),)
@@ -44,6 +46,13 @@ endif
CMAKE_PASSTHROUGH_ARGS :=
MENUCONFIG_PRESET_ARG := $(if $(strip $(MENUCONFIG_PRESET)),--preset $(MENUCONFIG_PRESET),)
CLEONOS_SOURCE_PRESENT := $(if $(wildcard cleonos/CMakeLists.txt),1,0)
OPT_LEVEL_EFFECTIVE := $(strip $(OPT_LEVEL))
ifeq ($(OPT_LEVEL_EFFECTIVE),)
ifneq ($(filter 1 ON on TRUE true YES yes Y y,$(O2)),)
OPT_LEVEL_EFFECTIVE := 2
endif
endif
ifeq ($(strip $(CLEONOS_ENABLE)),auto)
ifeq ($(CLEONOS_SOURCE_PRESENT),1)
@@ -70,6 +79,7 @@ endif
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE)
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_QEMU_ENABLE_USB_TABLET=$(CLEONOS_QEMU_ENABLE_USB_TABLET)
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_OPT_LEVEL=$(OPT_LEVEL_EFFECTIVE)
ifneq ($(strip $(LIMINE_SKIP_CONFIGURE)),)
CMAKE_PASSTHROUGH_ARGS += -DLIMINE_SKIP_CONFIGURE=$(LIMINE_SKIP_CONFIGURE)
@@ -112,7 +122,7 @@ configure:
reconfigure:
> $(Q)rm -rf $(CMAKE_BUILD_DIR)
> $(Q)$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)"
> $(Q)$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" OPT_LEVEL="$(OPT_LEVEL)" O2="$(O2)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" CLEONOS_QEMU_ENABLE_USB_TABLET="$(CLEONOS_QEMU_ENABLE_USB_TABLET)"
menuconfig:
> $(Q)if command -v $(PYTHON) >/dev/null 2>&1; then \
@@ -244,6 +254,9 @@ help:
> $(Q)echo "QEMU USB tablet toggle:"
> $(Q)echo " make run CLEONOS_QEMU_ENABLE_USB_TABLET=OFF # default: PS/2 mouse path"
> $(Q)echo " make run CLEONOS_QEMU_ENABLE_USB_TABLET=ON # USB tablet, requires USB HID support"
> $(Q)echo "Optimization:"
> $(Q)echo " make run O2=1"
> $(Q)echo " make run OPT_LEVEL=2"
> $(Q)echo ""
> $(Q)echo "Pass custom CMake cache args via:"
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"

View File

@@ -176,7 +176,7 @@ set(USER_SHELL_COMMAND_APPS
diskinfo mkfsfat32 mount partctl
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm kdbg bmpview qrcode browser
vim uwm
vim uwm terminal
)
foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
@@ -280,7 +280,7 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
)
list(APPEND USER_APP_OUTPUTS "${_app_out}")
if(_app_name STREQUAL "file_explorer")
if(_app_name STREQUAL "file_explorer" OR _app_name STREQUAL "terminal" OR _app_name STREQUAL "taskmgr")
list(APPEND RAMDISK_UWM_APPS "${_app_out}")
elseif(_app_name MATCHES ".*drv$")
list(APPEND RAMDISK_DRIVER_APPS "${_app_out}")

232
cleonos/c/apps/app_heap.inc Normal file
View File

@@ -0,0 +1,232 @@
#include <stddef.h>
#include <string.h>
#ifndef CLEONOS_APP_HEAP_CAPACITY
#define CLEONOS_APP_HEAP_CAPACITY (2U * 1024U * 1024U)
#endif
#define CLEONOS_APP_HEAP_ALIGN 8U
#define CLEONOS_APP_HEAP_MAGIC 0xC10A5A7EU
typedef union cleonos_app_heap_storage {
unsigned long long align;
unsigned char bytes[CLEONOS_APP_HEAP_CAPACITY];
} cleonos_app_heap_storage;
typedef struct cleonos_app_heap_block {
size_t size;
unsigned int used;
unsigned int magic;
struct cleonos_app_heap_block *next;
struct cleonos_app_heap_block *prev;
} cleonos_app_heap_block;
static cleonos_app_heap_storage cleonos_app_heap;
static cleonos_app_heap_block *cleonos_app_heap_head = (cleonos_app_heap_block *)0;
static int cleonos_app_heap_ready = 0;
static size_t cleonos_app_heap_align_up(size_t value, size_t align) {
size_t mask;
if (align == 0U) {
return value;
}
mask = align - 1U;
return (value + mask) & ~mask;
}
static void cleonos_app_heap_init(void) {
size_t header_size = cleonos_app_heap_align_up(sizeof(cleonos_app_heap_block), CLEONOS_APP_HEAP_ALIGN);
if (cleonos_app_heap_ready != 0) {
return;
}
if ((size_t)CLEONOS_APP_HEAP_CAPACITY <= header_size + CLEONOS_APP_HEAP_ALIGN) {
return;
}
cleonos_app_heap_head = (cleonos_app_heap_block *)(void *)cleonos_app_heap.bytes;
cleonos_app_heap_head->size = (size_t)CLEONOS_APP_HEAP_CAPACITY - header_size;
cleonos_app_heap_head->used = 0U;
cleonos_app_heap_head->magic = CLEONOS_APP_HEAP_MAGIC;
cleonos_app_heap_head->next = (cleonos_app_heap_block *)0;
cleonos_app_heap_head->prev = (cleonos_app_heap_block *)0;
cleonos_app_heap_ready = 1;
}
static void cleonos_app_heap_split(cleonos_app_heap_block *block, size_t need) {
size_t header_size = cleonos_app_heap_align_up(sizeof(cleonos_app_heap_block), CLEONOS_APP_HEAP_ALIGN);
unsigned char *next_addr;
cleonos_app_heap_block *next;
if (block == (cleonos_app_heap_block *)0 || block->size <= need + header_size + CLEONOS_APP_HEAP_ALIGN) {
return;
}
next_addr = ((unsigned char *)(void *)block) + header_size + need;
next = (cleonos_app_heap_block *)(void *)next_addr;
next->size = block->size - need - header_size;
next->used = 0U;
next->magic = CLEONOS_APP_HEAP_MAGIC;
next->next = block->next;
next->prev = block;
if (next->next != (cleonos_app_heap_block *)0) {
next->next->prev = next;
}
block->next = next;
block->size = need;
}
static void cleonos_app_heap_merge_next(cleonos_app_heap_block *block) {
size_t header_size = cleonos_app_heap_align_up(sizeof(cleonos_app_heap_block), CLEONOS_APP_HEAP_ALIGN);
cleonos_app_heap_block *next;
if (block == (cleonos_app_heap_block *)0 || block->used != 0U) {
return;
}
next = block->next;
if (next == (cleonos_app_heap_block *)0 || next->magic != CLEONOS_APP_HEAP_MAGIC || next->used != 0U) {
return;
}
block->size += header_size + next->size;
block->next = next->next;
if (block->next != (cleonos_app_heap_block *)0) {
block->next->prev = block;
}
}
static cleonos_app_heap_block *cleonos_app_heap_block_from_ptr(void *ptr) {
size_t header_size = cleonos_app_heap_align_up(sizeof(cleonos_app_heap_block), CLEONOS_APP_HEAP_ALIGN);
unsigned char *raw = (unsigned char *)ptr;
unsigned char *begin = cleonos_app_heap.bytes;
unsigned char *end = cleonos_app_heap.bytes + (size_t)CLEONOS_APP_HEAP_CAPACITY;
cleonos_app_heap_block *block;
if (ptr == (void *)0 || raw < begin + header_size || raw >= end) {
return (cleonos_app_heap_block *)0;
}
block = (cleonos_app_heap_block *)(void *)(raw - header_size);
if (block->magic != CLEONOS_APP_HEAP_MAGIC || block->used == 0U) {
return (cleonos_app_heap_block *)0;
}
return block;
}
void *malloc(size_t size) {
cleonos_app_heap_block *current;
size_t need = cleonos_app_heap_align_up(size, CLEONOS_APP_HEAP_ALIGN);
size_t header_size = cleonos_app_heap_align_up(sizeof(cleonos_app_heap_block), CLEONOS_APP_HEAP_ALIGN);
if (size == 0U) {
return (void *)0;
}
cleonos_app_heap_init();
if (cleonos_app_heap_ready == 0) {
return (void *)0;
}
current = cleonos_app_heap_head;
while (current != (cleonos_app_heap_block *)0) {
if (current->magic == CLEONOS_APP_HEAP_MAGIC && current->used == 0U && current->size >= need) {
cleonos_app_heap_split(current, need);
current->used = 1U;
return (void *)(((unsigned char *)(void *)current) + header_size);
}
current = current->next;
}
return (void *)0;
}
void free(void *ptr) {
cleonos_app_heap_block *block = cleonos_app_heap_block_from_ptr(ptr);
if (block == (cleonos_app_heap_block *)0) {
return;
}
block->used = 0U;
cleonos_app_heap_merge_next(block);
if (block->prev != (cleonos_app_heap_block *)0) {
cleonos_app_heap_merge_next(block->prev);
}
}
void *calloc(size_t count, size_t size) {
size_t total;
void *ptr;
if (count == 0U || size == 0U) {
return (void *)0;
}
if (count > ((size_t)-1) / size) {
return (void *)0;
}
total = count * size;
ptr = malloc(total);
if (ptr == (void *)0) {
return (void *)0;
}
(void)memset(ptr, 0, total);
return ptr;
}
void *realloc(void *ptr, size_t size) {
cleonos_app_heap_block *block;
void *out;
size_t old_size;
if (ptr == (void *)0) {
return malloc(size);
}
if (size == 0U) {
free(ptr);
return (void *)0;
}
block = cleonos_app_heap_block_from_ptr(ptr);
if (block == (cleonos_app_heap_block *)0) {
return (void *)0;
}
old_size = block->size;
size = cleonos_app_heap_align_up(size, CLEONOS_APP_HEAP_ALIGN);
if (old_size >= size) {
cleonos_app_heap_split(block, size);
return ptr;
}
if (block->next != (cleonos_app_heap_block *)0 && block->next->used == 0U) {
cleonos_app_heap_merge_next(block);
if (block->size >= size) {
cleonos_app_heap_split(block, size);
return ptr;
}
}
out = malloc(size);
if (out == (void *)0) {
return (void *)0;
}
if (old_size < size) {
(void)memcpy(out, ptr, old_size);
} else {
(void)memcpy(out, ptr, size);
}
free(ptr);
return out;
}

View File

@@ -0,0 +1,2 @@
#define CLEONOS_APP_HEAP_CAPACITY (3U * 1024U * 1024U)
#include "app_heap.inc"

View File

@@ -13,6 +13,10 @@
#include "../../include/cleonos_syscall.h"
#ifdef putc
#undef putc
#endif
#define DG_HEAP_SIZE (32U * 1024U * 1024U)
#define DG_MAX_MEM_FD 64
#define DG_PATH_MAX 192
@@ -55,6 +59,8 @@ static struct dg_stream g_dg_stdout_stream = {DG_STDIO_MAGIC, 1, 0, 0};
static struct dg_stream g_dg_stderr_stream = {DG_STDIO_MAGIC, 2, 0, 0};
static int g_dg_errno = 0;
static unsigned short g_dg_ctype_table[384];
static int32_t g_dg_toupper_table[384];
static int32_t g_dg_tolower_table[384];
static int g_dg_ctype_ready = 0;
FILE *stdin = (FILE *)(void *)&g_dg_stdin_stream;
@@ -103,6 +109,13 @@ static void dg_init_ctype_table(void) {
for (c = -128; c < 256; c++) {
unsigned short flags = 0U;
int ch = (c < 0) ? (c + 256) : c;
int upper = dg_is_lower(ch) ? (ch - 'a' + 'A') : ch;
int lower = dg_is_upper(ch) ? (ch - 'A' + 'a') : ch;
if (c == -1) {
upper = -1;
lower = -1;
}
if (dg_is_upper(ch) != 0) {
flags |= _ISupper;
@@ -142,6 +155,8 @@ static void dg_init_ctype_table(void) {
}
g_dg_ctype_table[c + 128] = flags;
g_dg_toupper_table[c + 128] = (int32_t)upper;
g_dg_tolower_table[c + 128] = (int32_t)lower;
}
g_dg_ctype_ready = 1;
@@ -153,6 +168,18 @@ const unsigned short int **__ctype_b_loc(void) {
return &table_ptr;
}
const int32_t **__ctype_toupper_loc(void) {
static const int32_t *table_ptr = (const int32_t *)(void *)(g_dg_toupper_table + 128);
dg_init_ctype_table();
return &table_ptr;
}
const int32_t **__ctype_tolower_loc(void) {
static const int32_t *table_ptr = (const int32_t *)(void *)(g_dg_tolower_table + 128);
dg_init_ctype_table();
return &table_ptr;
}
int system(const char *command) {
(void)command;
errno = ENOSYS;
@@ -1180,6 +1207,11 @@ size_t dg_fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) {
return (size_t)wrote / size;
}
int putc(int ch, FILE *stream) {
unsigned char out = (unsigned char)(ch & 0xFF);
return (dg_fwrite(&out, 1U, 1U, stream) == 1U) ? (int)out : EOF;
}
int dg_fseek(FILE *stream, long offset, int whence) {
struct dg_stream *s = dg_stream_ptr(stream);

View File

@@ -0,0 +1,2 @@
#define CLEONOS_APP_HEAP_CAPACITY (3U * 1024U * 1024U)
#include "app_heap.inc"

View File

@@ -16,7 +16,7 @@ static int ush_cmd_help(void) {
ush_writeln(" bmpview <file.bmp> [cols]");
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
ush_writeln(" vim [file] (vim-like editor: normal/insert/:w/:q/:wq)");
ush_writeln(" uwm (user-space window manager)");
ush_writeln(" uwm (user-space window manager; Start includes Task Manager)");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]");
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");

View File

@@ -138,7 +138,7 @@ static int ush_cmd_help(void) {
ush_writeln(" bmpview <file.bmp> [cols]");
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
ush_writeln(" vim [file] (vim-like editor)");
ush_writeln(" uwm (user-space window manager)");
ush_writeln(" uwm (user-space window manager; Start includes Task Manager)");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]");
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
#ifndef CLEONOS_TERMINAL_H
#define CLEONOS_TERMINAL_H
#include "../cmd_runtime.h"
int cleonos_terminal_run(void);
#endif

View File

@@ -0,0 +1,2 @@
#define CLEONOS_APP_HEAP_CAPACITY (4U * 1024U * 1024U)
#include "../app_heap.inc"

View File

@@ -0,0 +1,9 @@
#include "terminal/terminal.h"
int cleonos_app_main(int argc, char **argv, char **envp) {
(void)argc;
(void)argv;
(void)envp;
return (cleonos_terminal_run() != 0) ? 0 : 1;
}

View File

@@ -4,6 +4,8 @@
#include "../cmd_runtime.h"
#define USH_UWM_APP_COUNT 3U
#define USH_UWM_TERMINAL_INDEX 1
#define USH_UWM_TASKMGR_INDEX 2
#define USH_UWM_TASKBAR_INDEX 3
#define USH_UWM_START_INDEX 4
#define USH_UWM_WINDOW_COUNT 5U
@@ -57,6 +59,11 @@ typedef struct ush_uwm_window {
int minimized;
int closed;
int topmost;
int maximized;
int restore_x;
int restore_y;
int restore_w;
int restore_h;
int dirty;
ush_uwm_window_kind kind;
ush_uwm_u32 accent;
@@ -110,6 +117,7 @@ void ush_uwm_minimize_window(ush_uwm_session *sess, int index);
void ush_uwm_close_window(ush_uwm_session *sess, int index);
void ush_uwm_restore_window(ush_uwm_session *sess, int index);
void ush_uwm_toggle_topmost(ush_uwm_session *sess, int index);
void ush_uwm_toggle_maximize(ush_uwm_session *sess, int index);
void ush_uwm_toggle_start(ush_uwm_session *sess);
void ush_uwm_close_start(ush_uwm_session *sess);
void ush_uwm_refresh_taskbar(ush_uwm_session *sess);

View File

@@ -82,6 +82,11 @@ static void ush_uwm_init_window(ush_uwm_window *win, ush_uwm_window_kind kind, c
win->minimized = 0;
win->closed = closed;
win->topmost = topmost;
win->maximized = 0;
win->restore_x = x;
win->restore_y = y;
win->restore_w = w;
win->restore_h = h;
win->dirty = 1;
win->kind = kind;
win->accent = accent;
@@ -128,10 +133,10 @@ int ush_uwm_prepare_session(ush_uwm_session *sess) {
int start_h;
int app_gap;
int i;
const char *titles[USH_UWM_APP_COUNT] = {"FILE EXPLORER", "NOTEPAD", "EDGE"};
const char *subtitles[USH_UWM_APP_COUNT] = {"LOCAL DISK AND SYSTEM FILES", "EDIT TEXT INSIDE CLEONOS",
"WEB PREVIEW AND HTTP TOOLS"};
const ush_uwm_u32 accents[USH_UWM_APP_COUNT] = {0x000078D7U, 0x0000A300U, 0x00007ACCU};
const char *titles[USH_UWM_APP_COUNT] = {"FILE EXPLORER", "TERMINAL", "TASK MANAGER"};
const char *subtitles[USH_UWM_APP_COUNT] = {"LOCAL DISK AND SYSTEM FILES", "DESKTOP TERMINAL APP",
"PROCESS MONITOR AND END TASK"};
const ush_uwm_u32 accents[USH_UWM_APP_COUNT] = {0x000078D7U, 0x0000A300U, 0x000078D7U};
if (sess == (ush_uwm_session *)0) {
return 0;

View File

@@ -1,6 +1,8 @@
#include "uwm.h"
#define USH_UWM_FILE_EXPLORER_PATH "/shell/uwm/file_explorer.elf"
#define USH_UWM_TASKMGR_PATH "/shell/uwm/taskmgr.elf"
#define USH_UWM_TERMINAL_PATH "/shell/uwm/terminal.elf"
static int ush_uwm_launch_file_explorer(void) {
u64 pid = cleonos_sys_spawn_pathv(USH_UWM_FILE_EXPLORER_PATH, "", "LAUNCHED_BY=uwm");
@@ -8,6 +10,18 @@ static int ush_uwm_launch_file_explorer(void) {
return (pid != 0ULL && pid != (u64)-1) ? 1 : 0;
}
static int ush_uwm_launch_terminal(void) {
u64 pid = cleonos_sys_spawn_pathv(USH_UWM_TERMINAL_PATH, "", "LAUNCHED_BY=uwm");
return (pid != 0ULL && pid != (u64)-1) ? 1 : 0;
}
static int ush_uwm_launch_taskmgr(void) {
u64 pid = cleonos_sys_spawn_pathv(USH_UWM_TASKMGR_PATH, "", "LAUNCHED_BY=uwm");
return (pid != 0ULL && pid != (u64)-1) ? 1 : 0;
}
static void ush_uwm_launch_or_restore_app(ush_uwm_session *sess, int index) {
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
return;
@@ -18,6 +32,16 @@ static void ush_uwm_launch_or_restore_app(ush_uwm_session *sess, int index) {
return;
}
if (index == USH_UWM_TERMINAL_INDEX) {
(void)ush_uwm_launch_terminal();
return;
}
if (index == USH_UWM_TASKMGR_INDEX) {
(void)ush_uwm_launch_taskmgr();
return;
}
ush_uwm_restore_window(sess, index);
}
@@ -46,6 +70,72 @@ static int ush_uwm_hit_resize(const ush_uwm_window *win, int x, int y) {
: 0;
}
static int ush_uwm_point_in_window(const ush_uwm_window *win, int x, int y) {
if (win == (const ush_uwm_window *)0 || win->alive == 0 || win->closed != 0 || win->id == 0ULL) {
return 0;
}
return (x >= win->x && y >= win->y && x < win->x + win->w && y < win->y + win->h) ? 1 : 0;
}
static int ush_uwm_hit_session_window_at(const ush_uwm_session *sess, int global_x, int global_y) {
int i;
if (sess == (const ush_uwm_session *)0) {
return -1;
}
if (ush_uwm_point_in_window(&sess->windows[USH_UWM_START_INDEX], global_x, global_y) != 0) {
return USH_UWM_START_INDEX;
}
for (i = (int)USH_UWM_APP_COUNT - 1; i >= 0; i--) {
if (sess->windows[i].topmost != 0 && ush_uwm_point_in_window(&sess->windows[i], global_x, global_y) != 0) {
return i;
}
}
if (ush_uwm_app_index_valid(sess->active_window) != 0 &&
ush_uwm_point_in_window(&sess->windows[sess->active_window], global_x, global_y) != 0) {
return sess->active_window;
}
for (i = (int)USH_UWM_APP_COUNT - 1; i >= 0; i--) {
if (ush_uwm_point_in_window(&sess->windows[i], global_x, global_y) != 0) {
return i;
}
}
if (ush_uwm_point_in_window(&sess->windows[USH_UWM_TASKBAR_INDEX], global_x, global_y) != 0) {
return USH_UWM_TASKBAR_INDEX;
}
return -1;
}
static void ush_uwm_repair_mouse_target(ush_uwm_session *sess, int *window_index, int *local_x, int *local_y) {
cleonos_mouse_state mouse;
int hit;
if (sess == (ush_uwm_session *)0 || window_index == (int *)0 || local_x == (int *)0 || local_y == (int *)0) {
return;
}
ush_zero(&mouse, (u64)sizeof(mouse));
if (cleonos_sys_mouse_state(&mouse) == 0ULL || mouse.ready == 0ULL) {
return;
}
hit = ush_uwm_hit_session_window_at(sess, ush_uwm_u64_as_i32(mouse.x), ush_uwm_u64_as_i32(mouse.y));
if (ush_uwm_window_index_valid(hit) == 0) {
return;
}
*window_index = hit;
*local_x = ush_uwm_u64_as_i32(mouse.x) - sess->windows[hit].x;
*local_y = ush_uwm_u64_as_i32(mouse.y) - sess->windows[hit].y;
}
static int ush_uwm_taskbar_app_x(const ush_uwm_window *taskbar) {
int search_w = USH_UWM_TASKBAR_SEARCH_W;
@@ -87,13 +177,14 @@ static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *runnin
return;
}
if (key == (u64)'q' || key == (u64)'Q') {
*running = 0;
if (key == (u64)' ') {
ush_uwm_focus_next(sess);
return;
}
if (key == (u64)' ') {
ush_uwm_focus_next(sess);
idx = sess->active_window;
if (key == (u64)'q' || key == (u64)'Q') {
*running = 0;
return;
}
@@ -102,7 +193,6 @@ static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *runnin
return;
}
idx = sess->active_window;
if (ush_uwm_app_index_valid(idx) == 0 || sess->windows[idx].alive == 0) {
return;
}
@@ -122,6 +212,10 @@ static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *runnin
return;
}
if (sess->windows[idx].maximized != 0) {
return;
}
if (key == (u64)'+' || key == (u64)'=') {
(void)ush_uwm_window_resize(sess, idx, sess->windows[idx].w + 32, sess->windows[idx].h + 24);
return;
@@ -228,6 +322,14 @@ static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index,
left_changed = ((changed & 0x1ULL) != 0ULL) ? 1 : 0;
left_down = ((buttons & 0x1ULL) != 0ULL) ? 1 : 0;
if (left_changed != 0 && left_down != 0) {
ush_uwm_repair_mouse_target(sess, &window_index, &local_x, &local_y);
if (ush_uwm_window_index_valid(window_index) == 0) {
return;
}
win = &sess->windows[window_index];
}
if (left_changed == 0) {
return;
}
@@ -274,11 +376,15 @@ static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index,
}
if (ush_uwm_hit_topmost(win, local_x, local_y) != 0) {
if (window_index == USH_UWM_TERMINAL_INDEX) {
ush_uwm_toggle_maximize(sess, window_index);
} else {
ush_uwm_toggle_topmost(sess, window_index);
}
return;
}
if (ush_uwm_hit_resize(win, local_x, local_y) != 0) {
if (win->maximized == 0 && ush_uwm_hit_resize(win, local_x, local_y) != 0) {
sess->resizing = 1;
sess->resize_window = window_index;
sess->mouse_packet_seen = 0ULL;
@@ -291,7 +397,7 @@ static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index,
return;
}
if (local_y >= 0 && local_y < USH_UWM_TITLE_H) {
if (win->maximized == 0 && local_y >= 0 && local_y < USH_UWM_TITLE_H) {
sess->dragging = 1;
sess->drag_window = window_index;
sess->mouse_packet_seen = 0ULL;
@@ -312,13 +418,15 @@ static void ush_uwm_handle_mouse_move(ush_uwm_session *sess, int window_index, c
global_x = ush_uwm_u64_as_i32(event->arg0);
global_y = ush_uwm_u64_as_i32(event->arg1);
if (sess->resizing != 0 && sess->resize_window == window_index && ush_uwm_app_index_valid(window_index) != 0) {
if (sess->resizing != 0 && sess->resize_window == window_index && ush_uwm_app_index_valid(window_index) != 0 &&
sess->windows[window_index].maximized == 0) {
sess->resize_pending_w = sess->resize_start_w + (global_x - sess->resize_start_x);
sess->resize_pending_h = sess->resize_start_h + (global_y - sess->resize_start_y);
return;
}
if (sess->dragging != 0 && sess->drag_window == window_index && ush_uwm_app_index_valid(window_index) != 0) {
if (sess->dragging != 0 && sess->drag_window == window_index && ush_uwm_app_index_valid(window_index) != 0 &&
sess->windows[window_index].maximized == 0) {
(void)ush_uwm_window_move_clamped(sess, window_index, global_x - sess->drag_offset_x,
global_y - sess->drag_offset_y);
}
@@ -357,13 +465,15 @@ static int ush_uwm_drive_direct_pointer(ush_uwm_session *sess) {
global_x = ush_uwm_u64_as_i32(mouse.x);
global_y = ush_uwm_u64_as_i32(mouse.y);
if (sess->resizing != 0 && ush_uwm_app_index_valid(sess->resize_window) != 0) {
if (sess->resizing != 0 && ush_uwm_app_index_valid(sess->resize_window) != 0 &&
sess->windows[sess->resize_window].maximized == 0) {
sess->resize_pending_w = sess->resize_start_w + (global_x - sess->resize_start_x);
sess->resize_pending_h = sess->resize_start_h + (global_y - sess->resize_start_y);
return 1;
}
if (sess->dragging != 0 && ush_uwm_app_index_valid(sess->drag_window) != 0) {
if (sess->dragging != 0 && ush_uwm_app_index_valid(sess->drag_window) != 0 &&
sess->windows[sess->drag_window].maximized == 0) {
(void)ush_uwm_window_move_clamped(sess, sess->drag_window, global_x - sess->drag_offset_x,
global_y - sess->drag_offset_y);
return 1;

View File

@@ -0,0 +1,2 @@
#define CLEONOS_APP_HEAP_CAPACITY (3U * 1024U * 1024U)
#include "../app_heap.inc"

View File

@@ -13,6 +13,10 @@
#define UWM_COLOR_MUTED 0x00666666U
#define UWM_COLOR_BORDER 0x00D0D0D0U
static int ush_uwm_window_pointer_valid(const ush_uwm_window *win) {
return ((u64)(usize)win >= 4096ULL) ? 1 : 0;
}
static int ush_uwm_work_bottom(const ush_uwm_session *sess) {
int bottom;
@@ -67,8 +71,8 @@ static void ush_uwm_fill_rect(ush_uwm_window *win, int x, int y, int w, int h, u
int bottom;
int row;
if (win == (ush_uwm_window *)0 || win->pixels == (ush_uwm_u32 *)0 || win->w <= 0 || win->h <= 0 || w <= 0 ||
h <= 0) {
if (ush_uwm_window_pointer_valid(win) == 0 || win->pixels == (ush_uwm_u32 *)0 || win->w <= 0 || win->h <= 0 ||
w <= 0 || h <= 0) {
return;
}
@@ -208,6 +212,46 @@ static u64 ush_uwm_glyph_mask(char ch) {
return UWM_GLYPH7(14U, 17U, 17U, 15U, 1U, 1U, 14U);
case '-':
return UWM_GLYPH7(0U, 0U, 0U, 31U, 0U, 0U, 0U);
case '>':
return UWM_GLYPH7(16U, 8U, 4U, 2U, 4U, 8U, 16U);
case '<':
return UWM_GLYPH7(1U, 2U, 4U, 8U, 4U, 2U, 1U);
case '$':
return UWM_GLYPH7(4U, 15U, 20U, 14U, 5U, 30U, 4U);
case '#':
return UWM_GLYPH7(10U, 31U, 10U, 10U, 31U, 10U, 10U);
case '?':
return UWM_GLYPH7(14U, 17U, 1U, 2U, 4U, 0U, 4U);
case '!':
return UWM_GLYPH7(4U, 4U, 4U, 4U, 4U, 0U, 4U);
case ',':
return UWM_GLYPH7(0U, 0U, 0U, 0U, 0U, 4U, 8U);
case ';':
return UWM_GLYPH7(0U, 4U, 4U, 0U, 0U, 4U, 8U);
case '*':
return UWM_GLYPH7(0U, 21U, 14U, 31U, 14U, 21U, 0U);
case '(':
return UWM_GLYPH7(2U, 4U, 8U, 8U, 8U, 4U, 2U);
case ')':
return UWM_GLYPH7(8U, 4U, 2U, 2U, 2U, 4U, 8U);
case '[':
return UWM_GLYPH7(14U, 8U, 8U, 8U, 8U, 8U, 14U);
case ']':
return UWM_GLYPH7(14U, 2U, 2U, 2U, 2U, 2U, 14U);
case '@':
return UWM_GLYPH7(14U, 17U, 23U, 21U, 23U, 16U, 15U);
case '%':
return UWM_GLYPH7(24U, 25U, 2U, 4U, 8U, 19U, 3U);
case '&':
return UWM_GLYPH7(12U, 18U, 20U, 8U, 21U, 18U, 13U);
case '~':
return UWM_GLYPH7(0U, 0U, 8U, 21U, 2U, 0U, 0U);
case '\\':
return UWM_GLYPH7(16U, 16U, 8U, 4U, 2U, 1U, 1U);
case '"':
return UWM_GLYPH7(10U, 10U, 10U, 0U, 0U, 0U, 0U);
case '\'':
return UWM_GLYPH7(4U, 4U, 8U, 0U, 0U, 0U, 0U);
case '_':
return UWM_GLYPH7(0U, 0U, 0U, 0U, 0U, 0U, 31U);
case '.':
@@ -296,6 +340,14 @@ static void ush_uwm_draw_control_button(ush_uwm_window *win, int x, int active,
ush_uwm_fill_rect(win, cx - 4, cy - 6, 8, 2, fg);
ush_uwm_fill_rect(win, cx - 1, cy - 4, 2, 9, fg);
ush_uwm_fill_rect(win, cx - 6, cy + 4, 12, 2, fg);
} else if (kind == 3) {
ush_uwm_stroke_rect(win, cx - 6, cy - 6, 12, 12, fg);
ush_uwm_fill_rect(win, cx - 6, cy - 6, 12, 2, fg);
} else if (kind == 4) {
ush_uwm_stroke_rect(win, cx - 4, cy - 7, 10, 10, fg);
ush_uwm_fill_rect(win, cx - 4, cy - 7, 10, 2, fg);
ush_uwm_stroke_rect(win, cx - 7, cy - 3, 10, 10, fg);
ush_uwm_fill_rect(win, cx - 7, cy - 3, 10, 2, fg);
} else {
int i;
for (i = 0; i < 11; i++) {
@@ -305,7 +357,7 @@ static void ush_uwm_draw_control_button(ush_uwm_window *win, int x, int active,
}
}
static void ush_uwm_draw_window_controls(ush_uwm_window *win, int active) {
static void ush_uwm_draw_window_controls(ush_uwm_window *win, int active, int index) {
int close_x;
int pin_x;
int min_x;
@@ -317,7 +369,11 @@ static void ush_uwm_draw_window_controls(ush_uwm_window *win, int active) {
close_x = win->w - USH_UWM_CONTROL_W;
min_x = close_x - USH_UWM_CONTROL_W;
pin_x = min_x - USH_UWM_CONTROL_W;
if (index == USH_UWM_TERMINAL_INDEX) {
ush_uwm_draw_control_button(win, pin_x, active, (win->maximized != 0) ? 4 : 3);
} else {
ush_uwm_draw_control_button(win, pin_x, active, 1);
}
ush_uwm_draw_control_button(win, min_x, active, 0);
ush_uwm_draw_control_button(win, close_x, active, 2);
}
@@ -358,50 +414,40 @@ static void ush_uwm_render_files(ush_uwm_window *win) {
ush_uwm_draw_text(win, 118, USH_UWM_TITLE_H + 166, "TEMP", 1, UWM_COLOR_TEXT);
}
static void ush_uwm_render_editor(ush_uwm_window *win) {
int y;
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H, win->w, 24, 0x00F9F9F9U);
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H + 23, win->w, 1, UWM_COLOR_BORDER);
ush_uwm_draw_text(win, 12, USH_UWM_TITLE_H + 8, "FILE EDIT VIEW HELP", 1, UWM_COLOR_TEXT);
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H + 24, 46, win->h - USH_UWM_TITLE_H - 24, 0x00F0F0F0U);
ush_uwm_fill_rect(win, 46, USH_UWM_TITLE_H + 24, 1, win->h - USH_UWM_TITLE_H - 24, 0x00DDDDDDU);
for (y = 0; y < 7; y++) {
char label[4];
label[0] = (char)('1' + y);
label[1] = 0;
ush_uwm_draw_text(win, 18, USH_UWM_TITLE_H + 42 + (y * 18), label, 1, UWM_COLOR_MUTED);
static void ush_uwm_render_terminal_launcher(ush_uwm_window *win) {
if (win == (ush_uwm_window *)0) {
return;
}
ush_uwm_draw_text(win, 62, USH_UWM_TITLE_H + 42, "CLEONOS UWM REWRITE", 1, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 62, USH_UWM_TITLE_H + 60, "PIXEL RENDERER ONLINE", 1, 0x00008000U);
ush_uwm_draw_text(win, 62, USH_UWM_TITLE_H + 78, "WINDOWS 10 STYLE SHELL", 1, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 62, USH_UWM_TITLE_H + 96, "DRAG RESIZE MINIMIZE CLOSE", 1, UWM_COLOR_TEXT);
ush_uwm_fill_rect(win, 62, USH_UWM_TITLE_H + 120, 92, 2, UWM_COLOR_WIN_BLUE);
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H, win->w, win->h - USH_UWM_TITLE_H, 0x000C0C0CU);
ush_uwm_fill_rect(win, 18, USH_UWM_TITLE_H + 22, win->w - 36, win->h - USH_UWM_TITLE_H - 44, 0x00111111U);
ush_uwm_stroke_rect(win, 18, USH_UWM_TITLE_H + 22, win->w - 36, win->h - USH_UWM_TITLE_H - 44, 0x00333333U);
ush_uwm_draw_text(win, 34, USH_UWM_TITLE_H + 46, "TERMINAL IS A SEPARATE ELF NOW", 1, 0x0086D98AU);
ush_uwm_draw_text(win, 34, USH_UWM_TITLE_H + 72, "/SHELL/UWM/TERMINAL.ELF", 1, 0x00DCDCDCU);
ush_uwm_draw_text(win, 34, USH_UWM_TITLE_H + 98, "OPEN IT FROM START OR TASKBAR", 1, 0x00808080U);
}
static void ush_uwm_render_browser(ush_uwm_window *win) {
static void ush_uwm_render_taskmgr_launcher(ush_uwm_window *win) {
int card_w;
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H, win->w, 42, 0x00F7F7F7U);
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H + 41, win->w, 1, UWM_COLOR_BORDER);
ush_uwm_fill_rect(win, 14, USH_UWM_TITLE_H + 10, win->w - 28, 22, UWM_COLOR_WHITE);
ush_uwm_stroke_rect(win, 14, USH_UWM_TITLE_H + 10, win->w - 28, 22, UWM_COLOR_BORDER);
ush_uwm_draw_text_limit(win, 24, USH_UWM_TITLE_H + 17, "HTTP://EXAMPLE.COM", 1, UWM_COLOR_MUTED, win->w - 24);
ush_uwm_draw_text_limit(win, 24, USH_UWM_TITLE_H + 17, "/SHELL/UWM/TASKMGR.ELF", 1, UWM_COLOR_MUTED, win->w - 24);
ush_uwm_draw_text(win, 22, USH_UWM_TITLE_H + 66, "WELCOME TO CLEONOS", 2, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 24, USH_UWM_TITLE_H + 94, "NETWORK AND HTML DEMOS LIVE HERE", 1, UWM_COLOR_MUTED);
ush_uwm_draw_text(win, 22, USH_UWM_TITLE_H + 66, "TASK MANAGER", 2, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 24, USH_UWM_TITLE_H + 94, "PROCESS LIST AND END TASK LIVE HERE", 1, UWM_COLOR_MUTED);
card_w = (win->w - 58) / 2;
if (card_w < 80) {
card_w = 80;
}
ush_uwm_fill_rect(win, 22, USH_UWM_TITLE_H + 122, card_w, 54, 0x00EAF4FFU);
ush_uwm_stroke_rect(win, 22, USH_UWM_TITLE_H + 122, card_w, 54, 0x00B7D8F4U);
ush_uwm_draw_text(win, 34, USH_UWM_TITLE_H + 142, "HTTPGET", 1, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 34, USH_UWM_TITLE_H + 142, "PROCESSES", 1, UWM_COLOR_TEXT);
ush_uwm_fill_rect(win, 36 + card_w, USH_UWM_TITLE_H + 122, card_w, 54, 0x00EAF7EAU);
ush_uwm_stroke_rect(win, 36 + card_w, USH_UWM_TITLE_H + 122, card_w, 54, 0x00B7E0B7U);
ush_uwm_draw_text(win, 48 + card_w, USH_UWM_TITLE_H + 142, "NSLOOKUP", 1, UWM_COLOR_TEXT);
ush_uwm_draw_text(win, 48 + card_w, USH_UWM_TITLE_H + 142, "END TASK", 1, UWM_COLOR_TEXT);
}
static void ush_uwm_render_app_window(ush_uwm_session *sess, int index) {
@@ -423,23 +469,25 @@ static void ush_uwm_render_app_window(ush_uwm_session *sess, int index) {
ush_uwm_fill_rect(win, 0, 0, win->w, USH_UWM_TITLE_H, title_bg);
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H, win->w, 1, UWM_COLOR_BORDER);
ush_uwm_draw_text_limit(win, 12, 12, win->title, 1, title_fg, win->w - (USH_UWM_CONTROL_W * 3) - 8);
if (win->topmost != 0) {
if (win->topmost != 0 && index != USH_UWM_TERMINAL_INDEX) {
ush_uwm_draw_text(win, win->w - (USH_UWM_CONTROL_W * 3) - 18, 12, "^", 1, title_fg);
}
ush_uwm_draw_window_controls(win, active);
ush_uwm_draw_window_controls(win, active, index);
if (index == 0) {
ush_uwm_render_files(win);
} else if (index == 1) {
ush_uwm_render_editor(win);
ush_uwm_render_terminal_launcher(win);
} else {
ush_uwm_render_browser(win);
ush_uwm_render_taskmgr_launcher(win);
}
if (win->maximized == 0) {
ush_uwm_fill_rect(win, win->w - 14, win->h - 3, 11, 1, UWM_COLOR_MUTED);
ush_uwm_fill_rect(win, win->w - 10, win->h - 7, 7, 1, UWM_COLOR_MUTED);
ush_uwm_fill_rect(win, win->w - 6, win->h - 11, 3, 1, UWM_COLOR_MUTED);
}
}
static void ush_uwm_render_taskbar(ush_uwm_session *sess) {
ush_uwm_window *taskbar;
@@ -507,7 +555,7 @@ static void ush_uwm_render_taskbar(ush_uwm_session *sess) {
static void ush_uwm_render_start(ush_uwm_session *sess) {
ush_uwm_window *start;
int i;
const char *labels[USH_UWM_APP_COUNT] = {"FILE EXPLORER", "NOTEPAD", "EDGE"};
const char *labels[USH_UWM_APP_COUNT] = {"FILE EXPLORER", "TERMINAL", "TASK MANAGER"};
if (sess == (ush_uwm_session *)0) {
return;
@@ -675,6 +723,7 @@ void ush_uwm_destroy_window(ush_uwm_window *win) {
win->pixel_count = 0ULL;
win->minimized = 0;
win->closed = 1;
win->maximized = 0;
win->dirty = 1;
}
@@ -791,6 +840,135 @@ int ush_uwm_window_resize(ush_uwm_session *sess, int index, int target_w, int ta
return 1;
}
static int ush_uwm_window_recreate_geometry(ush_uwm_session *sess, int index, int target_x, int target_y, int target_w,
int target_h) {
ush_uwm_window *win;
int max_x;
int max_y;
int new_x;
int new_y;
int new_w;
int new_h;
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
return 0;
}
win = &sess->windows[index];
if (win->closed != 0 || win->minimized != 0) {
return 0;
}
new_w = ush_uwm_clampi(target_w, USH_UWM_MIN_WINDOW_W, sess->screen_w);
new_h = ush_uwm_clampi(target_h, USH_UWM_MIN_WINDOW_H, ush_uwm_work_bottom(sess) - USH_UWM_TOP_CLAMP_Y);
max_x = sess->screen_w - new_w;
max_y = ush_uwm_work_bottom(sess) - new_h;
if (max_x < 0) {
max_x = 0;
}
if (max_y < USH_UWM_TOP_CLAMP_Y) {
max_y = USH_UWM_TOP_CLAMP_Y;
}
new_x = ush_uwm_clampi(target_x, 0, max_x);
new_y = ush_uwm_clampi(target_y, USH_UWM_TOP_CLAMP_Y, max_y);
if (ush_uwm_replace_pixels(win, new_w, new_h) == 0) {
return 0;
}
if (win->id != 0ULL || win->alive != 0) {
ush_uwm_destroy_kernel_window(win);
}
win->x = new_x;
win->y = new_y;
win->closed = 0;
win->minimized = 0;
ush_uwm_render_window(sess, index);
if (ush_uwm_create_window(win) == 0) {
win->closed = 1;
return 0;
}
if (ush_uwm_present_window(win) == 0) {
ush_uwm_destroy_kernel_window(win);
win->closed = 1;
return 0;
}
sess->active_window = index;
(void)cleonos_sys_wm_set_focus(win->id);
ush_uwm_refresh_taskbar(sess);
return 1;
}
void ush_uwm_toggle_maximize(ush_uwm_session *sess, int index) {
ush_uwm_window *win;
int target_w;
int target_h;
int restore_x;
int restore_y;
int restore_w;
int restore_h;
if (sess == (ush_uwm_session *)0 || index != USH_UWM_TERMINAL_INDEX || ush_uwm_app_index_valid(index) == 0) {
return;
}
win = &sess->windows[index];
if (win->alive == 0 || win->id == 0ULL || win->closed != 0 || win->minimized != 0) {
return;
}
target_w = sess->screen_w;
target_h = ush_uwm_work_bottom(sess) - USH_UWM_TOP_CLAMP_Y;
if (target_w < USH_UWM_MIN_WINDOW_W) {
target_w = USH_UWM_MIN_WINDOW_W;
}
if (target_h < USH_UWM_MIN_WINDOW_H) {
target_h = USH_UWM_MIN_WINDOW_H;
}
if (win->maximized == 0) {
win->restore_x = win->x;
win->restore_y = win->y;
win->restore_w = win->w;
win->restore_h = win->h;
win->maximized = 1;
if (ush_uwm_window_recreate_geometry(sess, index, 0, USH_UWM_TOP_CLAMP_Y, target_w, target_h) == 0) {
win->maximized = 0;
ush_uwm_refresh_window(sess, index);
return;
}
return;
}
restore_x = win->restore_x;
restore_y = win->restore_y;
restore_w = win->restore_w;
restore_h = win->restore_h;
if (restore_w < USH_UWM_MIN_WINDOW_W) {
restore_w = USH_UWM_MIN_WINDOW_W;
}
if (restore_h < USH_UWM_MIN_WINDOW_H) {
restore_h = USH_UWM_MIN_WINDOW_H;
}
if (restore_w > sess->screen_w) {
restore_w = sess->screen_w;
}
if (restore_h > target_h) {
restore_h = target_h;
}
win->maximized = 0;
if (ush_uwm_window_recreate_geometry(sess, index, restore_x, restore_y, restore_w, restore_h) == 0) {
win->maximized = 1;
ush_uwm_refresh_window(sess, index);
return;
}
}
void ush_uwm_set_active(ush_uwm_session *sess, int index) {
ush_uwm_window *win;
int old_active;
@@ -857,13 +1035,24 @@ void ush_uwm_minimize_window(ush_uwm_session *sess, int index) {
}
void ush_uwm_close_window(ush_uwm_session *sess, int index) {
ush_uwm_window *win;
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
return;
}
ush_uwm_destroy_kernel_window(&sess->windows[index]);
sess->windows[index].closed = 1;
sess->windows[index].minimized = 0;
win = &sess->windows[index];
ush_uwm_destroy_kernel_window(win);
if (win->maximized != 0) {
win->x = win->restore_x;
win->y = win->restore_y;
win->maximized = 0;
if (win->restore_w >= USH_UWM_MIN_WINDOW_W && win->restore_h >= USH_UWM_MIN_WINDOW_H) {
(void)ush_uwm_replace_pixels(win, win->restore_w, win->restore_h);
}
}
win->closed = 1;
win->minimized = 0;
if (sess->active_window == index) {
ush_uwm_focus_next(sess);
}

View File

@@ -263,6 +263,7 @@ typedef struct cleonos_net_tcp_recv_req {
#define CLEONOS_SYSCALL_WM_SET_FOCUS 113ULL
#define CLEONOS_SYSCALL_WM_SET_FLAGS 114ULL
#define CLEONOS_SYSCALL_WM_RESIZE 115ULL
#define CLEONOS_SYSCALL_PTY_OPEN 116ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -381,5 +382,6 @@ u64 cleonos_sys_wm_move(const cleonos_wm_move_req *req);
u64 cleonos_sys_wm_set_focus(u64 window_id);
u64 cleonos_sys_wm_set_flags(u64 window_id, u64 flags);
u64 cleonos_sys_wm_resize(const cleonos_wm_resize_req *req);
u64 cleonos_sys_pty_open(void);
#endif

View File

@@ -26,6 +26,7 @@ long strtol(const char *text, char **out_end, int base);
unsigned long strtoul(const char *text, char **out_end, int base);
long long strtoll(const char *text, char **out_end, int base);
unsigned long long strtoull(const char *text, char **out_end, int base);
double strtod(const char *text, char **out_end);
void *malloc(size_t size);
void free(void *ptr);

View File

@@ -72,6 +72,81 @@ long long atoll(const char *text) {
return strtoll(text, (char **)0, 10);
}
double strtod(const char *text, char **out_end) {
const char *p = clib_skip_space(text);
double value = 0.0;
double scale = 1.0;
int negative = 0;
int any = 0;
int exp_negative = 0;
int exp_value = 0;
if (out_end != (char **)0) {
*out_end = (char *)text;
}
if (p == (const char *)0) {
return 0.0;
}
if (*p == '+' || *p == '-') {
negative = (*p == '-') ? 1 : 0;
p++;
}
while (isdigit((unsigned char)*p) != 0) {
value = (value * 10.0) + (double)(*p - '0');
any = 1;
p++;
}
if (*p == '.') {
p++;
while (isdigit((unsigned char)*p) != 0) {
scale *= 0.1;
value += (double)(*p - '0') * scale;
any = 1;
p++;
}
}
if (any != 0 && (*p == 'e' || *p == 'E')) {
const char *exp_start = p;
p++;
if (*p == '+' || *p == '-') {
exp_negative = (*p == '-') ? 1 : 0;
p++;
}
if (isdigit((unsigned char)*p) == 0) {
p = exp_start;
} else {
while (isdigit((unsigned char)*p) != 0) {
if (exp_value < 308) {
exp_value = (exp_value * 10) + (*p - '0');
}
p++;
}
while (exp_value > 0) {
value = (exp_negative != 0) ? (value * 0.1) : (value * 10.0);
exp_value--;
}
}
}
if (any == 0) {
return 0.0;
}
if (out_end != (char **)0) {
*out_end = (char *)p;
}
return (negative != 0) ? -value : value;
}
unsigned long strtoul(const char *text, char **out_end, int base) {
const char *p = clib_skip_space(text);
int negative = 0;
@@ -241,7 +316,7 @@ unsigned long long strtoull(const char *text, char **out_end, int base) {
}
#ifndef CLIB_HEAP_CAPACITY
#define CLIB_HEAP_CAPACITY (2U * 1024U * 1024U)
#define CLIB_HEAP_CAPACITY (256U * 1024U)
#endif
#define CLIB_HEAP_ALIGN 8U

View File

@@ -495,3 +495,7 @@ u64 cleonos_sys_wm_set_flags(u64 window_id, u64 flags) {
u64 cleonos_sys_wm_resize(const cleonos_wm_resize_req *req) {
return cleonos_syscall(CLEONOS_SYSCALL_WM_RESIZE, (u64)req, 0ULL, 0ULL);
}
u64 cleonos_sys_pty_open(void) {
return cleonos_syscall(CLEONOS_SYSCALL_PTY_OPEN, 0ULL, 0ULL, 0ULL);
}

2
clks

Submodule clks updated: 1ad59e99ea...83377b472a

View File

@@ -894,6 +894,14 @@ UserSafeControllerUSC危险 syscall 确认:
- 说明:
- 调整窗口尺寸并保持 `window_id` 不变;调整后用户态应重新 `WM_PRESENT` 一次提交新尺寸内容。
### 116 `CLEONOS_SYSCALL_PTY_OPEN`
- 参数:无
- 返回:成功返回一个可读写 FD失败返回 `(u64)-1`
- 说明:
- 创建桌面伪 tty 输出端。用户态可把该 FD 传给 `EXEC_PATHV_IO` 的 stdout/stderr然后通过 `FD_READ` 从同一 FD 读取子进程输出。
- 当前 PTY 是“命令输出捕获型”最小实现,不提供完整主从终端会话语义;阻塞式交互 shell 仍应继续使用普通 TTY。
## 5. 用户态封装函数
用户态封装位于:
@@ -932,6 +940,7 @@ UserSafeControllerUSC危险 syscall 确认:
- `cleonos_sys_mouse_state()`
- `cleonos_sys_wm_create()` / `cleonos_sys_wm_destroy()` / `cleonos_sys_wm_present()`
- `cleonos_sys_wm_poll_event()` / `cleonos_sys_wm_move()` / `cleonos_sys_wm_set_focus()`
- `cleonos_sys_pty_open()`
## 6. 开发注意事项
@@ -942,7 +951,7 @@ UserSafeControllerUSC危险 syscall 确认:
## 7. Wine 兼容说明
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..115`(含 `DL_*``FB_*``KERNEL_VERSION``DISK_*``NET_*``MOUSE_STATE``WM_*`)。
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..116`(含 `DL_*``FB_*``KERNEL_VERSION``DISK_*``NET_*``MOUSE_STATE``WM_*``PTY_OPEN`)。
- `DL_*``77..79`)在 Wine 中为“可运行兼容”实现:
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
@@ -962,6 +971,7 @@ UserSafeControllerUSC危险 syscall 确认:
- 网络 syscall`95..106`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
- `MOUSE_STATE``107`)在 Wine 中为基础兼容实现:可返回指针数据结构;未启用窗口鼠标事件时 `ready` 可能为 `0`
- `WM_*``108..115`)在 Wine 当前为兼容占位实现(统一返回 `0`);不会创建真实窗口服务。
- `PTY_OPEN``116`)在 Wine 中创建内存缓冲 FD写入端通过 `FD_WRITE` 追加,读取端通过 `FD_READ` 消费,用于桌面 Terminal 捕获子进程输出。
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0``AUDIO_PLAY_TONE=0``AUDIO_STOP=1`
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。

2
kit

Submodule kit updated: 46c6d4a547...3f29819598

2
wine

Submodule wine updated: c31867a23a...fe46a157c2