mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-27 05:34:00 +00:00
桌面环境
This commit is contained in:
@@ -36,7 +36,7 @@ set(CLEONOS_QEMU_ACCEL_ARGS "")
|
|||||||
if(CLEONOS_QEMU_ENABLE_KVM)
|
if(CLEONOS_QEMU_ENABLE_KVM)
|
||||||
list(APPEND CLEONOS_QEMU_ACCEL_ARGS -enable-kvm -cpu host)
|
list(APPEND CLEONOS_QEMU_ACCEL_ARGS -enable-kvm -cpu host)
|
||||||
endif()
|
endif()
|
||||||
set(CLEONOS_QEMU_ENABLE_USB_TABLET ON CACHE BOOL "Enable QEMU USB tablet for absolute mouse pointer")
|
set(CLEONOS_QEMU_ENABLE_USB_TABLET OFF CACHE BOOL "Enable QEMU USB tablet for absolute mouse pointer (requires USB HID support)")
|
||||||
set(CLEONOS_QEMU_INPUT_ARGS "")
|
set(CLEONOS_QEMU_INPUT_ARGS "")
|
||||||
if(CLEONOS_QEMU_ENABLE_USB_TABLET)
|
if(CLEONOS_QEMU_ENABLE_USB_TABLET)
|
||||||
list(APPEND CLEONOS_QEMU_INPUT_ARGS -usb -device usb-tablet)
|
list(APPEND CLEONOS_QEMU_INPUT_ARGS -usb -device usb-tablet)
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -21,6 +21,7 @@ MENUCONFIG_PRESET ?=
|
|||||||
DISK_IMAGE_MB ?=
|
DISK_IMAGE_MB ?=
|
||||||
CLEONOS_ENABLE ?= auto
|
CLEONOS_ENABLE ?= auto
|
||||||
QEMU_DRIVE_IMAGE ?= build/x86_64/cleonos_disk.img
|
QEMU_DRIVE_IMAGE ?= build/x86_64/cleonos_disk.img
|
||||||
|
CLEONOS_QEMU_ENABLE_USB_TABLET ?= OFF
|
||||||
SHOW_COMMANDS ?= 0
|
SHOW_COMMANDS ?= 0
|
||||||
V ?= 0
|
V ?= 0
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ MENUCONFIG_SCOPE_ARG += --clks-only
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE)
|
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE)
|
||||||
|
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_QEMU_ENABLE_USB_TABLET=$(CLEONOS_QEMU_ENABLE_USB_TABLET)
|
||||||
|
|
||||||
ifneq ($(strip $(LIMINE_SKIP_CONFIGURE)),)
|
ifneq ($(strip $(LIMINE_SKIP_CONFIGURE)),)
|
||||||
CMAKE_PASSTHROUGH_ARGS += -DLIMINE_SKIP_CONFIGURE=$(LIMINE_SKIP_CONFIGURE)
|
CMAKE_PASSTHROUGH_ARGS += -DLIMINE_SKIP_CONFIGURE=$(LIMINE_SKIP_CONFIGURE)
|
||||||
@@ -240,8 +242,8 @@ help:
|
|||||||
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=ON' # force on"
|
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=ON' # force on"
|
||||||
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=OFF' # force off"
|
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=OFF' # force off"
|
||||||
> $(Q)echo "QEMU USB tablet toggle:"
|
> $(Q)echo "QEMU USB tablet toggle:"
|
||||||
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_USB_TABLET=ON' # absolute pointer"
|
> $(Q)echo " make run CLEONOS_QEMU_ENABLE_USB_TABLET=OFF # default: PS/2 mouse path"
|
||||||
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_USB_TABLET=OFF' # disable tablet"
|
> $(Q)echo " make run CLEONOS_QEMU_ENABLE_USB_TABLET=ON # USB tablet, requires USB HID support"
|
||||||
> $(Q)echo ""
|
> $(Q)echo ""
|
||||||
> $(Q)echo "Pass custom CMake cache args via:"
|
> $(Q)echo "Pass custom CMake cache args via:"
|
||||||
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"
|
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
file(GLOB_RECURSE USER_INC_SOURCES_ABS CONFIGURE_DEPENDS
|
file(GLOB_RECURSE USER_INC_SOURCES_ABS CONFIGURE_DEPENDS
|
||||||
"${CMAKE_SOURCE_DIR}/cleonos/**/*.inc"
|
"${CMAKE_SOURCE_DIR}/cleonos/**/*.inc"
|
||||||
|
"${CMAKE_SOURCE_DIR}/cleonos/c/include/*.h"
|
||||||
|
"${CMAKE_SOURCE_DIR}/cleonos/c/include/**/*.h"
|
||||||
|
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/*.h"
|
||||||
|
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/**/*.h"
|
||||||
)
|
)
|
||||||
list(SORT USER_INC_SOURCES_ABS)
|
list(SORT USER_INC_SOURCES_ABS)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "cmd_runtime.h"
|
#include "cmd_runtime.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "gumbo.h"
|
#include "gumbo.h"
|
||||||
@@ -8,15 +9,19 @@
|
|||||||
#define USH_BROWSER_SOURCE_MAX 256U
|
#define USH_BROWSER_SOURCE_MAX 256U
|
||||||
#define USH_BROWSER_HOST_MAX 128U
|
#define USH_BROWSER_HOST_MAX 128U
|
||||||
#define USH_BROWSER_PATH_MAX 256U
|
#define USH_BROWSER_PATH_MAX 256U
|
||||||
#define USH_BROWSER_HTML_MAX (512U * 1024U)
|
#define USH_BROWSER_HTML_MAX (256U * 1024U)
|
||||||
#define USH_BROWSER_TEXT_MAX (160U * 1024U)
|
#define USH_BROWSER_TEXT_MAX (96U * 1024U)
|
||||||
|
#define USH_BROWSER_GUMBO_PARSE_MAX (96U * 1024U)
|
||||||
|
#define USH_BROWSER_GUMBO_MAX_ERRORS 0
|
||||||
|
#define USH_BROWSER_HTML_BUF_CAP (USH_BROWSER_HTML_MAX + 1U)
|
||||||
|
#define USH_BROWSER_TEXT_BUF_CAP (USH_BROWSER_TEXT_MAX + 1U)
|
||||||
#define USH_BROWSER_TITLE_MAX 128U
|
#define USH_BROWSER_TITLE_MAX 128U
|
||||||
#define USH_BROWSER_DNS_PACKET_MAX 512U
|
#define USH_BROWSER_DNS_PACKET_MAX 512U
|
||||||
#define USH_BROWSER_HTTP_RECV_CHUNK 2048U
|
#define USH_BROWSER_HTTP_RECV_CHUNK 2048U
|
||||||
#define USH_BROWSER_TCP_POLL_BUDGET 200000000ULL
|
#define USH_BROWSER_TCP_POLL_BUDGET 200000000ULL
|
||||||
#define USH_BROWSER_TCP_RECV_IDLE_LOOPS 40ULL
|
#define USH_BROWSER_TCP_RECV_IDLE_LOOPS 40ULL
|
||||||
|
|
||||||
#define USH_BROWSER_LINK_MAX 128U
|
#define USH_BROWSER_LINK_MAX 96U
|
||||||
#define USH_BROWSER_LINK_TEXT_MAX 96U
|
#define USH_BROWSER_LINK_TEXT_MAX 96U
|
||||||
#define USH_BROWSER_LINK_HREF_MAX 192U
|
#define USH_BROWSER_LINK_HREF_MAX 192U
|
||||||
#define USH_BROWSER_HISTORY_MAX 16U
|
#define USH_BROWSER_HISTORY_MAX 16U
|
||||||
@@ -24,7 +29,7 @@
|
|||||||
#define USH_BROWSER_SEG_MAX 32U
|
#define USH_BROWSER_SEG_MAX 32U
|
||||||
#define USH_BROWSER_SEG_LEN_MAX 63U
|
#define USH_BROWSER_SEG_LEN_MAX 63U
|
||||||
#define USH_BROWSER_CSS_TEXT_MAX 4096U
|
#define USH_BROWSER_CSS_TEXT_MAX 4096U
|
||||||
#define USH_BROWSER_CSS_RULE_MAX 160U
|
#define USH_BROWSER_CSS_RULE_MAX 96U
|
||||||
#define USH_BROWSER_CSS_IDENT_MAX 48U
|
#define USH_BROWSER_CSS_IDENT_MAX 48U
|
||||||
#define USH_BROWSER_ANSI_RESET "\x1B[0m"
|
#define USH_BROWSER_ANSI_RESET "\x1B[0m"
|
||||||
#define USH_BROWSER_ANSI_BLUE "\x1B[34m"
|
#define USH_BROWSER_ANSI_BLUE "\x1B[34m"
|
||||||
@@ -76,9 +81,9 @@ typedef struct ush_browser_css_rule {
|
|||||||
ush_browser_style_delta delta;
|
ush_browser_style_delta delta;
|
||||||
} ush_browser_css_rule;
|
} ush_browser_css_rule;
|
||||||
|
|
||||||
static char ush_browser_html_buf[USH_BROWSER_HTML_MAX + 1U];
|
static char *ush_browser_html_buf;
|
||||||
static char ush_browser_http_raw_buf[USH_BROWSER_HTML_MAX + 1U];
|
static char *ush_browser_http_raw_buf;
|
||||||
static char ush_browser_text_buf[USH_BROWSER_TEXT_MAX + 1U];
|
static char *ush_browser_text_buf;
|
||||||
static char ush_browser_title[USH_BROWSER_TITLE_MAX];
|
static char ush_browser_title[USH_BROWSER_TITLE_MAX];
|
||||||
static ush_browser_link ush_browser_links[USH_BROWSER_LINK_MAX];
|
static ush_browser_link ush_browser_links[USH_BROWSER_LINK_MAX];
|
||||||
|
|
||||||
@@ -88,6 +93,26 @@ static u64 ush_browser_link_count = 0ULL;
|
|||||||
static ush_browser_css_rule ush_browser_css_rules[USH_BROWSER_CSS_RULE_MAX];
|
static ush_browser_css_rule ush_browser_css_rules[USH_BROWSER_CSS_RULE_MAX];
|
||||||
static u64 ush_browser_css_rule_count = 0ULL;
|
static u64 ush_browser_css_rule_count = 0ULL;
|
||||||
|
|
||||||
|
static int ush_browser_ensure_buffers(void) {
|
||||||
|
if (ush_browser_html_buf != (char *)0 && ush_browser_http_raw_buf != (char *)0 &&
|
||||||
|
ush_browser_text_buf != (char *)0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_browser_html_buf = (char *)malloc((size_t)USH_BROWSER_HTML_BUF_CAP);
|
||||||
|
ush_browser_http_raw_buf = (char *)malloc((size_t)USH_BROWSER_HTML_BUF_CAP);
|
||||||
|
ush_browser_text_buf = (char *)malloc((size_t)USH_BROWSER_TEXT_BUF_CAP);
|
||||||
|
if (ush_browser_html_buf == (char *)0 || ush_browser_http_raw_buf == (char *)0 ||
|
||||||
|
ush_browser_text_buf == (char *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_browser_html_buf[0] = '\0';
|
||||||
|
ush_browser_http_raw_buf[0] = '\0';
|
||||||
|
ush_browser_text_buf[0] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int ush_browser_is_http_url(const char *text) {
|
static int ush_browser_is_http_url(const char *text) {
|
||||||
if (text == (const char *)0) {
|
if (text == (const char *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -917,7 +942,7 @@ static int ush_browser_fetch_http(const char *url_text, char *out_html, u64 out_
|
|||||||
|
|
||||||
*out_size = 0ULL;
|
*out_size = 0ULL;
|
||||||
out_html[0] = '\0';
|
out_html[0] = '\0';
|
||||||
ush_zero(ush_browser_http_raw_buf, (u64)sizeof(ush_browser_http_raw_buf));
|
ush_zero(ush_browser_http_raw_buf, (u64)USH_BROWSER_HTML_BUF_CAP);
|
||||||
|
|
||||||
if (cleonos_sys_net_available() == 0ULL) {
|
if (cleonos_sys_net_available() == 0ULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -969,11 +994,11 @@ static int ush_browser_fetch_http(const char *url_text, char *out_html, u64 out_
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (raw_len + 1ULL < (u64)sizeof(ush_browser_http_raw_buf)) {
|
while (raw_len + 1ULL < (u64)USH_BROWSER_HTML_BUF_CAP) {
|
||||||
cleonos_net_tcp_recv_req recv_req;
|
cleonos_net_tcp_recv_req recv_req;
|
||||||
u8 chunk[USH_BROWSER_HTTP_RECV_CHUNK];
|
u8 chunk[USH_BROWSER_HTTP_RECV_CHUNK];
|
||||||
u64 got;
|
u64 got;
|
||||||
u64 cap_left = (u64)sizeof(ush_browser_http_raw_buf) - 1ULL - raw_len;
|
u64 cap_left = (u64)USH_BROWSER_HTML_BUF_CAP - 1ULL - raw_len;
|
||||||
|
|
||||||
recv_req.out_payload_ptr = (u64)(usize)chunk;
|
recv_req.out_payload_ptr = (u64)(usize)chunk;
|
||||||
recv_req.payload_capacity = (u64)sizeof(chunk);
|
recv_req.payload_capacity = (u64)sizeof(chunk);
|
||||||
@@ -1124,7 +1149,7 @@ static void ush_browser_text_newline(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ush_browser_text_len + 1ULL >= (u64)sizeof(ush_browser_text_buf)) {
|
if (ush_browser_text_len + 1ULL >= (u64)USH_BROWSER_TEXT_BUF_CAP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1134,7 +1159,7 @@ static void ush_browser_text_newline(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ush_browser_text_append_char(char ch) {
|
static void ush_browser_text_append_char(char ch) {
|
||||||
if (ush_browser_text_len + 1ULL >= (u64)sizeof(ush_browser_text_buf)) {
|
if (ush_browser_text_len + 1ULL >= (u64)USH_BROWSER_TEXT_BUF_CAP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1180,7 +1205,7 @@ static void ush_browser_text_append_raw(const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (text[i] != '\0') {
|
while (text[i] != '\0') {
|
||||||
if (ush_browser_text_len + 1ULL >= (u64)sizeof(ush_browser_text_buf)) {
|
if (ush_browser_text_len + 1ULL >= (u64)USH_BROWSER_TEXT_BUF_CAP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2371,19 +2396,89 @@ static int ush_browser_read_file(const ush_state *sh, const char *arg, char *out
|
|||||||
return (total > 0ULL) ? 1 : 0;
|
return (total > 0ULL) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ush_browser_render_html(const char *html, u64 html_size) {
|
static int ush_browser_render_html_fallback(const char *html, u64 html_size) {
|
||||||
GumboOutput *output;
|
u64 i = 0ULL;
|
||||||
ush_browser_style root_style;
|
int in_tag = 0;
|
||||||
|
int pending_space = 0;
|
||||||
|
|
||||||
if (html == (const char *)0 || html_size == 0ULL) {
|
if (html == (const char *)0 || html_size == 0ULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = gumbo_parse_with_options(&kGumboDefaultOptions, html, (size_t)html_size);
|
ush_browser_link_count = 0ULL;
|
||||||
if (output == (GumboOutput *)0 || output->root == (GumboNode *)0) {
|
ush_browser_css_rule_count = 0ULL;
|
||||||
|
ush_browser_text_reset();
|
||||||
|
ush_zero(ush_browser_title, (u64)sizeof(ush_browser_title));
|
||||||
|
ush_copy(ush_browser_title, (u64)sizeof(ush_browser_title), "HTML fallback");
|
||||||
|
|
||||||
|
while (i < html_size && html[i] != '\0') {
|
||||||
|
char ch = html[i];
|
||||||
|
|
||||||
|
if (ch == '<') {
|
||||||
|
in_tag = 1;
|
||||||
|
if (pending_space == 0) {
|
||||||
|
ush_browser_text_append_char(' ');
|
||||||
|
pending_space = 1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_tag != 0) {
|
||||||
|
if (ch == '>') {
|
||||||
|
in_tag = 0;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == '&') {
|
||||||
|
ush_browser_text_append_char(' ');
|
||||||
|
pending_space = 1;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_browser_text_append_char(ch);
|
||||||
|
pending_space = (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') ? 1 : 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_browser_text_trim_trailing_spaces();
|
||||||
|
if (ush_browser_text_len == 0ULL) {
|
||||||
|
ush_browser_text_append("[browser] no renderable text");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_browser_render_html(const char *html, u64 html_size) {
|
||||||
|
GumboOutput *output;
|
||||||
|
GumboOptions options;
|
||||||
|
ush_browser_style root_style;
|
||||||
|
u64 parse_size;
|
||||||
|
|
||||||
|
if (html == (const char *)0 || html_size == 0ULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_size = html_size;
|
||||||
|
if (parse_size > (u64)USH_BROWSER_GUMBO_PARSE_MAX) {
|
||||||
|
parse_size = (u64)USH_BROWSER_GUMBO_PARSE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = kGumboDefaultOptions;
|
||||||
|
options.max_errors = USH_BROWSER_GUMBO_MAX_ERRORS;
|
||||||
|
options.stop_on_first_error = false;
|
||||||
|
|
||||||
|
output = gumbo_parse_with_options(&options, html, (size_t)parse_size);
|
||||||
|
if (output == (GumboOutput *)0 || output->root == (GumboNode *)0) {
|
||||||
|
if (output != (GumboOutput *)0) {
|
||||||
|
gumbo_destroy_output(&options, output);
|
||||||
|
}
|
||||||
|
return ush_browser_render_html_fallback(html, parse_size);
|
||||||
|
}
|
||||||
|
|
||||||
ush_browser_link_count = 0ULL;
|
ush_browser_link_count = 0ULL;
|
||||||
ush_browser_css_rule_count = 0ULL;
|
ush_browser_css_rule_count = 0ULL;
|
||||||
ush_browser_text_reset();
|
ush_browser_text_reset();
|
||||||
@@ -2395,7 +2490,7 @@ static int ush_browser_render_html(const char *html, u64 html_size) {
|
|||||||
ush_browser_walk_dom_styled(output->root, &root_style);
|
ush_browser_walk_dom_styled(output->root, &root_style);
|
||||||
ush_browser_text_trim_trailing_spaces();
|
ush_browser_text_trim_trailing_spaces();
|
||||||
|
|
||||||
gumbo_destroy_output(&kGumboDefaultOptions, output);
|
gumbo_destroy_output(&options, output);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2929,6 +3024,11 @@ static int ush_cmd_browser(const ush_state *sh, const char *arg) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ush_browser_ensure_buffers() == 0) {
|
||||||
|
ush_writeln("browser: memory allocation failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0ULL; i < (u64)USH_BROWSER_HISTORY_MAX; i++) {
|
for (i = 0ULL; i < (u64)USH_BROWSER_HISTORY_MAX; i++) {
|
||||||
history[i][0] = '\0';
|
history[i][0] = '\0';
|
||||||
}
|
}
|
||||||
@@ -2953,7 +3053,7 @@ static int ush_cmd_browser(const ush_state *sh, const char *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ush_browser_load_source(sh, current_source, ush_browser_html_buf, (u64)sizeof(ush_browser_html_buf),
|
if (ush_browser_load_source(sh, current_source, ush_browser_html_buf, (u64)USH_BROWSER_HTML_BUF_CAP,
|
||||||
&html_size) == 0) {
|
&html_size) == 0) {
|
||||||
if (ush_browser_is_https_url(current_source) != 0) {
|
if (ush_browser_is_https_url(current_source) != 0) {
|
||||||
ush_writeln("browser: https:// is not supported yet");
|
ush_writeln("browser: https:// is not supported yet");
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ static int ush_cmd_help(void) {
|
|||||||
ush_writeln(" bmpview <file.bmp> [cols]");
|
ush_writeln(" bmpview <file.bmp> [cols]");
|
||||||
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
|
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
|
||||||
ush_writeln(" vim [file] (vim-like editor: normal/insert/:w/:q/:wq)");
|
ush_writeln(" vim [file] (vim-like editor: normal/insert/:w/:q/:wq)");
|
||||||
ush_writeln(" uwm (user-space window manager demo)");
|
ush_writeln(" uwm (user-space window manager)");
|
||||||
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
|
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
|
||||||
ush_writeln(" fastfetch [--plain]");
|
ush_writeln(" fastfetch [--plain]");
|
||||||
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
|
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ static int ush_cmd_help(void) {
|
|||||||
ush_writeln(" bmpview <file.bmp> [cols]");
|
ush_writeln(" bmpview <file.bmp> [cols]");
|
||||||
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
|
ush_writeln(" qrcode [--ecc <L|M|Q|H>] <text>");
|
||||||
ush_writeln(" vim [file] (vim-like editor)");
|
ush_writeln(" vim [file] (vim-like editor)");
|
||||||
ush_writeln(" uwm (user-space window manager demo)");
|
ush_writeln(" uwm (user-space window manager)");
|
||||||
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
|
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
|
||||||
ush_writeln(" fastfetch [--plain]");
|
ush_writeln(" fastfetch [--plain]");
|
||||||
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
|
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
|
||||||
|
|||||||
@@ -3,33 +3,65 @@
|
|||||||
|
|
||||||
#include "../cmd_runtime.h"
|
#include "../cmd_runtime.h"
|
||||||
|
|
||||||
#define USH_UWM_WINDOW_COUNT 3U
|
#define USH_UWM_APP_COUNT 3U
|
||||||
|
#define USH_UWM_TASKBAR_INDEX 3
|
||||||
|
#define USH_UWM_START_INDEX 4
|
||||||
|
#define USH_UWM_WINDOW_COUNT 5U
|
||||||
#define USH_UWM_TTY_DISPLAY 1ULL
|
#define USH_UWM_TTY_DISPLAY 1ULL
|
||||||
#define USH_UWM_TITLE_DRAG_HEIGHT 18
|
|
||||||
#define USH_UWM_MOVE_STEP 12
|
#define USH_UWM_TOP_CLAMP_Y 24
|
||||||
|
#define USH_UWM_TITLE_H 32
|
||||||
|
#define USH_UWM_TASKBAR_H 48
|
||||||
|
#define USH_UWM_START_W 320
|
||||||
|
#define USH_UWM_START_H 360
|
||||||
|
#define USH_UWM_APP_START_W 360
|
||||||
|
#define USH_UWM_APP_START_H 240
|
||||||
|
#define USH_UWM_MIN_WINDOW_W 220
|
||||||
|
#define USH_UWM_MIN_WINDOW_H 150
|
||||||
|
#define USH_UWM_MOVE_STEP 16
|
||||||
|
#define USH_UWM_RESIZE_GRIP 18
|
||||||
|
#define USH_UWM_CONTROL_W 46
|
||||||
#define USH_UWM_EVENT_BUDGET 128ULL
|
#define USH_UWM_EVENT_BUDGET 128ULL
|
||||||
#define USH_UWM_STARTUP_KEY_DRAIN_MAX 256ULL
|
#define USH_UWM_STARTUP_KEY_DRAIN_MAX 256ULL
|
||||||
#define USH_UWM_MIN_WINDOW_W 180
|
#define USH_UWM_IDLE_SPINS 32
|
||||||
#define USH_UWM_MIN_WINDOW_H 120
|
|
||||||
#define USH_UWM_TOP_CLAMP_Y 24
|
#define USH_UWM_TASKBAR_START_W 48
|
||||||
|
#define USH_UWM_TASKBAR_SEARCH_W 220
|
||||||
|
#define USH_UWM_TASKBAR_BUTTON_W 132
|
||||||
|
#define USH_UWM_TASKBAR_BUTTON_GAP 6
|
||||||
|
|
||||||
#define USH_UWM_KEY_LEFT 1ULL
|
#define USH_UWM_KEY_LEFT 1ULL
|
||||||
#define USH_UWM_KEY_RIGHT 2ULL
|
#define USH_UWM_KEY_RIGHT 2ULL
|
||||||
#define USH_UWM_KEY_UP 3ULL
|
#define USH_UWM_KEY_UP 3ULL
|
||||||
#define USH_UWM_KEY_DOWN 4ULL
|
#define USH_UWM_KEY_DOWN 4ULL
|
||||||
|
|
||||||
|
#define USH_UWM_WM_FLAG_TOPMOST 0x1ULL
|
||||||
|
|
||||||
typedef unsigned int ush_uwm_u32;
|
typedef unsigned int ush_uwm_u32;
|
||||||
|
|
||||||
|
typedef enum ush_uwm_window_kind {
|
||||||
|
USH_UWM_KIND_APP = 0,
|
||||||
|
USH_UWM_KIND_TASKBAR = 1,
|
||||||
|
USH_UWM_KIND_START = 2
|
||||||
|
} ush_uwm_window_kind;
|
||||||
|
|
||||||
typedef struct ush_uwm_window {
|
typedef struct ush_uwm_window {
|
||||||
u64 id;
|
u64 id;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
ush_uwm_u32 color;
|
|
||||||
ush_uwm_u32 *pixels;
|
ush_uwm_u32 *pixels;
|
||||||
u64 pixel_count;
|
u64 pixel_count;
|
||||||
int alive;
|
int alive;
|
||||||
|
int minimized;
|
||||||
|
int closed;
|
||||||
|
int topmost;
|
||||||
|
int dirty;
|
||||||
|
ush_uwm_window_kind kind;
|
||||||
|
ush_uwm_u32 accent;
|
||||||
|
char title[32];
|
||||||
|
char subtitle[64];
|
||||||
} ush_uwm_window;
|
} ush_uwm_window;
|
||||||
|
|
||||||
typedef struct ush_uwm_session {
|
typedef struct ush_uwm_session {
|
||||||
@@ -40,24 +72,47 @@ typedef struct ush_uwm_session {
|
|||||||
int drag_window;
|
int drag_window;
|
||||||
int drag_offset_x;
|
int drag_offset_x;
|
||||||
int drag_offset_y;
|
int drag_offset_y;
|
||||||
|
int resizing;
|
||||||
|
int resize_window;
|
||||||
|
int resize_start_x;
|
||||||
|
int resize_start_y;
|
||||||
|
int resize_start_w;
|
||||||
|
int resize_start_h;
|
||||||
|
int resize_pending_w;
|
||||||
|
int resize_pending_h;
|
||||||
|
int start_open;
|
||||||
|
u64 mouse_packet_seen;
|
||||||
u64 tty_before;
|
u64 tty_before;
|
||||||
int tty_switched;
|
int tty_switched;
|
||||||
|
char last_error[96];
|
||||||
ush_uwm_window windows[USH_UWM_WINDOW_COUNT];
|
ush_uwm_window windows[USH_UWM_WINDOW_COUNT];
|
||||||
} ush_uwm_session;
|
} ush_uwm_session;
|
||||||
|
|
||||||
int ush_uwm_window_index_valid(int index);
|
int ush_uwm_window_index_valid(int index);
|
||||||
|
int ush_uwm_app_index_valid(int index);
|
||||||
int ush_uwm_clampi(int value, int min_value, int max_value);
|
int ush_uwm_clampi(int value, int min_value, int max_value);
|
||||||
int ush_uwm_u64_as_i32(u64 raw);
|
int ush_uwm_u64_as_i32(u64 raw);
|
||||||
void ush_uwm_drain_startup_keys(void);
|
void ush_uwm_drain_startup_keys(void);
|
||||||
|
|
||||||
void ush_uwm_render_content(ush_uwm_window *win);
|
|
||||||
int ush_uwm_alloc_pixels(ush_uwm_window *win);
|
int ush_uwm_alloc_pixels(ush_uwm_window *win);
|
||||||
|
int ush_uwm_replace_pixels(ush_uwm_window *win, int width, int height);
|
||||||
|
void ush_uwm_render_window(ush_uwm_session *sess, int index);
|
||||||
|
void ush_uwm_refresh_window(ush_uwm_session *sess, int index);
|
||||||
int ush_uwm_create_window(ush_uwm_window *win);
|
int ush_uwm_create_window(ush_uwm_window *win);
|
||||||
int ush_uwm_present_window(const ush_uwm_window *win);
|
int ush_uwm_present_window(const ush_uwm_window *win);
|
||||||
|
void ush_uwm_destroy_kernel_window(ush_uwm_window *win);
|
||||||
void ush_uwm_destroy_window(ush_uwm_window *win);
|
void ush_uwm_destroy_window(ush_uwm_window *win);
|
||||||
int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x, int target_y);
|
int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x, int target_y);
|
||||||
|
int ush_uwm_window_resize(ush_uwm_session *sess, int index, int target_w, int target_h);
|
||||||
void ush_uwm_set_active(ush_uwm_session *sess, int index);
|
void ush_uwm_set_active(ush_uwm_session *sess, int index);
|
||||||
void ush_uwm_focus_next(ush_uwm_session *sess);
|
void ush_uwm_focus_next(ush_uwm_session *sess);
|
||||||
|
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_start(ush_uwm_session *sess);
|
||||||
|
void ush_uwm_close_start(ush_uwm_session *sess);
|
||||||
|
void ush_uwm_refresh_taskbar(ush_uwm_session *sess);
|
||||||
|
|
||||||
void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event, int *running);
|
void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event, int *running);
|
||||||
int ush_uwm_loop(ush_uwm_session *sess);
|
int ush_uwm_loop(ush_uwm_session *sess);
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
static void ush_uwm_usage(void) {
|
static void ush_uwm_usage(void) {
|
||||||
ush_writeln("usage: uwm");
|
ush_writeln("usage: uwm");
|
||||||
ush_writeln("wm mode: kernel compositor + user window manager");
|
ush_writeln("keys: q quit, tab focus, 1/2/3 restore, wasd/arrow move");
|
||||||
ush_writeln("keys: q quit, tab focus next, 1/2/3 focus, wasd/arrow move");
|
ush_writeln("keys: m minimize, x close, t pin top, +/- resize");
|
||||||
ush_writeln("mouse: drag focused window by title bar");
|
ush_writeln("mouse: drag titlebar, resize bottom-right, use taskbar/start");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ush_uwm_parse_args(const char *arg) {
|
static int ush_uwm_parse_args(const char *arg) {
|
||||||
char first[USH_PATH_MAX];
|
char first[USH_PATH_MAX];
|
||||||
const char *rest = "";
|
const char *rest = "";
|
||||||
|
|
||||||
if (arg == (const char *)0 || arg[0] == '\0') {
|
if (arg == (const char *)0 || arg[0] == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ static int ush_uwm_parse_args(const char *arg) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rest != (const char *)0 && rest[0] != '\0') {
|
if (rest != (const char *)0 && rest[0] != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,74 +30,170 @@ static int ush_uwm_parse_args(const char *arg) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_fail(ush_uwm_session *sess, const char *message) {
|
||||||
|
if (sess != (ush_uwm_session *)0 && message != (const char *)0) {
|
||||||
|
ush_copy(sess->last_error, (u64)sizeof(sess->last_error), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_work_bottom(const ush_uwm_session *sess) {
|
||||||
|
int bottom;
|
||||||
|
|
||||||
|
if (sess == (const ush_uwm_session *)0) {
|
||||||
|
return USH_UWM_TOP_CLAMP_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bottom = sess->screen_h - USH_UWM_TASKBAR_H;
|
||||||
|
if (bottom < USH_UWM_TOP_CLAMP_Y) {
|
||||||
|
bottom = USH_UWM_TOP_CLAMP_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_fit_dimension(int wanted, int min_value, int max_value) {
|
||||||
|
if (max_value < 64) {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_value < min_value) {
|
||||||
|
return max_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ush_uwm_clampi(wanted, min_value, max_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_init_window(ush_uwm_window *win, ush_uwm_window_kind kind, const char *title, const char *subtitle,
|
||||||
|
int x, int y, int w, int h, ush_uwm_u32 accent, int topmost, int closed) {
|
||||||
|
if (win == (ush_uwm_window *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win->id = 0ULL;
|
||||||
|
win->x = x;
|
||||||
|
win->y = y;
|
||||||
|
win->w = w;
|
||||||
|
win->h = h;
|
||||||
|
win->pixels = (ush_uwm_u32 *)0;
|
||||||
|
win->pixel_count = 0ULL;
|
||||||
|
win->alive = 0;
|
||||||
|
win->minimized = 0;
|
||||||
|
win->closed = closed;
|
||||||
|
win->topmost = topmost;
|
||||||
|
win->dirty = 1;
|
||||||
|
win->kind = kind;
|
||||||
|
win->accent = accent;
|
||||||
|
ush_copy(win->title, (u64)sizeof(win->title), title);
|
||||||
|
ush_copy(win->subtitle, (u64)sizeof(win->subtitle), subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_boot_window(ush_uwm_session *sess, int index) {
|
||||||
|
ush_uwm_window *win;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[index];
|
||||||
|
if (win->closed != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win->pixels == (ush_uwm_u32 *)0 && ush_uwm_alloc_pixels(win) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_render_window(sess, index);
|
||||||
|
if (ush_uwm_create_window(win) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_uwm_present_window(win) == 0) {
|
||||||
|
ush_uwm_destroy_kernel_window(win);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int ush_uwm_prepare_session(ush_uwm_session *sess) {
|
int ush_uwm_prepare_session(ush_uwm_session *sess) {
|
||||||
cleonos_fb_info fb;
|
cleonos_fb_info fb;
|
||||||
int i;
|
int work_bottom;
|
||||||
|
int work_h;
|
||||||
int base_w;
|
int base_w;
|
||||||
int base_h;
|
int base_h;
|
||||||
const int x_offsets[USH_UWM_WINDOW_COUNT] = {64, 220, 380};
|
int start_w;
|
||||||
const int y_offsets[USH_UWM_WINDOW_COUNT] = {80, 140, 220};
|
int start_h;
|
||||||
const ush_uwm_u32 colors[USH_UWM_WINDOW_COUNT] = {0x002B3C66UL, 0x00385C7AUL, 0x004A7288UL};
|
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};
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0) {
|
if (sess == (ush_uwm_session *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ush_zero(sess, (u64)sizeof(*sess));
|
ush_zero(sess, (u64)sizeof(*sess));
|
||||||
|
ush_copy(sess->last_error, (u64)sizeof(sess->last_error), "uwm: init failed");
|
||||||
|
|
||||||
if (cleonos_sys_fb_info(&fb) == 0ULL || fb.width == 0ULL || fb.height == 0ULL || fb.bpp != 32ULL) {
|
if (cleonos_sys_fb_info(&fb) == 0ULL || fb.width == 0ULL || fb.height == 0ULL || fb.bpp != 32ULL) {
|
||||||
return 0;
|
return ush_uwm_fail(sess, "uwm: framebuffer unavailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fb.width > 4096ULL || fb.height > 4096ULL) {
|
if (fb.width > 4096ULL || fb.height > 4096ULL) {
|
||||||
return 0;
|
return ush_uwm_fail(sess, "uwm: framebuffer is larger than 4096x4096");
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->screen_w = (int)fb.width;
|
sess->screen_w = (int)fb.width;
|
||||||
sess->screen_h = (int)fb.height;
|
sess->screen_h = (int)fb.height;
|
||||||
sess->active_window = 0;
|
sess->active_window = 0;
|
||||||
sess->dragging = 0;
|
|
||||||
sess->drag_window = -1;
|
sess->drag_window = -1;
|
||||||
sess->drag_offset_x = 0;
|
sess->resize_window = -1;
|
||||||
sess->drag_offset_y = 0;
|
|
||||||
sess->tty_before = cleonos_sys_tty_active();
|
sess->tty_before = cleonos_sys_tty_active();
|
||||||
sess->tty_switched = 0;
|
|
||||||
|
|
||||||
base_w = sess->screen_w / 3;
|
work_bottom = ush_uwm_work_bottom(sess);
|
||||||
base_h = sess->screen_h / 3;
|
work_h = work_bottom - USH_UWM_TOP_CLAMP_Y;
|
||||||
if (base_w < USH_UWM_MIN_WINDOW_W) {
|
if (work_h < 80) {
|
||||||
base_w = USH_UWM_MIN_WINDOW_W;
|
work_h = 80;
|
||||||
}
|
|
||||||
if (base_h < USH_UWM_MIN_WINDOW_H) {
|
|
||||||
base_h = USH_UWM_MIN_WINDOW_H;
|
|
||||||
}
|
|
||||||
if (base_w > sess->screen_w - 40) {
|
|
||||||
base_w = sess->screen_w - 40;
|
|
||||||
}
|
|
||||||
if (base_h > sess->screen_h - 40) {
|
|
||||||
base_h = sess->screen_h - 40;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (int)USH_UWM_WINDOW_COUNT; i++) {
|
base_w = ush_uwm_fit_dimension(USH_UWM_APP_START_W, USH_UWM_MIN_WINDOW_W, sess->screen_w - 48);
|
||||||
ush_uwm_window *win = &sess->windows[i];
|
base_h = ush_uwm_fit_dimension(USH_UWM_APP_START_H, USH_UWM_MIN_WINDOW_H, work_h - 32);
|
||||||
|
app_gap = (sess->screen_w > 900) ? 120 : 58;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
int max_x = sess->screen_w - base_w;
|
int max_x = sess->screen_w - base_w;
|
||||||
int max_y = sess->screen_h - base_h;
|
int max_y = work_bottom - base_h;
|
||||||
|
int x = 56 + (i * app_gap);
|
||||||
|
int y = 64 + (i * 46);
|
||||||
|
|
||||||
if (max_x < 0) {
|
if (max_x < 0) {
|
||||||
max_x = 0;
|
max_x = 0;
|
||||||
}
|
}
|
||||||
if (max_y < 0) {
|
if (max_y < USH_UWM_TOP_CLAMP_Y) {
|
||||||
max_y = 0;
|
max_y = USH_UWM_TOP_CLAMP_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
win->id = 0ULL;
|
ush_uwm_init_window(&sess->windows[i], USH_UWM_KIND_APP, titles[i], subtitles[i], ush_uwm_clampi(x, 0, max_x),
|
||||||
win->x = ush_uwm_clampi(x_offsets[i], 0, max_x);
|
ush_uwm_clampi(y, USH_UWM_TOP_CLAMP_Y, max_y), base_w, base_h, accents[i], 0, 0);
|
||||||
win->y = ush_uwm_clampi(y_offsets[i], USH_UWM_TOP_CLAMP_Y, max_y);
|
}
|
||||||
win->w = base_w;
|
|
||||||
win->h = base_h;
|
ush_uwm_init_window(&sess->windows[USH_UWM_TASKBAR_INDEX], USH_UWM_KIND_TASKBAR, "TASKBAR", "", 0,
|
||||||
win->color = colors[i];
|
sess->screen_h - USH_UWM_TASKBAR_H, sess->screen_w, USH_UWM_TASKBAR_H, 0x000078D7U, 1, 0);
|
||||||
win->pixels = (ush_uwm_u32 *)0;
|
if (sess->windows[USH_UWM_TASKBAR_INDEX].y < USH_UWM_TOP_CLAMP_Y) {
|
||||||
win->pixel_count = 0ULL;
|
sess->windows[USH_UWM_TASKBAR_INDEX].y = USH_UWM_TOP_CLAMP_Y;
|
||||||
win->alive = 0;
|
}
|
||||||
|
|
||||||
|
start_w = ush_uwm_fit_dimension(USH_UWM_START_W, 180, sess->screen_w - 16);
|
||||||
|
start_h = ush_uwm_fit_dimension(USH_UWM_START_H, 160, work_h - 8);
|
||||||
|
ush_uwm_init_window(&sess->windows[USH_UWM_START_INDEX], USH_UWM_KIND_START, "START", "", 0,
|
||||||
|
sess->screen_h - USH_UWM_TASKBAR_H - start_h, start_w, start_h, 0x000078D7U, 1, 1);
|
||||||
|
if (sess->windows[USH_UWM_START_INDEX].y < USH_UWM_TOP_CLAMP_Y) {
|
||||||
|
sess->windows[USH_UWM_START_INDEX].y = USH_UWM_TOP_CLAMP_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -105,30 +201,34 @@ int ush_uwm_prepare_session(ush_uwm_session *sess) {
|
|||||||
|
|
||||||
int ush_uwm_start(ush_uwm_session *sess) {
|
int ush_uwm_start(ush_uwm_session *sess) {
|
||||||
int i;
|
int i;
|
||||||
|
int started = 0;
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0) {
|
if (sess == (ush_uwm_session *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (int)USH_UWM_WINDOW_COUNT; i++) {
|
if (ush_uwm_boot_window(sess, USH_UWM_TASKBAR_INDEX) == 0) {
|
||||||
ush_uwm_window *win = &sess->windows[i];
|
return ush_uwm_fail(sess, "uwm: taskbar create failed");
|
||||||
|
}
|
||||||
|
|
||||||
if (ush_uwm_alloc_pixels(win) == 0) {
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
return 0;
|
if (ush_uwm_boot_window(sess, i) != 0) {
|
||||||
}
|
started++;
|
||||||
|
|
||||||
if (ush_uwm_create_window(win) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ush_uwm_render_content(win);
|
|
||||||
if (ush_uwm_present_window(win) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->active_window = (int)USH_UWM_WINDOW_COUNT - 1;
|
if (started == 0) {
|
||||||
ush_uwm_set_active(sess, sess->active_window);
|
return ush_uwm_fail(sess, "uwm: app window create failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = (int)USH_UWM_APP_COUNT - 1; i >= 0; i--) {
|
||||||
|
if (sess->windows[i].alive != 0) {
|
||||||
|
ush_uwm_set_active(sess, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +285,7 @@ int ush_cmd_uwm(const char *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ush_uwm_prepare_session(&sess) == 0) {
|
if (ush_uwm_prepare_session(&sess) == 0) {
|
||||||
ush_writeln("uwm: framebuffer unavailable");
|
ush_writeln(sess.last_error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,13 +295,10 @@ int ush_cmd_uwm(const char *arg) {
|
|||||||
if (ush_uwm_start(&sess) == 0) {
|
if (ush_uwm_start(&sess) == 0) {
|
||||||
ush_uwm_stop(&sess);
|
ush_uwm_stop(&sess);
|
||||||
ush_uwm_restore_tty(&sess);
|
ush_uwm_restore_tty(&sess);
|
||||||
ush_writeln("uwm: kernel wm unavailable or init failed");
|
ush_writeln(sess.last_error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ush_writeln("uwm: kernel window framework online");
|
|
||||||
ush_writeln("uwm: q quit | tab focus | 1/2/3 focus | wasd/arrow move");
|
|
||||||
|
|
||||||
if (ush_uwm_loop(&sess) != 0) {
|
if (ush_uwm_loop(&sess) != 0) {
|
||||||
success = 1;
|
success = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,67 @@
|
|||||||
#include "uwm.h"
|
#include "uwm.h"
|
||||||
|
|
||||||
|
static int ush_uwm_hit_close(const ush_uwm_window *win, int x, int y) {
|
||||||
|
return (win != (const ush_uwm_window *)0 && x >= win->w - USH_UWM_CONTROL_W && y >= 0 &&
|
||||||
|
y < USH_UWM_TITLE_H)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_hit_minimize(const ush_uwm_window *win, int x, int y) {
|
||||||
|
return (win != (const ush_uwm_window *)0 && x >= win->w - (USH_UWM_CONTROL_W * 2) &&
|
||||||
|
x < win->w - USH_UWM_CONTROL_W && y >= 0 && y < USH_UWM_TITLE_H)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_hit_topmost(const ush_uwm_window *win, int x, int y) {
|
||||||
|
return (win != (const ush_uwm_window *)0 && x >= win->w - (USH_UWM_CONTROL_W * 3) &&
|
||||||
|
x < win->w - (USH_UWM_CONTROL_W * 2) && y >= 0 && y < USH_UWM_TITLE_H)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_hit_resize(const ush_uwm_window *win, int x, int y) {
|
||||||
|
return (win != (const ush_uwm_window *)0 && x >= win->w - USH_UWM_RESIZE_GRIP &&
|
||||||
|
y >= win->h - USH_UWM_RESIZE_GRIP)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_taskbar_app_x(const ush_uwm_window *taskbar) {
|
||||||
|
int search_w = USH_UWM_TASKBAR_SEARCH_W;
|
||||||
|
|
||||||
|
if (taskbar == (const ush_uwm_window *)0) {
|
||||||
|
return USH_UWM_TASKBAR_START_W + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskbar->w < 720) {
|
||||||
|
search_w = 128;
|
||||||
|
}
|
||||||
|
if (taskbar->w < 520) {
|
||||||
|
search_w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return USH_UWM_TASKBAR_START_W + 8 + ((search_w > 0) ? (search_w + 10) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_finish_resize(ush_uwm_session *sess) {
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || sess->resizing == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = sess->resize_window;
|
||||||
|
sess->resizing = 0;
|
||||||
|
sess->resize_window = -1;
|
||||||
|
if (ush_uwm_app_index_valid(index) != 0) {
|
||||||
|
(void)ush_uwm_window_resize(sess, index, sess->resize_pending_w, sess->resize_pending_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *running) {
|
static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *running) {
|
||||||
int idx = 0;
|
int idx;
|
||||||
int dx = 0;
|
int dx = 0;
|
||||||
int dy = 0;
|
int dy = 0;
|
||||||
|
|
||||||
@@ -14,21 +74,43 @@ static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *runnin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == (u64)'\t') {
|
if (key == (u64)' ') {
|
||||||
ush_uwm_focus_next(sess);
|
ush_uwm_focus_next(sess);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key >= (u64)'1' && key <= (u64)'3') {
|
if (key == (u64)'1' || key == (u64)'2' || key == (u64)'3') {
|
||||||
int candidate = (int)(key - (u64)'1');
|
ush_uwm_restore_window(sess, (int)(key - (u64)'1'));
|
||||||
if (ush_uwm_window_index_valid(candidate) != 0) {
|
|
||||||
ush_uwm_set_active(sess, candidate);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = sess->active_window;
|
idx = sess->active_window;
|
||||||
if (ush_uwm_window_index_valid(idx) == 0 || sess->windows[idx].alive == 0) {
|
if (ush_uwm_app_index_valid(idx) == 0 || sess->windows[idx].alive == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == (u64)'m' || key == (u64)'M') {
|
||||||
|
ush_uwm_minimize_window(sess, idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == (u64)'x' || key == (u64)'X') {
|
||||||
|
ush_uwm_close_window(sess, idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == (u64)'t' || key == (u64)'T') {
|
||||||
|
ush_uwm_toggle_topmost(sess, idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == (u64)'+' || key == (u64)'=') {
|
||||||
|
(void)ush_uwm_window_resize(sess, idx, sess->windows[idx].w + 32, sess->windows[idx].h + 24);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == (u64)'-') {
|
||||||
|
(void)ush_uwm_window_resize(sess, idx, sess->windows[idx].w - 32, sess->windows[idx].h - 24);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +129,66 @@ static void ush_uwm_handle_key_event(ush_uwm_session *sess, u64 key, int *runnin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_handle_taskbar_click(ush_uwm_session *sess, int local_x, int local_y) {
|
||||||
|
const ush_uwm_window *taskbar;
|
||||||
|
int app_x;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskbar = &sess->windows[USH_UWM_TASKBAR_INDEX];
|
||||||
|
if (local_y < 0 || local_y >= taskbar->h) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_x >= 0 && local_x < USH_UWM_TASKBAR_START_W) {
|
||||||
|
ush_uwm_toggle_start(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_x = ush_uwm_taskbar_app_x(taskbar);
|
||||||
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
|
ush_uwm_window *app = &sess->windows[i];
|
||||||
|
|
||||||
|
if (local_x >= app_x && local_x < app_x + USH_UWM_TASKBAR_BUTTON_W && local_y >= 5 && local_y < taskbar->h - 5) {
|
||||||
|
if (app->alive != 0 && app->minimized == 0 && sess->active_window == i) {
|
||||||
|
ush_uwm_minimize_window(sess, i);
|
||||||
|
} else {
|
||||||
|
ush_uwm_restore_window(sess, i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app_x += USH_UWM_TASKBAR_BUTTON_W + USH_UWM_TASKBAR_BUTTON_GAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_handle_start_click(ush_uwm_session *sess, int local_x, int local_y) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_x < 52 && local_y >= sess->windows[USH_UWM_START_INDEX].h - 52) {
|
||||||
|
ush_uwm_close_start(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
|
int y = 78 + (i * 44);
|
||||||
|
|
||||||
|
if (local_x >= 66 && local_x < sess->windows[USH_UWM_START_INDEX].w - 16 && local_y >= y && local_y < y + 34) {
|
||||||
|
ush_uwm_restore_window(sess, i);
|
||||||
|
ush_uwm_close_start(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event) {
|
static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event) {
|
||||||
|
ush_uwm_window *win;
|
||||||
u64 buttons;
|
u64 buttons;
|
||||||
u64 changed;
|
u64 changed;
|
||||||
int local_x;
|
int local_x;
|
||||||
@@ -60,6 +201,7 @@ static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[window_index];
|
||||||
buttons = event->arg0;
|
buttons = event->arg0;
|
||||||
changed = event->arg1;
|
changed = event->arg1;
|
||||||
local_x = ush_uwm_u64_as_i32(event->arg2);
|
local_x = ush_uwm_u64_as_i32(event->arg2);
|
||||||
@@ -71,39 +213,144 @@ static void ush_uwm_handle_mouse_button(ush_uwm_session *sess, int window_index,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left_down != 0) {
|
if (left_down == 0) {
|
||||||
if (local_y >= 0 && local_y < USH_UWM_TITLE_DRAG_HEIGHT) {
|
if (sess->dragging != 0 && sess->drag_window == window_index) {
|
||||||
sess->dragging = 1;
|
sess->dragging = 0;
|
||||||
sess->drag_window = window_index;
|
sess->drag_window = -1;
|
||||||
sess->drag_offset_x = local_x;
|
|
||||||
sess->drag_offset_y = local_y;
|
|
||||||
sess->active_window = window_index;
|
|
||||||
}
|
}
|
||||||
} else if (sess->dragging != 0 && sess->drag_window == window_index) {
|
if (sess->resizing != 0 && sess->resize_window == window_index) {
|
||||||
sess->dragging = 0;
|
ush_uwm_finish_resize(sess);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win->kind == USH_UWM_KIND_TASKBAR) {
|
||||||
|
ush_uwm_handle_taskbar_click(sess, local_x, local_y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win->kind == USH_UWM_KIND_START) {
|
||||||
|
ush_uwm_handle_start_click(sess, local_x, local_y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_uwm_app_index_valid(window_index) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sess->start_open != 0) {
|
||||||
|
ush_uwm_close_start(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_set_active(sess, window_index);
|
||||||
|
|
||||||
|
if (ush_uwm_hit_close(win, local_x, local_y) != 0) {
|
||||||
|
ush_uwm_close_window(sess, window_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_uwm_hit_minimize(win, local_x, local_y) != 0) {
|
||||||
|
ush_uwm_minimize_window(sess, window_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_uwm_hit_topmost(win, local_x, local_y) != 0) {
|
||||||
|
ush_uwm_toggle_topmost(sess, window_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_uwm_hit_resize(win, local_x, local_y) != 0) {
|
||||||
|
sess->resizing = 1;
|
||||||
|
sess->resize_window = window_index;
|
||||||
|
sess->mouse_packet_seen = 0ULL;
|
||||||
|
sess->resize_start_x = win->x + local_x;
|
||||||
|
sess->resize_start_y = win->y + local_y;
|
||||||
|
sess->resize_start_w = win->w;
|
||||||
|
sess->resize_start_h = win->h;
|
||||||
|
sess->resize_pending_w = win->w;
|
||||||
|
sess->resize_pending_h = win->h;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_y >= 0 && local_y < USH_UWM_TITLE_H) {
|
||||||
|
sess->dragging = 1;
|
||||||
|
sess->drag_window = window_index;
|
||||||
|
sess->mouse_packet_seen = 0ULL;
|
||||||
|
sess->drag_offset_x = local_x;
|
||||||
|
sess->drag_offset_y = local_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ush_uwm_handle_mouse_move(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event) {
|
static void ush_uwm_handle_mouse_move(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event) {
|
||||||
int global_x;
|
int global_x;
|
||||||
int global_y;
|
int global_y;
|
||||||
int new_x;
|
|
||||||
int new_y;
|
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0 || event == (const cleonos_wm_event *)0 ||
|
if (sess == (ush_uwm_session *)0 || event == (const cleonos_wm_event *)0 ||
|
||||||
ush_uwm_window_index_valid(window_index) == 0) {
|
ush_uwm_window_index_valid(window_index) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sess->dragging == 0 || sess->drag_window != window_index) {
|
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) {
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
global_x = ush_uwm_u64_as_i32(event->arg0);
|
if (sess->dragging != 0 && sess->drag_window == window_index && ush_uwm_app_index_valid(window_index) != 0) {
|
||||||
global_y = ush_uwm_u64_as_i32(event->arg1);
|
(void)ush_uwm_window_move_clamped(sess, window_index, global_x - sess->drag_offset_x,
|
||||||
new_x = global_x - sess->drag_offset_x;
|
global_y - sess->drag_offset_y);
|
||||||
new_y = global_y - sess->drag_offset_y;
|
}
|
||||||
(void)ush_uwm_window_move_clamped(sess, window_index, new_x, new_y);
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_drive_direct_pointer(ush_uwm_session *sess) {
|
||||||
|
cleonos_mouse_state mouse;
|
||||||
|
int global_x;
|
||||||
|
int global_y;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || (sess->dragging == 0 && sess->resizing == 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_zero(&mouse, (u64)sizeof(mouse));
|
||||||
|
if (cleonos_sys_mouse_state(&mouse) == 0ULL || mouse.ready == 0ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse.packet_count == sess->mouse_packet_seen) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sess->mouse_packet_seen = mouse.packet_count;
|
||||||
|
|
||||||
|
if ((mouse.buttons & 0x1ULL) == 0ULL) {
|
||||||
|
if (sess->dragging != 0) {
|
||||||
|
sess->dragging = 0;
|
||||||
|
sess->drag_window = -1;
|
||||||
|
}
|
||||||
|
if (sess->resizing != 0) {
|
||||||
|
ush_uwm_finish_resize(sess);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
(void)ush_uwm_window_move_clamped(sess, sess->drag_window, global_x - sess->drag_offset_x,
|
||||||
|
global_y - sess->drag_offset_y);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event, int *running) {
|
void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos_wm_event *event, int *running) {
|
||||||
@@ -114,11 +361,23 @@ void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos
|
|||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case CLEONOS_WM_EVENT_FOCUS_GAINED:
|
case CLEONOS_WM_EVENT_FOCUS_GAINED:
|
||||||
sess->active_window = window_index;
|
if (ush_uwm_app_index_valid(window_index) != 0) {
|
||||||
|
int old_active = sess->active_window;
|
||||||
|
sess->active_window = window_index;
|
||||||
|
if (ush_uwm_app_index_valid(old_active) != 0 && old_active != window_index) {
|
||||||
|
ush_uwm_refresh_window(sess, old_active);
|
||||||
|
}
|
||||||
|
ush_uwm_refresh_window(sess, window_index);
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CLEONOS_WM_EVENT_FOCUS_LOST:
|
case CLEONOS_WM_EVENT_FOCUS_LOST:
|
||||||
if (sess->drag_window == window_index) {
|
if (sess->drag_window == window_index) {
|
||||||
sess->dragging = 0;
|
sess->dragging = 0;
|
||||||
|
sess->drag_window = -1;
|
||||||
|
}
|
||||||
|
if (sess->resize_window == window_index) {
|
||||||
|
ush_uwm_finish_resize(sess);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLEONOS_WM_EVENT_KEY:
|
case CLEONOS_WM_EVENT_KEY:
|
||||||
@@ -135,8 +394,41 @@ void ush_uwm_handle_event(ush_uwm_session *sess, int window_index, const cleonos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ush_uwm_poll_window_events(ush_uwm_session *sess, int window_index, int *running) {
|
||||||
|
ush_uwm_window *win;
|
||||||
|
u64 budget = 0ULL;
|
||||||
|
int handled = 0;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || running == (int *)0 || ush_uwm_window_index_valid(window_index) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[window_index];
|
||||||
|
if (win->alive == 0 || win->id == 0ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (budget < USH_UWM_EVENT_BUDGET) {
|
||||||
|
cleonos_wm_event event;
|
||||||
|
ush_zero(&event, (u64)sizeof(event));
|
||||||
|
if (cleonos_sys_wm_poll_event(win->id, &event) == 0ULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_handle_event(sess, window_index, &event, running);
|
||||||
|
handled++;
|
||||||
|
if (*running == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
budget++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
int ush_uwm_loop(ush_uwm_session *sess) {
|
int ush_uwm_loop(ush_uwm_session *sess) {
|
||||||
int running = 1;
|
int running = 1;
|
||||||
|
int idle_spins = 0;
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0) {
|
if (sess == (ush_uwm_session *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -144,30 +436,33 @@ int ush_uwm_loop(ush_uwm_session *sess) {
|
|||||||
|
|
||||||
while (running != 0) {
|
while (running != 0) {
|
||||||
int i;
|
int i;
|
||||||
|
int handled_events = 0;
|
||||||
|
int preferred_window = -1;
|
||||||
|
|
||||||
|
if (sess->dragging != 0 && ush_uwm_window_index_valid(sess->drag_window) != 0) {
|
||||||
|
preferred_window = sess->drag_window;
|
||||||
|
} else if (sess->resizing != 0 && ush_uwm_window_index_valid(sess->resize_window) != 0) {
|
||||||
|
preferred_window = sess->resize_window;
|
||||||
|
} else if (sess->start_open != 0 && sess->windows[USH_UWM_START_INDEX].alive != 0) {
|
||||||
|
preferred_window = USH_UWM_START_INDEX;
|
||||||
|
} else if (ush_uwm_window_index_valid(sess->active_window) != 0) {
|
||||||
|
preferred_window = sess->active_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled_events += ush_uwm_drive_direct_pointer(sess);
|
||||||
|
if (preferred_window >= 0) {
|
||||||
|
handled_events += ush_uwm_poll_window_events(sess, preferred_window, &running);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < (int)USH_UWM_WINDOW_COUNT; i++) {
|
for (i = 0; i < (int)USH_UWM_WINDOW_COUNT; i++) {
|
||||||
ush_uwm_window *win = &sess->windows[i];
|
if (i == preferred_window) {
|
||||||
u64 budget = 0ULL;
|
|
||||||
|
|
||||||
if (win->alive == 0 || win->id == 0ULL) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
handled_events += ush_uwm_poll_window_events(sess, i, &running);
|
||||||
while (budget < USH_UWM_EVENT_BUDGET) {
|
|
||||||
cleonos_wm_event event;
|
|
||||||
ush_zero(&event, (u64)sizeof(event));
|
|
||||||
if (cleonos_sys_wm_poll_event(win->id, &event) == 0ULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ush_uwm_handle_event(sess, i, &event, &running);
|
|
||||||
if (running == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
budget++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (running == 0) {
|
if (running == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -177,7 +472,20 @@ int ush_uwm_loop(ush_uwm_session *sess) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)cleonos_sys_yield();
|
if (handled_events != 0 || sess->dragging != 0 || sess->resizing != 0) {
|
||||||
|
idle_spins = 0;
|
||||||
|
(void)cleonos_sys_yield();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idle_spins < USH_UWM_IDLE_SPINS) {
|
||||||
|
idle_spins++;
|
||||||
|
(void)cleonos_sys_yield();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
idle_spins = 0;
|
||||||
|
(void)cleonos_sys_sleep_ticks(1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -4,7 +4,15 @@ int ush_uwm_window_index_valid(int index) {
|
|||||||
return (index >= 0 && index < (int)USH_UWM_WINDOW_COUNT) ? 1 : 0;
|
return (index >= 0 && index < (int)USH_UWM_WINDOW_COUNT) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ush_uwm_app_index_valid(int index) {
|
||||||
|
return (index >= 0 && index < (int)USH_UWM_APP_COUNT) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ush_uwm_clampi(int value, int min_value, int max_value) {
|
int ush_uwm_clampi(int value, int min_value, int max_value) {
|
||||||
|
if (max_value < min_value) {
|
||||||
|
return min_value;
|
||||||
|
}
|
||||||
|
|
||||||
if (value < min_value) {
|
if (value < min_value) {
|
||||||
return min_value;
|
return min_value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,65 @@
|
|||||||
#include "uwm.h"
|
#include "uwm.h"
|
||||||
|
|
||||||
|
#define UWM_GLYPH7(r0, r1, r2, r3, r4, r5, r6) \
|
||||||
|
(((u64)(r0) << 30U) | ((u64)(r1) << 25U) | ((u64)(r2) << 20U) | ((u64)(r3) << 15U) | \
|
||||||
|
((u64)(r4) << 10U) | ((u64)(r5) << 5U) | (u64)(r6))
|
||||||
|
|
||||||
|
#define UWM_COLOR_WHITE 0x00FFFFFFU
|
||||||
|
#define UWM_COLOR_WIN_BLUE 0x000078D7U
|
||||||
|
#define UWM_COLOR_DARKER 0x00181818U
|
||||||
|
#define UWM_COLOR_LIGHT_BG 0x00F3F3F3U
|
||||||
|
#define UWM_COLOR_PANEL 0x00FFFFFFU
|
||||||
|
#define UWM_COLOR_TEXT 0x00232323U
|
||||||
|
#define UWM_COLOR_MUTED 0x00666666U
|
||||||
|
#define UWM_COLOR_BORDER 0x00D0D0D0U
|
||||||
|
|
||||||
|
static int ush_uwm_work_bottom(const ush_uwm_session *sess) {
|
||||||
|
int bottom;
|
||||||
|
|
||||||
|
if (sess == (const ush_uwm_session *)0) {
|
||||||
|
return USH_UWM_TOP_CLAMP_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bottom = sess->screen_h - USH_UWM_TASKBAR_H;
|
||||||
|
if (bottom < USH_UWM_TOP_CLAMP_Y) {
|
||||||
|
bottom = USH_UWM_TOP_CLAMP_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ush_uwm_u32 ush_uwm_mix(ush_uwm_u32 a, ush_uwm_u32 b, int pos, int max_pos) {
|
||||||
|
unsigned int ar;
|
||||||
|
unsigned int ag;
|
||||||
|
unsigned int ab;
|
||||||
|
unsigned int br;
|
||||||
|
unsigned int bg;
|
||||||
|
unsigned int bb;
|
||||||
|
unsigned int r;
|
||||||
|
unsigned int g;
|
||||||
|
unsigned int blue;
|
||||||
|
unsigned int left;
|
||||||
|
unsigned int right;
|
||||||
|
|
||||||
|
if (max_pos <= 0) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = ush_uwm_clampi(pos, 0, max_pos);
|
||||||
|
left = (unsigned int)(max_pos - pos);
|
||||||
|
right = (unsigned int)pos;
|
||||||
|
ar = (a >> 16U) & 0xFFU;
|
||||||
|
ag = (a >> 8U) & 0xFFU;
|
||||||
|
ab = a & 0xFFU;
|
||||||
|
br = (b >> 16U) & 0xFFU;
|
||||||
|
bg = (b >> 8U) & 0xFFU;
|
||||||
|
bb = b & 0xFFU;
|
||||||
|
r = ((ar * left) + (br * right)) / (unsigned int)max_pos;
|
||||||
|
g = ((ag * left) + (bg * right)) / (unsigned int)max_pos;
|
||||||
|
blue = ((ab * left) + (bb * right)) / (unsigned int)max_pos;
|
||||||
|
return (ush_uwm_u32)((r << 16U) | (g << 8U) | blue);
|
||||||
|
}
|
||||||
|
|
||||||
static void ush_uwm_fill_rect(ush_uwm_window *win, int x, int y, int w, int h, ush_uwm_u32 color) {
|
static void ush_uwm_fill_rect(ush_uwm_window *win, int x, int y, int w, int h, ush_uwm_u32 color) {
|
||||||
int left;
|
int left;
|
||||||
int top;
|
int top;
|
||||||
@@ -38,54 +98,517 @@ static void ush_uwm_fill_rect(ush_uwm_window *win, int x, int y, int w, int h, u
|
|||||||
u64 base = (u64)(unsigned int)row * (u64)(unsigned int)win->w;
|
u64 base = (u64)(unsigned int)row * (u64)(unsigned int)win->w;
|
||||||
int col;
|
int col;
|
||||||
|
|
||||||
|
if (base + (u64)(unsigned int)right > win->pixel_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (col = left; col < right; col++) {
|
for (col = left; col < right; col++) {
|
||||||
u64 idx = base + (u64)(unsigned int)col;
|
win->pixels[base + (u64)(unsigned int)col] = color;
|
||||||
if (idx >= win->pixel_count) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
win->pixels[idx] = color;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ush_uwm_render_content(ush_uwm_window *win) {
|
static void ush_uwm_gradient_rect(ush_uwm_window *win, int x, int y, int w, int h, ush_uwm_u32 top,
|
||||||
int y;
|
ush_uwm_u32 bottom) {
|
||||||
|
int row;
|
||||||
|
|
||||||
if (win == (ush_uwm_window *)0 || win->pixels == (ush_uwm_u32 *)0) {
|
for (row = 0; row < h; row++) {
|
||||||
return;
|
ush_uwm_fill_rect(win, x, y + row, w, 1, ush_uwm_mix(top, bottom, row, h - 1));
|
||||||
}
|
|
||||||
|
|
||||||
ush_uwm_fill_rect(win, 0, 0, win->w, win->h, win->color);
|
|
||||||
ush_uwm_fill_rect(win, 0, 0, win->w, 18, 0x001A1F2BUL);
|
|
||||||
ush_uwm_fill_rect(win, 8, 5, 8, 8, 0x00FFD166UL);
|
|
||||||
ush_uwm_fill_rect(win, win->w - 18, 5, 10, 8, 0x00E76F51UL);
|
|
||||||
|
|
||||||
for (y = 30; y < win->h; y += 22) {
|
|
||||||
ush_uwm_fill_rect(win, 10, y, win->w - 20, 1, 0x003F4D62UL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_stroke_rect(ush_uwm_window *win, int x, int y, int w, int h, ush_uwm_u32 color) {
|
||||||
|
ush_uwm_fill_rect(win, x, y, w, 1, color);
|
||||||
|
ush_uwm_fill_rect(win, x, y + h - 1, w, 1, color);
|
||||||
|
ush_uwm_fill_rect(win, x, y, 1, h, color);
|
||||||
|
ush_uwm_fill_rect(win, x + w - 1, y, 1, h, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char ush_uwm_upper_char(char ch) {
|
||||||
|
if (ch >= 'a' && ch <= 'z') {
|
||||||
|
return (char)(ch - ('a' - 'A'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 ush_uwm_glyph_mask(char ch) {
|
||||||
|
switch (ush_uwm_upper_char(ch)) {
|
||||||
|
case 'A':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 17U, 31U, 17U, 17U, 17U);
|
||||||
|
case 'B':
|
||||||
|
return UWM_GLYPH7(30U, 17U, 17U, 30U, 17U, 17U, 30U);
|
||||||
|
case 'C':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 16U, 16U, 16U, 17U, 14U);
|
||||||
|
case 'D':
|
||||||
|
return UWM_GLYPH7(30U, 17U, 17U, 17U, 17U, 17U, 30U);
|
||||||
|
case 'E':
|
||||||
|
return UWM_GLYPH7(31U, 16U, 16U, 30U, 16U, 16U, 31U);
|
||||||
|
case 'F':
|
||||||
|
return UWM_GLYPH7(31U, 16U, 16U, 30U, 16U, 16U, 16U);
|
||||||
|
case 'G':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 16U, 23U, 17U, 17U, 15U);
|
||||||
|
case 'H':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 17U, 31U, 17U, 17U, 17U);
|
||||||
|
case 'I':
|
||||||
|
return UWM_GLYPH7(31U, 4U, 4U, 4U, 4U, 4U, 31U);
|
||||||
|
case 'J':
|
||||||
|
return UWM_GLYPH7(1U, 1U, 1U, 1U, 17U, 17U, 14U);
|
||||||
|
case 'K':
|
||||||
|
return UWM_GLYPH7(17U, 18U, 20U, 24U, 20U, 18U, 17U);
|
||||||
|
case 'L':
|
||||||
|
return UWM_GLYPH7(16U, 16U, 16U, 16U, 16U, 16U, 31U);
|
||||||
|
case 'M':
|
||||||
|
return UWM_GLYPH7(17U, 27U, 21U, 21U, 17U, 17U, 17U);
|
||||||
|
case 'N':
|
||||||
|
return UWM_GLYPH7(17U, 25U, 21U, 19U, 17U, 17U, 17U);
|
||||||
|
case 'O':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 17U, 17U, 17U, 17U, 14U);
|
||||||
|
case 'P':
|
||||||
|
return UWM_GLYPH7(30U, 17U, 17U, 30U, 16U, 16U, 16U);
|
||||||
|
case 'Q':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 17U, 17U, 21U, 18U, 13U);
|
||||||
|
case 'R':
|
||||||
|
return UWM_GLYPH7(30U, 17U, 17U, 30U, 20U, 18U, 17U);
|
||||||
|
case 'S':
|
||||||
|
return UWM_GLYPH7(15U, 16U, 16U, 14U, 1U, 1U, 30U);
|
||||||
|
case 'T':
|
||||||
|
return UWM_GLYPH7(31U, 4U, 4U, 4U, 4U, 4U, 4U);
|
||||||
|
case 'U':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 17U, 17U, 17U, 17U, 14U);
|
||||||
|
case 'V':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 17U, 17U, 17U, 10U, 4U);
|
||||||
|
case 'W':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 17U, 21U, 21U, 21U, 10U);
|
||||||
|
case 'X':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 10U, 4U, 10U, 17U, 17U);
|
||||||
|
case 'Y':
|
||||||
|
return UWM_GLYPH7(17U, 17U, 10U, 4U, 4U, 4U, 4U);
|
||||||
|
case 'Z':
|
||||||
|
return UWM_GLYPH7(31U, 1U, 2U, 4U, 8U, 16U, 31U);
|
||||||
|
case '0':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 19U, 21U, 25U, 17U, 14U);
|
||||||
|
case '1':
|
||||||
|
return UWM_GLYPH7(4U, 12U, 4U, 4U, 4U, 4U, 14U);
|
||||||
|
case '2':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 1U, 2U, 4U, 8U, 31U);
|
||||||
|
case '3':
|
||||||
|
return UWM_GLYPH7(30U, 1U, 1U, 14U, 1U, 1U, 30U);
|
||||||
|
case '4':
|
||||||
|
return UWM_GLYPH7(2U, 6U, 10U, 18U, 31U, 2U, 2U);
|
||||||
|
case '5':
|
||||||
|
return UWM_GLYPH7(31U, 16U, 16U, 30U, 1U, 1U, 30U);
|
||||||
|
case '6':
|
||||||
|
return UWM_GLYPH7(14U, 16U, 16U, 30U, 17U, 17U, 14U);
|
||||||
|
case '7':
|
||||||
|
return UWM_GLYPH7(31U, 1U, 2U, 4U, 8U, 8U, 8U);
|
||||||
|
case '8':
|
||||||
|
return UWM_GLYPH7(14U, 17U, 17U, 14U, 17U, 17U, 14U);
|
||||||
|
case '9':
|
||||||
|
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(0U, 0U, 0U, 0U, 0U, 0U, 31U);
|
||||||
|
case '.':
|
||||||
|
return UWM_GLYPH7(0U, 0U, 0U, 0U, 0U, 12U, 12U);
|
||||||
|
case ':':
|
||||||
|
return UWM_GLYPH7(0U, 12U, 12U, 0U, 12U, 12U, 0U);
|
||||||
|
case '/':
|
||||||
|
return UWM_GLYPH7(1U, 1U, 2U, 4U, 8U, 16U, 16U);
|
||||||
|
case '+':
|
||||||
|
return UWM_GLYPH7(0U, 4U, 4U, 31U, 4U, 4U, 0U);
|
||||||
|
case '=':
|
||||||
|
return UWM_GLYPH7(0U, 0U, 31U, 0U, 31U, 0U, 0U);
|
||||||
|
case '^':
|
||||||
|
return UWM_GLYPH7(4U, 10U, 17U, 0U, 0U, 0U, 0U);
|
||||||
|
case '|':
|
||||||
|
return UWM_GLYPH7(4U, 4U, 4U, 4U, 4U, 4U, 4U);
|
||||||
|
default:
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_char(ush_uwm_window *win, int x, int y, char ch, int scale, ush_uwm_u32 color) {
|
||||||
|
u64 mask = ush_uwm_glyph_mask(ch);
|
||||||
|
int row;
|
||||||
|
|
||||||
|
if (mask == 0ULL || scale <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row = 0; row < 7; row++) {
|
||||||
|
int col;
|
||||||
|
for (col = 0; col < 5; col++) {
|
||||||
|
unsigned int bit_index = (unsigned int)((6 - row) * 5 + (4 - col));
|
||||||
|
if ((mask & (1ULL << bit_index)) != 0ULL) {
|
||||||
|
ush_uwm_fill_rect(win, x + (col * scale), y + (row * scale), scale, scale, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_text_limit(ush_uwm_window *win, int x, int y, const char *text, int scale, ush_uwm_u32 color,
|
||||||
|
int max_x) {
|
||||||
|
int cursor_x = x;
|
||||||
|
|
||||||
|
if (win == (ush_uwm_window *)0 || text == (const char *)0 || scale <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_x <= 0 || max_x > win->w) {
|
||||||
|
max_x = win->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*text != 0 && cursor_x + (5 * scale) <= max_x) {
|
||||||
|
if (*text != ' ') {
|
||||||
|
ush_uwm_draw_char(win, cursor_x, y, *text, scale, color);
|
||||||
|
}
|
||||||
|
cursor_x += 6 * scale;
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_text(ush_uwm_window *win, int x, int y, const char *text, int scale, ush_uwm_u32 color) {
|
||||||
|
ush_uwm_draw_text_limit(win, x, y, text, scale, color, win != (ush_uwm_window *)0 ? win->w : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_windows_logo(ush_uwm_window *win, int x, int y, int size, ush_uwm_u32 color) {
|
||||||
|
int half = size / 2;
|
||||||
|
int gap = (size >= 20) ? 2 : 1;
|
||||||
|
|
||||||
|
ush_uwm_fill_rect(win, x, y, half - gap, half - gap, color);
|
||||||
|
ush_uwm_fill_rect(win, x + half + gap, y, half - gap, half - gap, color);
|
||||||
|
ush_uwm_fill_rect(win, x, y + half + gap, half - gap, half - gap, color);
|
||||||
|
ush_uwm_fill_rect(win, x + half + gap, y + half + gap, half - gap, half - gap, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_control_button(ush_uwm_window *win, int x, int active, int kind) {
|
||||||
|
ush_uwm_u32 bg = (kind == 2) ? 0x00E81123U : (active != 0 ? 0x001A5EA0U : 0x00E5E5E5U);
|
||||||
|
ush_uwm_u32 fg = (kind == 2 || active != 0) ? UWM_COLOR_WHITE : UWM_COLOR_TEXT;
|
||||||
|
int cy = USH_UWM_TITLE_H / 2;
|
||||||
|
int cx = x + (USH_UWM_CONTROL_W / 2);
|
||||||
|
|
||||||
|
ush_uwm_fill_rect(win, x, 0, USH_UWM_CONTROL_W, USH_UWM_TITLE_H, bg);
|
||||||
|
if (kind == 0) {
|
||||||
|
ush_uwm_fill_rect(win, cx - 6, cy + 4, 12, 1, fg);
|
||||||
|
} else if (kind == 1) {
|
||||||
|
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 {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 11; i++) {
|
||||||
|
ush_uwm_fill_rect(win, cx - 5 + i, cy - 5 + i, 1, 1, fg);
|
||||||
|
ush_uwm_fill_rect(win, cx + 5 - i, cy - 5 + i, 1, 1, fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_window_controls(ush_uwm_window *win, int active) {
|
||||||
|
int close_x;
|
||||||
|
int pin_x;
|
||||||
|
int min_x;
|
||||||
|
|
||||||
|
if (win == (ush_uwm_window *)0 || win->w < (USH_UWM_CONTROL_W * 3) + 16) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close_x = win->w - USH_UWM_CONTROL_W;
|
||||||
|
min_x = close_x - USH_UWM_CONTROL_W;
|
||||||
|
pin_x = min_x - USH_UWM_CONTROL_W;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_draw_button(ush_uwm_window *win, int x, int y, int w, int h, const char *label, ush_uwm_u32 bg,
|
||||||
|
ush_uwm_u32 fg, int active) {
|
||||||
|
ush_uwm_fill_rect(win, x, y, w, h, bg);
|
||||||
|
if (active != 0) {
|
||||||
|
ush_uwm_fill_rect(win, x, y + h - 3, w, 3, UWM_COLOR_WIN_BLUE);
|
||||||
|
}
|
||||||
|
ush_uwm_draw_text_limit(win, x + 10, y + ((h - 7) / 2), label, 1, fg, x + w - 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_render_files(ush_uwm_window *win) {
|
||||||
|
int y;
|
||||||
|
|
||||||
|
ush_uwm_fill_rect(win, 0, USH_UWM_TITLE_H, 92, win->h - USH_UWM_TITLE_H, 0x00F7F7F7U);
|
||||||
|
ush_uwm_fill_rect(win, 92, USH_UWM_TITLE_H, 1, win->h - USH_UWM_TITLE_H, UWM_COLOR_BORDER);
|
||||||
|
ush_uwm_draw_text(win, 12, USH_UWM_TITLE_H + 16, "QUICK ACCESS", 1, UWM_COLOR_MUTED);
|
||||||
|
ush_uwm_draw_text(win, 18, USH_UWM_TITLE_H + 40, "DESKTOP", 1, UWM_COLOR_TEXT);
|
||||||
|
ush_uwm_draw_text(win, 18, USH_UWM_TITLE_H + 62, "SYSTEM", 1, UWM_COLOR_TEXT);
|
||||||
|
ush_uwm_draw_text(win, 18, USH_UWM_TITLE_H + 84, "TEMP", 1, UWM_COLOR_TEXT);
|
||||||
|
|
||||||
|
ush_uwm_draw_text(win, 112, USH_UWM_TITLE_H + 16, "THIS PC", 2, UWM_COLOR_TEXT);
|
||||||
|
ush_uwm_fill_rect(win, 112, USH_UWM_TITLE_H + 48, win->w - 132, 34, UWM_COLOR_PANEL);
|
||||||
|
ush_uwm_stroke_rect(win, 112, USH_UWM_TITLE_H + 48, win->w - 132, 34, UWM_COLOR_BORDER);
|
||||||
|
ush_uwm_draw_text(win, 124, USH_UWM_TITLE_H + 60, "C:/ CLEONOS LOCAL DISK", 1, UWM_COLOR_TEXT);
|
||||||
|
ush_uwm_fill_rect(win, 124, USH_UWM_TITLE_H + 72, win->w - 184, 4, 0x00D9D9D9U);
|
||||||
|
ush_uwm_fill_rect(win, 124, USH_UWM_TITLE_H + 72, (win->w - 184) / 2, 4, UWM_COLOR_WIN_BLUE);
|
||||||
|
|
||||||
|
y = USH_UWM_TITLE_H + 104;
|
||||||
|
while (y + 22 < win->h - 14) {
|
||||||
|
ush_uwm_fill_rect(win, 112, y, win->w - 132, 1, 0x00E6E6E6U);
|
||||||
|
y += 28;
|
||||||
|
}
|
||||||
|
ush_uwm_draw_text(win, 118, USH_UWM_TITLE_H + 110, "SYSTEM", 1, UWM_COLOR_TEXT);
|
||||||
|
ush_uwm_draw_text(win, 118, USH_UWM_TITLE_H + 138, "SHELL", 1, UWM_COLOR_TEXT);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_render_browser(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(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);
|
||||||
|
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_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_uwm_render_app_window(ush_uwm_session *sess, int index) {
|
||||||
|
ush_uwm_window *win;
|
||||||
|
int active;
|
||||||
|
ush_uwm_u32 title_bg;
|
||||||
|
ush_uwm_u32 title_fg;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[index];
|
||||||
|
active = (sess->active_window == index && win->minimized == 0 && win->closed == 0) ? 1 : 0;
|
||||||
|
title_bg = (active != 0) ? win->accent : 0x00F3F3F3U;
|
||||||
|
title_fg = (active != 0) ? UWM_COLOR_WHITE : UWM_COLOR_TEXT;
|
||||||
|
|
||||||
|
ush_uwm_fill_rect(win, 0, 0, win->w, win->h, UWM_COLOR_LIGHT_BG);
|
||||||
|
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) {
|
||||||
|
ush_uwm_draw_text(win, win->w - (USH_UWM_CONTROL_W * 3) - 18, 12, "^", 1, title_fg);
|
||||||
|
}
|
||||||
|
ush_uwm_draw_window_controls(win, active);
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
ush_uwm_render_files(win);
|
||||||
|
} else if (index == 1) {
|
||||||
|
ush_uwm_render_editor(win);
|
||||||
|
} else {
|
||||||
|
ush_uwm_render_browser(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int search_w;
|
||||||
|
int app_x;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskbar = &sess->windows[USH_UWM_TASKBAR_INDEX];
|
||||||
|
ush_uwm_gradient_rect(taskbar, 0, 0, taskbar->w, taskbar->h, 0x00252525U, 0x001A1A1AU);
|
||||||
|
ush_uwm_fill_rect(taskbar, 0, 0, taskbar->w, 1, 0x004A4A4AU);
|
||||||
|
ush_uwm_fill_rect(taskbar, 0, 0, USH_UWM_TASKBAR_START_W, taskbar->h,
|
||||||
|
sess->start_open ? UWM_COLOR_WIN_BLUE : UWM_COLOR_DARKER);
|
||||||
|
ush_uwm_draw_windows_logo(taskbar, 15, 12, 16, UWM_COLOR_WHITE);
|
||||||
|
|
||||||
|
search_w = USH_UWM_TASKBAR_SEARCH_W;
|
||||||
|
if (taskbar->w < 720) {
|
||||||
|
search_w = 128;
|
||||||
|
}
|
||||||
|
if (taskbar->w < 520) {
|
||||||
|
search_w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_x = USH_UWM_TASKBAR_START_W + 8;
|
||||||
|
if (search_w > 0) {
|
||||||
|
ush_uwm_fill_rect(taskbar, app_x, 6, search_w, taskbar->h - 12, 0x00303030U);
|
||||||
|
ush_uwm_stroke_rect(taskbar, app_x, 6, search_w, taskbar->h - 12, 0x00484848U);
|
||||||
|
ush_uwm_draw_text_limit(taskbar, app_x + 12, 17, "TYPE HERE TO SEARCH", 1, 0x00C8C8C8U, app_x + search_w - 8);
|
||||||
|
app_x += search_w + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
|
ush_uwm_window *app = &sess->windows[i];
|
||||||
|
ush_uwm_u32 bg = 0x00282828U;
|
||||||
|
ush_uwm_u32 fg = 0x00EAEAEAU;
|
||||||
|
int active = 0;
|
||||||
|
|
||||||
|
if (app_x + USH_UWM_TASKBAR_BUTTON_W > taskbar->w - 98) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app->closed != 0) {
|
||||||
|
bg = 0x001F1F1FU;
|
||||||
|
fg = 0x007C7C7CU;
|
||||||
|
} else if (app->minimized != 0) {
|
||||||
|
bg = 0x002F2F2FU;
|
||||||
|
} else if (sess->active_window == i) {
|
||||||
|
bg = 0x00383838U;
|
||||||
|
active = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_draw_button(taskbar, app_x, 5, USH_UWM_TASKBAR_BUTTON_W, taskbar->h - 10, app->title, bg, fg, active);
|
||||||
|
app_x += USH_UWM_TASKBAR_BUTTON_W + USH_UWM_TASKBAR_BUTTON_GAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskbar->w > 260) {
|
||||||
|
ush_uwm_draw_text(taskbar, taskbar->w - 86, 11, "CLKS", 1, UWM_COLOR_WHITE);
|
||||||
|
ush_uwm_draw_text(taskbar, taskbar->w - 86, 24, "UWM", 1, 0x00CFCFCFU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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"};
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = &sess->windows[USH_UWM_START_INDEX];
|
||||||
|
ush_uwm_gradient_rect(start, 0, 0, start->w, start->h, 0x00292929U, 0x001E1E1EU);
|
||||||
|
ush_uwm_fill_rect(start, 0, 0, 52, start->h, 0x00191919U);
|
||||||
|
ush_uwm_draw_windows_logo(start, 16, start->h - 34, 18, UWM_COLOR_WHITE);
|
||||||
|
ush_uwm_draw_text(start, 68, 20, "CLEONOS", 2, UWM_COLOR_WHITE);
|
||||||
|
ush_uwm_draw_text(start, 70, 48, "START", 1, 0x00BDBDBDU);
|
||||||
|
|
||||||
|
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
|
||||||
|
int y = 78 + (i * 44);
|
||||||
|
ush_uwm_u32 bg = (sess->active_window == i && sess->windows[i].closed == 0 && sess->windows[i].minimized == 0)
|
||||||
|
? 0x003B3B3BU
|
||||||
|
: 0x00272727U;
|
||||||
|
if (y + 34 > start->h - 76) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ush_uwm_fill_rect(start, 66, y, start->w - 82, 34, bg);
|
||||||
|
ush_uwm_fill_rect(start, 66, y, 4, 34, sess->windows[i].accent);
|
||||||
|
ush_uwm_draw_text_limit(start, 82, y + 10, labels[i], 1, UWM_COLOR_WHITE, start->w - 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start->w > 248 && start->h > 260) {
|
||||||
|
int tile_y = start->h - 68;
|
||||||
|
int tile_w = (start->w - 88) / 2;
|
||||||
|
ush_uwm_fill_rect(start, 66, tile_y, tile_w, 48, UWM_COLOR_WIN_BLUE);
|
||||||
|
ush_uwm_draw_text(start, 78, tile_y + 18, "SETTINGS", 1, UWM_COLOR_WHITE);
|
||||||
|
ush_uwm_fill_rect(start, 74 + tile_w, tile_y, tile_w, 48, 0x0000A300U);
|
||||||
|
ush_uwm_draw_text(start, 86 + tile_w, tile_y + 18, "TERMINAL", 1, UWM_COLOR_WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_render_window(ush_uwm_session *sess, int index) {
|
||||||
|
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sess->windows[index].pixels == (ush_uwm_u32 *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sess->windows[index].kind == USH_UWM_KIND_TASKBAR) {
|
||||||
|
ush_uwm_render_taskbar(sess);
|
||||||
|
} else if (sess->windows[index].kind == USH_UWM_KIND_START) {
|
||||||
|
ush_uwm_render_start(sess);
|
||||||
|
} else {
|
||||||
|
ush_uwm_render_app_window(sess, index);
|
||||||
|
}
|
||||||
|
sess->windows[index].dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_refresh_window(ush_uwm_session *sess, int index) {
|
||||||
|
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0 || sess->windows[index].alive == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_render_window(sess, index);
|
||||||
|
(void)ush_uwm_present_window(&sess->windows[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_refresh_taskbar(ush_uwm_session *sess) {
|
||||||
|
ush_uwm_refresh_window(sess, USH_UWM_TASKBAR_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
int ush_uwm_alloc_pixels(ush_uwm_window *win) {
|
int ush_uwm_alloc_pixels(ush_uwm_window *win) {
|
||||||
|
return (win == (ush_uwm_window *)0) ? 0 : ush_uwm_replace_pixels(win, win->w, win->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ush_uwm_replace_pixels(ush_uwm_window *win, int width, int height) {
|
||||||
u64 count;
|
u64 count;
|
||||||
u64 bytes;
|
u64 bytes;
|
||||||
|
ush_uwm_u32 *new_pixels;
|
||||||
|
|
||||||
if (win == (ush_uwm_window *)0 || win->w <= 0 || win->h <= 0) {
|
if (win == (ush_uwm_window *)0 || width <= 0 || height <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = (u64)(unsigned int)win->w * (u64)(unsigned int)win->h;
|
count = (u64)(unsigned int)width * (u64)(unsigned int)height;
|
||||||
if (count == 0ULL || count > (((u64)-1) / 4ULL)) {
|
if (count == 0ULL || count > (((u64)-1) / 4ULL)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes = count * 4ULL;
|
bytes = count * 4ULL;
|
||||||
win->pixels = (ush_uwm_u32 *)malloc((size_t)bytes);
|
new_pixels = (ush_uwm_u32 *)malloc((size_t)bytes);
|
||||||
if (win->pixels == (ush_uwm_u32 *)0) {
|
if (new_pixels == (ush_uwm_u32 *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (win->pixels != (ush_uwm_u32 *)0) {
|
||||||
|
free(win->pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
win->pixels = new_pixels;
|
||||||
win->pixel_count = count;
|
win->pixel_count = count;
|
||||||
|
win->w = width;
|
||||||
|
win->h = height;
|
||||||
ush_zero(win->pixels, bytes);
|
ush_zero(win->pixels, bytes);
|
||||||
|
win->dirty = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +623,7 @@ int ush_uwm_create_window(ush_uwm_window *win) {
|
|||||||
req.y = (u64)(i64)win->y;
|
req.y = (u64)(i64)win->y;
|
||||||
req.width = (u64)(unsigned int)win->w;
|
req.width = (u64)(unsigned int)win->w;
|
||||||
req.height = (u64)(unsigned int)win->h;
|
req.height = (u64)(unsigned int)win->h;
|
||||||
req.flags = 0ULL;
|
req.flags = (win->topmost != 0) ? USH_UWM_WM_FLAG_TOPMOST : 0ULL;
|
||||||
win->id = cleonos_sys_wm_create(&req);
|
win->id = cleonos_sys_wm_create(&req);
|
||||||
if (win->id == 0ULL) {
|
if (win->id == 0ULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -125,7 +648,7 @@ int ush_uwm_present_window(const ush_uwm_window *win) {
|
|||||||
return (cleonos_sys_wm_present(&req) != 0ULL) ? 1 : 0;
|
return (cleonos_sys_wm_present(&req) != 0ULL) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ush_uwm_destroy_window(ush_uwm_window *win) {
|
void ush_uwm_destroy_kernel_window(ush_uwm_window *win) {
|
||||||
if (win == (ush_uwm_window *)0) {
|
if (win == (ush_uwm_window *)0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,14 +657,25 @@ void ush_uwm_destroy_window(ush_uwm_window *win) {
|
|||||||
(void)cleonos_sys_wm_destroy(win->id);
|
(void)cleonos_sys_wm_destroy(win->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win->id = 0ULL;
|
||||||
|
win->alive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_destroy_window(ush_uwm_window *win) {
|
||||||
|
if (win == (ush_uwm_window *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_destroy_kernel_window(win);
|
||||||
if (win->pixels != (ush_uwm_u32 *)0) {
|
if (win->pixels != (ush_uwm_u32 *)0) {
|
||||||
free(win->pixels);
|
free(win->pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
win->id = 0ULL;
|
|
||||||
win->pixels = (ush_uwm_u32 *)0;
|
win->pixels = (ush_uwm_u32 *)0;
|
||||||
win->pixel_count = 0ULL;
|
win->pixel_count = 0ULL;
|
||||||
win->alive = 0;
|
win->minimized = 0;
|
||||||
|
win->closed = 1;
|
||||||
|
win->dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x, int target_y) {
|
int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x, int target_y) {
|
||||||
@@ -152,26 +686,29 @@ int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x,
|
|||||||
int new_x;
|
int new_x;
|
||||||
int new_y;
|
int new_y;
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0) {
|
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
win = &sess->windows[index];
|
win = &sess->windows[index];
|
||||||
if (win->alive == 0 || win->id == 0ULL) {
|
if (win->alive == 0 || win->id == 0ULL || win->closed != 0 || win->minimized != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
max_x = sess->screen_w - win->w;
|
max_x = sess->screen_w - win->w;
|
||||||
max_y = sess->screen_h - win->h;
|
max_y = ush_uwm_work_bottom(sess) - win->h;
|
||||||
if (max_x < 0) {
|
if (max_x < 0) {
|
||||||
max_x = 0;
|
max_x = 0;
|
||||||
}
|
}
|
||||||
if (max_y < 0) {
|
if (max_y < USH_UWM_TOP_CLAMP_Y) {
|
||||||
max_y = 0;
|
max_y = USH_UWM_TOP_CLAMP_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_x = ush_uwm_clampi(target_x, 0, max_x);
|
new_x = ush_uwm_clampi(target_x, 0, max_x);
|
||||||
new_y = ush_uwm_clampi(target_y, USH_UWM_TOP_CLAMP_Y, max_y);
|
new_y = ush_uwm_clampi(target_y, USH_UWM_TOP_CLAMP_Y, max_y);
|
||||||
|
if (new_x == win->x && new_y == win->y) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
req.window_id = win->id;
|
req.window_id = win->id;
|
||||||
req.x = (u64)(i64)new_x;
|
req.x = (u64)(i64)new_x;
|
||||||
@@ -185,20 +722,96 @@ int ush_uwm_window_move_clamped(ush_uwm_session *sess, int index, int target_x,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ush_uwm_window_resize(ush_uwm_session *sess, int index, int target_w, int target_h) {
|
||||||
|
ush_uwm_window *win;
|
||||||
|
cleonos_wm_resize_req req;
|
||||||
|
ush_uwm_u32 *new_pixels;
|
||||||
|
u64 count;
|
||||||
|
u64 bytes;
|
||||||
|
int max_w;
|
||||||
|
int max_h;
|
||||||
|
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->alive == 0 || win->id == 0ULL || win->closed != 0 || win->minimized != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_w = sess->screen_w - win->x;
|
||||||
|
max_h = ush_uwm_work_bottom(sess) - win->y;
|
||||||
|
if (max_w < USH_UWM_MIN_WINDOW_W) {
|
||||||
|
max_w = USH_UWM_MIN_WINDOW_W;
|
||||||
|
}
|
||||||
|
if (max_h < USH_UWM_MIN_WINDOW_H) {
|
||||||
|
max_h = USH_UWM_MIN_WINDOW_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_w = ush_uwm_clampi(target_w, USH_UWM_MIN_WINDOW_W, max_w);
|
||||||
|
new_h = ush_uwm_clampi(target_h, USH_UWM_MIN_WINDOW_H, max_h);
|
||||||
|
if (new_w == win->w && new_h == win->h) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = (u64)(unsigned int)new_w * (u64)(unsigned int)new_h;
|
||||||
|
if (count == 0ULL || count > (((u64)-1) / 4ULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = count * 4ULL;
|
||||||
|
new_pixels = (ush_uwm_u32 *)malloc((size_t)bytes);
|
||||||
|
if (new_pixels == (ush_uwm_u32 *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ush_zero(new_pixels, bytes);
|
||||||
|
|
||||||
|
req.window_id = win->id;
|
||||||
|
req.width = (u64)(unsigned int)new_w;
|
||||||
|
req.height = (u64)(unsigned int)new_h;
|
||||||
|
if (cleonos_sys_wm_resize(&req) == 0ULL) {
|
||||||
|
free(new_pixels);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win->pixels != (ush_uwm_u32 *)0) {
|
||||||
|
free(win->pixels);
|
||||||
|
}
|
||||||
|
win->pixels = new_pixels;
|
||||||
|
win->pixel_count = count;
|
||||||
|
win->w = new_w;
|
||||||
|
win->h = new_h;
|
||||||
|
win->dirty = 1;
|
||||||
|
|
||||||
|
ush_uwm_render_window(sess, index);
|
||||||
|
(void)ush_uwm_present_window(win);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void ush_uwm_set_active(ush_uwm_session *sess, int index) {
|
void ush_uwm_set_active(ush_uwm_session *sess, int index) {
|
||||||
ush_uwm_window *win;
|
ush_uwm_window *win;
|
||||||
|
int old_active;
|
||||||
|
|
||||||
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0) {
|
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
win = &sess->windows[index];
|
win = &sess->windows[index];
|
||||||
if (win->alive == 0 || win->id == 0ULL) {
|
if (win->alive == 0 || win->id == 0ULL || win->closed != 0 || win->minimized != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_active = sess->active_window;
|
||||||
if (cleonos_sys_wm_set_focus(win->id) != 0ULL) {
|
if (cleonos_sys_wm_set_focus(win->id) != 0ULL) {
|
||||||
sess->active_window = index;
|
sess->active_window = index;
|
||||||
|
if (ush_uwm_app_index_valid(old_active) != 0 && old_active != index) {
|
||||||
|
ush_uwm_refresh_window(sess, old_active);
|
||||||
|
}
|
||||||
|
ush_uwm_refresh_window(sess, index);
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,17 +823,149 @@ void ush_uwm_focus_next(ush_uwm_session *sess) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ush_uwm_window_index_valid(sess->active_window) != 0) {
|
start = (ush_uwm_app_index_valid(sess->active_window) != 0) ? sess->active_window : 0;
|
||||||
start = sess->active_window;
|
for (i = 1; i <= (int)USH_UWM_APP_COUNT; i++) {
|
||||||
} else {
|
int idx = (start + i) % (int)USH_UWM_APP_COUNT;
|
||||||
start = 0;
|
if (sess->windows[idx].alive != 0 && sess->windows[idx].minimized == 0 && sess->windows[idx].closed == 0) {
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i <= (int)USH_UWM_WINDOW_COUNT; i++) {
|
|
||||||
int idx = (start + i) % (int)USH_UWM_WINDOW_COUNT;
|
|
||||||
if (sess->windows[idx].alive != 0) {
|
|
||||||
ush_uwm_set_active(sess, idx);
|
ush_uwm_set_active(sess, idx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sess->active_window = -1;
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_minimize_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[index];
|
||||||
|
if (win->alive == 0 || win->closed != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_uwm_destroy_kernel_window(win);
|
||||||
|
win->minimized = 1;
|
||||||
|
if (sess->active_window == index) {
|
||||||
|
ush_uwm_focus_next(sess);
|
||||||
|
}
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_close_window(ush_uwm_session *sess, int index) {
|
||||||
|
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;
|
||||||
|
if (sess->active_window == index) {
|
||||||
|
ush_uwm_focus_next(sess);
|
||||||
|
}
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_restore_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[index];
|
||||||
|
if (win->alive != 0) {
|
||||||
|
win->closed = 0;
|
||||||
|
win->minimized = 0;
|
||||||
|
ush_uwm_set_active(sess, index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win->pixels == (ush_uwm_u32 *)0 && ush_uwm_alloc_pixels(win) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win->closed = 0;
|
||||||
|
win->minimized = 0;
|
||||||
|
ush_uwm_render_window(sess, index);
|
||||||
|
if (ush_uwm_create_window(win) == 0) {
|
||||||
|
win->closed = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void)ush_uwm_present_window(win);
|
||||||
|
ush_uwm_set_active(sess, index);
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_toggle_topmost(ush_uwm_session *sess, int index) {
|
||||||
|
ush_uwm_window *win;
|
||||||
|
u64 flags;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0 || ush_uwm_app_index_valid(index) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = &sess->windows[index];
|
||||||
|
if (win->id == 0ULL || win->alive == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win->topmost = (win->topmost == 0) ? 1 : 0;
|
||||||
|
flags = (win->topmost != 0) ? USH_UWM_WM_FLAG_TOPMOST : 0ULL;
|
||||||
|
(void)cleonos_sys_wm_set_flags(win->id, flags);
|
||||||
|
ush_uwm_refresh_window(sess, index);
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_close_start(ush_uwm_session *sess) {
|
||||||
|
ush_uwm_window *start;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = &sess->windows[USH_UWM_START_INDEX];
|
||||||
|
if (start->alive != 0) {
|
||||||
|
ush_uwm_destroy_kernel_window(start);
|
||||||
|
}
|
||||||
|
sess->start_open = 0;
|
||||||
|
start->closed = 1;
|
||||||
|
if (ush_uwm_app_index_valid(sess->active_window) != 0 && sess->windows[sess->active_window].alive != 0) {
|
||||||
|
(void)cleonos_sys_wm_set_focus(sess->windows[sess->active_window].id);
|
||||||
|
}
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_uwm_toggle_start(ush_uwm_session *sess) {
|
||||||
|
ush_uwm_window *start;
|
||||||
|
|
||||||
|
if (sess == (ush_uwm_session *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = &sess->windows[USH_UWM_START_INDEX];
|
||||||
|
if (start->alive != 0) {
|
||||||
|
ush_uwm_close_start(sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start->pixels == (ush_uwm_u32 *)0 && ush_uwm_alloc_pixels(start) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->start_open = 1;
|
||||||
|
start->closed = 0;
|
||||||
|
ush_uwm_render_window(sess, USH_UWM_START_INDEX);
|
||||||
|
if (ush_uwm_create_window(start) == 0) {
|
||||||
|
sess->start_open = 0;
|
||||||
|
start->closed = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void)ush_uwm_present_window(start);
|
||||||
|
(void)cleonos_sys_wm_set_focus(start->id);
|
||||||
|
ush_uwm_refresh_taskbar(sess);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,9 +60,11 @@ typedef struct cleonos_mouse_state {
|
|||||||
|
|
||||||
#define CLEONOS_WM_EVENT_FOCUS_GAINED 1ULL
|
#define CLEONOS_WM_EVENT_FOCUS_GAINED 1ULL
|
||||||
#define CLEONOS_WM_EVENT_FOCUS_LOST 2ULL
|
#define CLEONOS_WM_EVENT_FOCUS_LOST 2ULL
|
||||||
#define CLEONOS_WM_EVENT_KEY 3ULL
|
#define CLEONOS_WM_EVENT_KEY 3ULL
|
||||||
#define CLEONOS_WM_EVENT_MOUSE_MOVE 4ULL
|
#define CLEONOS_WM_EVENT_MOUSE_MOVE 4ULL
|
||||||
#define CLEONOS_WM_EVENT_MOUSE_BUTTON 5ULL
|
#define CLEONOS_WM_EVENT_MOUSE_BUTTON 5ULL
|
||||||
|
|
||||||
|
#define CLEONOS_WM_FLAG_TOPMOST 0x1ULL
|
||||||
|
|
||||||
typedef struct cleonos_wm_event {
|
typedef struct cleonos_wm_event {
|
||||||
u64 type;
|
u64 type;
|
||||||
@@ -88,11 +90,17 @@ typedef struct cleonos_wm_present_req {
|
|||||||
u64 src_pitch_bytes;
|
u64 src_pitch_bytes;
|
||||||
} cleonos_wm_present_req;
|
} cleonos_wm_present_req;
|
||||||
|
|
||||||
typedef struct cleonos_wm_move_req {
|
typedef struct cleonos_wm_move_req {
|
||||||
u64 window_id;
|
u64 window_id;
|
||||||
u64 x;
|
u64 x;
|
||||||
u64 y;
|
u64 y;
|
||||||
} cleonos_wm_move_req;
|
} cleonos_wm_move_req;
|
||||||
|
|
||||||
|
typedef struct cleonos_wm_resize_req {
|
||||||
|
u64 window_id;
|
||||||
|
u64 width;
|
||||||
|
u64 height;
|
||||||
|
} cleonos_wm_resize_req;
|
||||||
|
|
||||||
typedef struct cleonos_fb_blit_req {
|
typedef struct cleonos_fb_blit_req {
|
||||||
u64 pixels_ptr;
|
u64 pixels_ptr;
|
||||||
@@ -250,9 +258,11 @@ typedef struct cleonos_net_tcp_recv_req {
|
|||||||
#define CLEONOS_SYSCALL_WM_CREATE 108ULL
|
#define CLEONOS_SYSCALL_WM_CREATE 108ULL
|
||||||
#define CLEONOS_SYSCALL_WM_DESTROY 109ULL
|
#define CLEONOS_SYSCALL_WM_DESTROY 109ULL
|
||||||
#define CLEONOS_SYSCALL_WM_PRESENT 110ULL
|
#define CLEONOS_SYSCALL_WM_PRESENT 110ULL
|
||||||
#define CLEONOS_SYSCALL_WM_POLL_EVENT 111ULL
|
#define CLEONOS_SYSCALL_WM_POLL_EVENT 111ULL
|
||||||
#define CLEONOS_SYSCALL_WM_MOVE 112ULL
|
#define CLEONOS_SYSCALL_WM_MOVE 112ULL
|
||||||
#define CLEONOS_SYSCALL_WM_SET_FOCUS 113ULL
|
#define CLEONOS_SYSCALL_WM_SET_FOCUS 113ULL
|
||||||
|
#define CLEONOS_SYSCALL_WM_SET_FLAGS 114ULL
|
||||||
|
#define CLEONOS_SYSCALL_WM_RESIZE 115ULL
|
||||||
|
|
||||||
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
u64 cleonos_sys_log_write(const char *message, u64 length);
|
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||||
@@ -366,8 +376,10 @@ u64 cleonos_sys_mouse_state(cleonos_mouse_state *out_state);
|
|||||||
u64 cleonos_sys_wm_create(const cleonos_wm_create_req *req);
|
u64 cleonos_sys_wm_create(const cleonos_wm_create_req *req);
|
||||||
u64 cleonos_sys_wm_destroy(u64 window_id);
|
u64 cleonos_sys_wm_destroy(u64 window_id);
|
||||||
u64 cleonos_sys_wm_present(const cleonos_wm_present_req *req);
|
u64 cleonos_sys_wm_present(const cleonos_wm_present_req *req);
|
||||||
u64 cleonos_sys_wm_poll_event(u64 window_id, cleonos_wm_event *out_event);
|
u64 cleonos_sys_wm_poll_event(u64 window_id, cleonos_wm_event *out_event);
|
||||||
u64 cleonos_sys_wm_move(const cleonos_wm_move_req *req);
|
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_focus(u64 window_id);
|
||||||
|
u64 cleonos_sys_wm_set_flags(u64 window_id, u64 flags);
|
||||||
#endif
|
u64 cleonos_sys_wm_resize(const cleonos_wm_resize_req *req);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ unsigned long long strtoull(const char *text, char **out_end, int base) {
|
|||||||
return (unsigned long long)strtoul(text, out_end, base);
|
return (unsigned long long)strtoul(text, out_end, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CLIB_HEAP_CAPACITY (4U * 1024U * 1024U)
|
#ifndef CLIB_HEAP_CAPACITY
|
||||||
|
#define CLIB_HEAP_CAPACITY (2U * 1024U * 1024U)
|
||||||
|
#endif
|
||||||
#define CLIB_HEAP_ALIGN 8U
|
#define CLIB_HEAP_ALIGN 8U
|
||||||
|
|
||||||
typedef union clib_heap_storage {
|
typedef union clib_heap_storage {
|
||||||
|
|||||||
@@ -484,6 +484,14 @@ u64 cleonos_sys_wm_move(const cleonos_wm_move_req *req) {
|
|||||||
return cleonos_syscall(CLEONOS_SYSCALL_WM_MOVE, (u64)req, 0ULL, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_WM_MOVE, (u64)req, 0ULL, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 cleonos_sys_wm_set_focus(u64 window_id) {
|
u64 cleonos_sys_wm_set_focus(u64 window_id) {
|
||||||
return cleonos_syscall(CLEONOS_SYSCALL_WM_SET_FOCUS, window_id, 0ULL, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_WM_SET_FOCUS, window_id, 0ULL, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_wm_set_flags(u64 window_id, u64 flags) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_WM_SET_FLAGS, window_id, flags, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_wm_resize(const cleonos_wm_resize_req *req) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_WM_RESIZE, (u64)req, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|||||||
2
clks
2
clks
Submodule clks updated: 44d89fd3f7...a0202d15b1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
- Add a minimal user-space desktop environment entrypoint.
|
- Add a minimal user-space desktop environment entrypoint.
|
||||||
- Provide a simple window manager demo (`uwm`) with focus, dragging, and rendering in framebuffer.
|
- Provide a usable user-space window manager (`uwm`) with focus, dragging, resize, taskbar, and launcher.
|
||||||
- Expose mouse snapshot data to user-space through a dedicated syscall.
|
- Expose mouse snapshot data to user-space through a dedicated syscall.
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
@@ -11,28 +11,36 @@
|
|||||||
- Kernel side (`clks/kernel/runtime/syscall.c`) now exports mouse snapshot:
|
- Kernel side (`clks/kernel/runtime/syscall.c`) now exports mouse snapshot:
|
||||||
- fields: `x`, `y`, `buttons`, `packet_count`, `ready`.
|
- fields: `x`, `y`, `buttons`, `packet_count`, `ready`.
|
||||||
- User wrapper added: `cleonos_sys_mouse_state()`.
|
- User wrapper added: `cleonos_sys_mouse_state()`.
|
||||||
|
- Window protocol update:
|
||||||
|
- Added `WM_SET_FLAGS` (`id=114`) for `CLEONOS_WM_FLAG_TOPMOST`.
|
||||||
|
- Added `WM_RESIZE` (`id=115`) so resize keeps the same `window_id`.
|
||||||
- New user app:
|
- New user app:
|
||||||
- Added `cleonos/c/apps/uwm_main.c`.
|
- Added `cleonos/c/apps/uwm_main.c`.
|
||||||
- Features:
|
- Features:
|
||||||
- Desktop background rendering.
|
- Bottom taskbar with window buttons.
|
||||||
|
- Start launcher menu for built-in demo windows.
|
||||||
- Multiple windows with z-order.
|
- Multiple windows with z-order.
|
||||||
|
- Title bar with close, minimize, topmost, and resize controls.
|
||||||
- Active window focus + border highlight.
|
- Active window focus + border highlight.
|
||||||
- Drag by title bar (left mouse).
|
- Drag by title bar (left mouse).
|
||||||
- Keyboard fallback controls (`Tab`, `W/A/S/D`, `Q/Esc`).
|
- Keyboard fallback controls (`Tab`, `1/2/3`, `W/A/S/D`, `M`, `X`, `T`, `+/-`, `Q`).
|
||||||
- Build integration:
|
- Build integration:
|
||||||
- Added `uwm` into shell command app set in `cleonos/CMakeLists.txt`.
|
- Added `uwm` into shell command app set in `cleonos/CMakeLists.txt`.
|
||||||
- Updated shell help text and standalone `help` app output.
|
- Updated shell help text and standalone `help` app output.
|
||||||
- QEMU run/debug update:
|
- QEMU run/debug update:
|
||||||
- Added optional absolute pointer device by default:
|
- QEMU now keeps the default PS/2 mouse path enabled for `make run`/`make debug`.
|
||||||
|
- USB tablet is optional and disabled by default because the kernel currently has a PS/2 mouse driver, not a USB HID tablet driver.
|
||||||
|
- Optional absolute pointer device:
|
||||||
- `-usb -device usb-tablet`
|
- `-usb -device usb-tablet`
|
||||||
- New CMake option:
|
- New CMake option:
|
||||||
- `CLEONOS_QEMU_ENABLE_USB_TABLET=ON` (default).
|
- `CLEONOS_QEMU_ENABLE_USB_TABLET=OFF` (default).
|
||||||
|
- Set it to `ON` only after USB HID tablet support is available.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
- `uwm` can be started from user shell.
|
- `uwm` can be started from user shell.
|
||||||
- Framebuffer window demo draws multiple windows and supports dragging.
|
- UWM draws multiple windows, taskbar, and launcher, and supports dragging, minimize/restore, topmost, close, and resize.
|
||||||
- Mouse state is retrievable from user-space via syscall `107`.
|
- Mouse state is retrievable from user-space via syscall `107`.
|
||||||
- `make run`/`make debug` use USB tablet by default for smoother pointer interaction.
|
- `make run`/`make debug` use the PS/2 mouse path by default so the existing kernel mouse driver receives movement and buttons.
|
||||||
|
|
||||||
## Build Targets
|
## Build Targets
|
||||||
- `make userapps`
|
- `make userapps`
|
||||||
@@ -45,8 +53,8 @@
|
|||||||
## Debug Notes
|
## Debug Notes
|
||||||
- If `uwm` reports framebuffer unavailable:
|
- If `uwm` reports framebuffer unavailable:
|
||||||
- verify `FB_INFO` syscall is enabled and framebuffer bpp is `32`.
|
- verify `FB_INFO` syscall is enabled and framebuffer bpp is `32`.
|
||||||
- If pointer behavior is relative/jumpy:
|
- If the UWM cursor does not move under QEMU:
|
||||||
- keep `CLEONOS_QEMU_ENABLE_USB_TABLET=ON`.
|
- keep `CLEONOS_QEMU_ENABLE_USB_TABLET=OFF`.
|
||||||
- for manual QEMU invocation, include `-usb -device usb-tablet`.
|
- for manual QEMU invocation, do not include `-usb -device usb-tablet` until USB HID support exists.
|
||||||
- If mouse syscall returns `ready=0`:
|
- If mouse syscall returns `ready=0`:
|
||||||
- check boot log for PS/2 mouse init status under `[INFO][MOUSE]`.
|
- check boot log for PS/2 mouse init status under `[INFO][MOUSE]`.
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `/proc/<pid>`:指定 PID 快照文本
|
- `/proc/<pid>`:指定 PID 快照文本
|
||||||
- `/proc` 为只读;写入类 syscall 不支持。
|
- `/proc` 为只读;写入类 syscall 不支持。
|
||||||
|
|
||||||
## 4. Syscall 列表(0~113)
|
## 4. Syscall 列表(0~115)
|
||||||
|
|
||||||
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
||||||
|
|
||||||
@@ -870,6 +870,23 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `arg0`: `u64 window_id`
|
- `arg0`: `u64 window_id`
|
||||||
- 返回:成功 `1`,失败 `0`
|
- 返回:成功 `1`,失败 `0`
|
||||||
- 说明:将目标窗口置为焦点并提升到顶层 z-order。
|
- 说明:将目标窗口置为焦点并提升到顶层 z-order。
|
||||||
|
|
||||||
|
### 114 `CLEONOS_SYSCALL_WM_SET_FLAGS`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `u64 window_id`
|
||||||
|
- `arg1`: `u64 flags`
|
||||||
|
- 返回:成功 `1`,失败 `0`
|
||||||
|
- 说明:
|
||||||
|
- 设置窗口协议标志;当前支持 `CLEONOS_WM_FLAG_TOPMOST`(`bit0`),置位后窗口保持在普通窗口之上。
|
||||||
|
|
||||||
|
### 115 `CLEONOS_SYSCALL_WM_RESIZE`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `const struct { u64 window_id; u64 width; u64 height; } *req`
|
||||||
|
- 返回:成功 `1`,失败 `0`
|
||||||
|
- 说明:
|
||||||
|
- 调整窗口尺寸并保持 `window_id` 不变;调整后用户态应重新 `WM_PRESENT` 一次提交新尺寸内容。
|
||||||
|
|
||||||
## 5. 用户态封装函数
|
## 5. 用户态封装函数
|
||||||
|
|
||||||
@@ -919,7 +936,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
|
|
||||||
## 7. Wine 兼容说明
|
## 7. Wine 兼容说明
|
||||||
|
|
||||||
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..113`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`、`MOUSE_STATE`、`WM_*`)。
|
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..115`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`、`MOUSE_STATE`、`WM_*`)。
|
||||||
- `DL_*`(`77..79`)在 Wine 中为“可运行兼容”实现:
|
- `DL_*`(`77..79`)在 Wine 中为“可运行兼容”实现:
|
||||||
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
|
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
|
||||||
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
|
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
|
||||||
@@ -938,7 +955,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR`(`93..94`)在 Wine 中已实现为 512B 原始扇区读写(host 文件后端)。
|
- `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR`(`93..94`)在 Wine 中已实现为 512B 原始扇区读写(host 文件后端)。
|
||||||
- 网络 syscall(`95..106`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
|
- 网络 syscall(`95..106`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
|
||||||
- `MOUSE_STATE`(`107`)在 Wine 中为基础兼容实现:可返回指针数据结构;未启用窗口鼠标事件时 `ready` 可能为 `0`。
|
- `MOUSE_STATE`(`107`)在 Wine 中为基础兼容实现:可返回指针数据结构;未启用窗口鼠标事件时 `ready` 可能为 `0`。
|
||||||
- `WM_*`(`108..113`)在 Wine 当前为兼容占位实现(统一返回 `0`);不会创建真实窗口服务。
|
- `WM_*`(`108..115`)在 Wine 当前为兼容占位实现(统一返回 `0`);不会创建真实窗口服务。
|
||||||
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
||||||
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
||||||
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。
|
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。
|
||||||
|
|||||||
2
kit
2
kit
Submodule kit updated: 58fa3d6d1a...46c6d4a547
2
wine
2
wine
Submodule wine updated: b85078cb54...c31867a23a
Reference in New Issue
Block a user