Begin move to k3Menu

This commit is contained in:
Mid 2025-07-06 17:58:57 +03:00
parent c4d808833a
commit 93b885cb43
12 changed files with 410 additions and 547 deletions

View File

@ -199,37 +199,6 @@ foundStart:
return len;
}
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
// I don't like this.
// Biggest ugly by far is how it operates in 512-byte chunks, even though lean_read_inode already handles unaligned access
uint64_t find_child(const struct INode *node, const Str16 *name) {

View File

@ -74,6 +74,34 @@ static inline unsigned char std_bytecomp(size_t len, const void *one_, const voi
#define std_min(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a<_b?_a:_b;})
#define std_max(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a>_b?_a:_b;})
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
//#define S16_ARG(str) ((Str16*) &(struct {uint16_t len; char content[sizeof(str) - 1]}) {sizeof(str) - 1, (str)})
#endif

View File

@ -4,8 +4,13 @@
#include<stdint.h>
typedef enum {
LUMA_VID_COMMAND_END = 0, LUMA_VID_COMMAND_CLEAR = 1, LUMA_VID_COMMAND_RECT = 2, LUMA_VID_COMMAND_IMAGE = 3, LUMA_VID_COMMAND_IMAGE_NEW = 4, LUMA_VID_COMMAND_SET_COLOR_FLAT = 5,
LUMA_VID_COMMAND_SET_COLOR_GRAD = 6, LUMA_VID_COMMAND_IMAGE_DEL = 7, LUMA_VID_COMMAND_TEXT = 8, LUMA_VID_COMMAND_NEW_COLOR_FLAT = 9, LUMA_VID_COMMAND_NEW_COLOR_GRAD = 10, LUMA_VID_COMMAND_IMAGE_WRITE = 11,
LUMA_VID_COMMAND_END = 0, LUMA_VID_COMMAND_CLEAR = 1,
LUMA_VID_COMMAND_RECT = 2, LUMA_VID_COMMAND_IMAGE = 3,
LUMA_VID_COMMAND_IMAGE_NEW = 4, LUMA_VID_COMMAND_SET_COLOR_FLAT = 5,
LUMA_VID_COMMAND_SET_COLOR_GRAD = 6, LUMA_VID_COMMAND_IMAGE_DEL = 7,
LUMA_VID_COMMAND_TEXT = 8, LUMA_VID_COMMAND_NEW_COLOR_FLAT = 9,
LUMA_VID_COMMAND_NEW_COLOR_GRAD = 10, LUMA_VID_COMMAND_IMAGE_WRITE = 11,
LUMA_VID_COMMAND_TEXT_EXTENT = 12
} LumaVidCommandOp;
typedef enum {
@ -19,6 +24,12 @@ typedef enum {
LUMA_VID_ALIGN_BOTTOM_RIGHT = 3,
} LumaVidAlign;
typedef enum {
LUMA_VID_TEXT_ALIGN_LEFT = 0,
LUMA_VID_TEXT_ALIGN_CENTER = 1,
LUMA_VID_TEXT_ALIGN_RIGHT = 2,
} LumaVidTextAlign;
typedef union {
uint8_t op;
struct {
@ -73,6 +84,7 @@ typedef union {
uint16_t x;
uint16_t len;
uint16_t wall;
uint8_t align;
uint8_t data[];
} __attribute__((packed)) text;
struct {
@ -83,6 +95,14 @@ typedef union {
uint16_t len;
uint8_t data[];
} __attribute__((packed)) imageWrite;
struct {
uint8_t op;
uint16_t h;
uint16_t w;
uint16_t len;
uint16_t wall;
uint8_t data[];
} __attribute__((packed)) textExtent;
} __attribute__((packed)) LumaVidCommand;
#endif

View File

@ -129,10 +129,7 @@ __attribute__((optimize("Ofast"))) static void image(Image *img, uint16_t subX,
}
}
__attribute__((optimize("Ofast"))) static void text(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall) {
if(wall <= x) wall = 320;
static const uint8_t font[] = {
static const uint8_t font[] = {
0x20, 0x31, 0x95, 0x00, 0x21, 0x17, 0x15, 0x5f, 0x22, 0x32, 0x15, 0x2d,
0x23, 0x47, 0x15, 0xaa, 0xaf, 0x5f, 0x05, 0x24, 0x48, 0x15, 0x5e, 0x65,
0xcc, 0x47, 0x25, 0x57, 0x15, 0x6b, 0x1d, 0xc2, 0xb5, 0x06, 0x26, 0x57,
@ -183,9 +180,9 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
0x79, 0x47, 0x35, 0xa9, 0x4a, 0x44, 0x03, 0x7a, 0x45, 0x35, 0x4f, 0x12,
0x0f, 0x7b, 0x39, 0x15, 0x94, 0x14, 0x49, 0x04, 0x7c, 0x18, 0x15, 0xff,
0x7d, 0x39, 0x15, 0x91, 0x44, 0x49, 0x01, 0x7e, 0x52, 0x45, 0x36, 0x01
};
};
const uint8_t *find(char c) {
const uint8_t *find(char c) {
const uint8_t *a = font;
while(a - font < sizeof(font)) {
if(*a == c) {
@ -195,17 +192,49 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
}
}
return NULL;
}
__attribute__((optimize("Ofast"))) static void line_extent(const char **strp, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 13;
const char *str = *strp;
while(len--) {
if(*str == 10) {
str++;
*strp = str;
return;
}
const uint8_t *data = find(*(str++));
if(data == NULL) continue;
uint8_t width = data[2] & 0x0F;
if(*w + width >= wall) {
if(*w != 0) {
str--;
}
*strp = str;
return;
}
*w += width;
}
*strp = str;
}
__attribute__((optimize("Ofast"))) static void text_line(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall) {
if(wall <= x) wall = 320;
uint16_t startX = x;
int col = colorFunc(0, 0);
while(len--) {
if(*str == 10) {
str++;
x = startX;
y += 13;
continue;
return;
}
const uint8_t *data = find(*(str++));
@ -216,8 +245,8 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
uint8_t width = data[2] & 0x0F;
if(x + width >= wall) {
x = startX;
y += 13;
return;
}
for(int ix = 0; ix < (data[1] >> 4); ix++) {
@ -234,6 +263,53 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
}
}
__attribute__((optimize("Ofast"))) static void text_extent(const char *str, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 0;
const char *str2 = str;
while(len) {
uint16_t lineWidth = 0, lineHeight = 0;
line_extent(&str2, len, wall, &lineWidth, &lineHeight);
len = str + len - str2;
if(*w < lineWidth) {
*w = lineWidth;
}
*h += lineHeight;
}
}
__attribute__((optimize("Ofast"))) static void text(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall, uint8_t align) {
if(wall <= x) wall = 320;
uint16_t lineW, lineH;
while(len) {
const char *lineEnd = str;
line_extent(&lineEnd, len, wall, &lineW, &lineH);
if(align == LUMA_VID_TEXT_ALIGN_LEFT) {
text_line(str, len, x, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_CENTER) {
text_line(str, len, (wall + x) / 2 - lineW / 2, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_RIGHT) {
text_line(str, len, wall - lineW, y, wall);
}
if(lineEnd == str) {
break;
}
len = str + len - lineEnd;
str = lineEnd;
y += lineH;
}
}
static void compileCommandList(uint8_t *src, uint8_t *dst) {
size_t len = 0;
while(1) {
@ -410,6 +486,9 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE_DEL) {
src += sizeof(cmd->imageDel);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT) {
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.align;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.wall;
len += 4;
@ -435,7 +514,7 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
len += cmd->text.len;
dst[len++] = 0x83; /* add esp, imm8 */
dst[len++] = 0xC4;
dst[len++] = 0x14;
dst[len++] = 0x18;
src += sizeof(cmd->text) + cmd->text.len;
} else if(cmd->op == LUMA_VID_COMMAND_NEW_COLOR_FLAT) {
MiniCol minicol = ((cmd->colorFlat.r & ~7) << 8) | ((cmd->colorFlat.g & ~3) << 3) | (cmd->colorFlat.b >> 3);
@ -452,6 +531,12 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
}
q_reavg();
src += sizeof(cmd->colorGrad);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT_EXTENT) {
uint16_t w, h;
text_extent(cmd->textExtent.data, cmd->textExtent.len, cmd->textExtent.wall, &w, &h);
cmd->textExtent.w = w;
cmd->textExtent.h = h;
src += sizeof(cmd->textExtent) + cmd->textExtent.len;
}
}
}

View File

@ -10,4 +10,4 @@ mod: $(OBJECTS)
../../build/wm/%.o: %.c
mkdir -p $(@D)
i386-elf-gcc -march=i386 -Isrc -Os -pie -nodefaultlibs -nostdlib -nostartfiles -DEEBIE_MEMSET=__builtin_memset -fms-extensions -fomit-frame-pointer -c -o $@ -ffreestanding -mgeneral-regs-only -std=gnu11 -Wall $<
i386-elf-gcc -march=i386 -Isrc -Os -pie -nodefaultlibs -nostdlib -nostartfiles -DEEBIE_MEMSET=__builtin_memset -Dmalloc=tiny_malloc -Dcalloc=tiny_calloc -Dfree=tiny_free -Drealloc=tiny_realloc -fms-extensions -fomit-frame-pointer -c -o $@ -ffreestanding -mgeneral-regs-only -std=gnu11 -Wall $<

View File

@ -13,38 +13,6 @@ void ebml_reader_init(EBMLReader *this) {
static uint64_t VARINT_MASKS[] = {0, 0x80L, 0xC000L, 0xE00000L, 0xF0000000L, 0xF800000000L, 0xFC0000000000L, 0xFE000000000000L, 0L};
#include"../../std.h"
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[25] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
#define I(x) ((uint64_t)(x))
static int read_varint(const uint8_t *data, size_t length, uint64_t *result) {
if(data[0] & 0x80) {

View File

@ -8,7 +8,7 @@
#define dynstr16_ends_with(ds16, cstr) (((ds16)->len < sizeof(cstr) - 1) ? 0 : !std_bytecomp(sizeof(cstr) - 1, (cstr), (ds16)->data + (ds16)->len - sizeof(cstr) + 1))
struct Ctx {
/*struct Ctx {
Str16 *cd;
size_t cdSize;
} ;
@ -190,12 +190,12 @@ static int files_window_back_cmd(void *ud, const DynStr16 *cmdline) {
update_listing(w);
return 1;
}
}*/
void FilesWindowCreate() {
if(!is_free_space()) return;
struct GList *list = glist_new(0, 0, 0, 0);
/*struct GList *list = glist_new(0, 0, 0, 0);
static const char name[] = "File Explorer";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) list, 0);
@ -215,5 +215,5 @@ void FilesWindowCreate() {
static const char backcmd[] = "back";
gwindow_regcmd(w, g_str16_new(sizeof(backcmd) - 1, backcmd), w, files_window_back_cmd);
add_window(w);
add_window(w);*/
}

View File

@ -12,6 +12,7 @@
#include"logserver.h"
#include"progdb.h"
#include"io.h"
#include"k3menu.h"
asm("modentry:\n"
"mov $stack + 2048, %esp\n"
@ -24,37 +25,6 @@ char stack[2048];
void *VidLink;
void *FSLink;
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
void initvid(int col) {
static uint8_t logo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
@ -275,241 +245,106 @@ void drawdesk(int x, int y, int w, int h) {
sys_signal_wait(VidLink, NULL);
}
struct GContainer *ui;
struct k3MScreen *ui;
struct k3MTextInput *cmdline;
struct GObj *windowTree;
struct WTreeNode *windowTreeRoot;
struct WTreeNode *windowTreeFocus;
struct GText *cmdline;
struct WindowTree {
bool split;
union {
struct GWindow gw;
struct {
struct WindowTree *a;
struct WindowTree *b;
} sub;
};
};
struct WindowTree *windowTree = NULL;
static void focus_next() {
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 0;
}
static int dirtyX1 = INT32_MAX;
static int dirtyX2 = INT32_MIN;
static int dirtyY1 = INT32_MAX;
static int dirtyY2 = INT32_MIN;
void dirty(int x1, int y1, int w, int h) {
int x2 = x1 + w;
int y2 = y1 + h;
if(dirtyX1 > x1) {
dirtyX1 = x1;
}
if(windowTreeFocus->parent) {
if(windowTreeFocus->parent->first == windowTreeFocus) {
windowTreeFocus = windowTreeFocus->parent->second;
} else if(windowTreeFocus->parent->second == windowTreeFocus) {
if(windowTreeFocus->parent->parent) {
windowTreeFocus = windowTreeFocus->parent->parent->second;
if(dirtyX2 < x2) {
dirtyX2 = x2;
}
if(dirtyY1 > y1) {
dirtyY1 = y1;
}
if(dirtyY2 < y2) {
dirtyY2 = y2;
}
}
static struct WindowTree *find_free_space(struct WindowTree *wt) {
if(wt->split) {
if(!wt->sub.a) {
wt->sub.a = tiny_calloc(1, sizeof(*wt->sub.a));
return wt->sub.a;
} else {
windowTreeFocus = windowTreeRoot;
}
while(!windowTreeFocus->window) {
windowTreeFocus = windowTreeFocus->first;
}
}
wt = find_free_space(wt->sub.a);
if(wt) return wt;
}
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 1;
}
}
static KeyReactFunc baseinputonkey;
static void inputonkey(struct GObj *_, struct GKeyEvent ev) {
if(ev.scancode == LK_ENTER) {
struct GText *t = (void*) _;
perform(t->data);
t->data->len = 0;
cmdline->focus ^= 1;
windowTree->focus ^= 1;
dirty_obj(_);
if(!wt->sub.b) {
wt->sub.b = tiny_calloc(1, sizeof(*wt->sub.b));
return wt->sub.b;
} else {
baseinputonkey(_, ev);
wt = find_free_space(wt->sub.b);
if(wt) return wt;
}
} else if(wt->gw.whole == NULL) {
return wt;
}
return NULL;
}
static void wtree_render_recur(struct WTreeNode *node) {
if(node->window) {
if(node->window->onRender) {
node->window->onRender((struct GObj*) node->window);
}
} else {
if(node->first) wtree_render_recur(node->first);
if(node->second) wtree_render_recur(node->second);
}
}
static void wtree_render(struct GObj *this) {
wtree_render_recur(windowTreeRoot);
}
static void wtree_key(struct GObj *this, struct GKeyEvent ev) {
if(this->focus == 0) return;
struct GWindow *add_window(const char *titleText) {
struct WindowTree *wt = find_free_space(windowTree);
if(windowTreeFocus && windowTreeFocus->window && windowTreeFocus->window->onKey) {
windowTreeFocus->window->onKey((struct GObj*) windowTreeFocus->window, ev);
}
}
static void wtree_fitter_recur(struct WTreeNode *node, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
if(node->window) {
node->window->x = x;
node->window->y = y;
node->window->w = w;
node->window->h = h;
node->window->fitter((struct GObj*) node->window);
} else {
if(node->vertical) {
if(node->first) {
wtree_fitter_recur(node->first, x, y, w, h / 2);
}
if(node->second) {
wtree_fitter_recur(node->second, x, y + h / 2, w, h / 2);
}
} else {
if(node->first) {
wtree_fitter_recur(node->first, x, y, w / 2, h);
}
if(node->second) {
wtree_fitter_recur(node->second, x + w / 2, y, w / 2, h);
}
}
}
}
static void wtree_fitter(struct GObj *_) {
wtree_fitter_recur(windowTreeRoot, windowTree->x, windowTree->y, windowTree->w, windowTree->h);
}
static void wtree_destroy_recur(struct WTreeNode *node) {
if(node->window) node->window->destroy((struct GObj*) node->window);
else {
if(node->first) wtree_destroy_recur(node->first);
if(node->second) wtree_destroy_recur(node->second);
}
}
static void wtree_destroy(struct GObj *_) {
wtree_destroy_recur(windowTreeRoot);
tiny_free(_);
}
static void init_ui() {
// Contains window tree and command bar
ui = gcont_new(0, 0, 320, 240, NULL);
if(!wt) return NULL;
// Contains windows
windowTree = tiny_calloc(sizeof(*windowTree), 1);
windowTree->onRender = wtree_render;
windowTree->onKey = wtree_key;
windowTree->destroy = wtree_destroy;
windowTree->fitter = wtree_fitter;
windowTree->x = windowTree->y = 0;
windowTree->w = 320;
windowTree->h = 226;
windowTree->focus = 0;
std_w8(wt, 0, sizeof(*wt));
windowTreeRoot = tiny_calloc(sizeof(*windowTreeRoot), 1);
windowTreeRoot->vertical = 0;
windowTreeRoot->window = NULL;
windowTreeRoot->parent = NULL;
windowTreeRoot->first = NULL;
windowTreeRoot->second = NULL;
windowTreeFocus = windowTreeRoot;
struct GWindow *gw = &wt->gw;
gcont_add(ui, 0, (struct GObj*) windowTree);
gw->whole = k3MObj();
k3MenuSetBounds(gw->whole, 0, 0, 320, 224);
static const char asdf[] = "Enter command, e.g. help";
cmdline = gtext_new(0, 226, 320, 14, g_dynstr16_new(sizeof(asdf) - 1, sizeof(asdf) - 1, asdf), NULL);
baseinputonkey = cmdline->onKey;
cmdline->onKey = inputonkey;
cmdline->focus = 1;
gw->title = k3MLabel(NULL, 14, titleText);
k3MenuSetBounds(gw->title, 0, 0, 320, 16);
k3MAddChild(gw->whole, gw->title);
gcont_add(ui, 0, (struct GObj*) cmdline);
gw->panel = k3MObj();
k3MenuSetBounds(gw->panel, 0, 0, 320, 224);
k3MAddChild(gw->whole, gw->panel);
ui->focus = 1;
k3MAddChild(ui, gw->whole);
return gw;
}
int add_window(struct GWindow *w) {
if(!windowTreeFocus) {
return 0;
}
if(windowTreeFocus && windowTreeFocus->window) {
windowTreeFocus->window->focus = 0;
}
if(!windowTreeFocus->window) {
windowTreeFocus->window = w;
} else {
struct WTreeNode *top = tiny_calloc(sizeof(*top), 1);
struct WTreeNode *second = tiny_calloc(sizeof(*second), 1);
top->vertical = windowTreeFocus->parent ? !windowTreeFocus->parent->vertical : 0;
top->window = NULL;
top->parent = windowTreeFocus->parent;
top->first = windowTreeFocus;
top->second = second;
second->window = w;
second->parent = top;
windowTreeFocus->parent = top;
if(top->parent) {
if(top->parent->first == windowTreeFocus) {
top->parent->first = top;
} else if(top->parent->second == windowTreeFocus) {
top->parent->second = top;
} else {
// wtf
}
} else {
windowTreeRoot = top;
}
windowTreeFocus = second;
}
windowTreeFocus->window->focus = 1;
windowTree->fitter(windowTree);
return 1;
}
int is_free_space() {
return 1;
}
static void destroy_window() {
if(!windowTreeFocus) return;
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 0;
windowTreeFocus->window->destroy((struct GObj*) windowTreeFocus->window);
windowTreeFocus->window = NULL;
if(windowTreeFocus->parent) {
struct WTreeNode *parent = windowTreeFocus->parent;
struct WTreeNode *other = NULL;
if(parent->first == windowTreeFocus) {
other = parent->second;
} else if(parent->second == windowTreeFocus) {
other = parent->first;
}
other->parent = parent->parent;
std_copy(parent, other, sizeof(struct WTreeNode));
tiny_free(windowTreeFocus);
windowTreeFocus = parent;
}
}
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 1;
}
windowTree->fitter(windowTree);
}
// Next lexicographical permutation of windows
static void permute() {
// TODO.
// TODO: Next lexicographical permutation of windows
}
static size_t path_size(Str16 *p) {
@ -811,33 +646,63 @@ static void load_programs() {
tiny_free(png);
}
static int dirtyX1 = INT32_MAX;
static int dirtyX2 = INT32_MIN;
static int dirtyY1 = INT32_MAX;
static int dirtyY2 = INT32_MIN;
void dirty(int x1, int y1, int w, int h) {
int x2 = x1 + w;
int y2 = y1 + h;
if(dirtyX1 > x1) {
dirtyX1 = x1;
}
if(dirtyX2 < x2) {
dirtyX2 = x2;
}
if(dirtyY1 > y1) {
dirtyY1 = y1;
}
if(dirtyY2 < y2) {
dirtyY2 = y2;
}
void dirty_obj(struct k3MObj *o) {
dirty(o->x, o->y, o->w, o->h);
}
void dirty_obj(struct GObj *o) {
dirty(o->x, o->y, o->w, o->h);
bool input_enter(struct k3MEvent *ev, uint8_t *ud) {
DynStr16 *ds16 = tiny_malloc(sizeof(*ds16) + strlen(cmdline->txt));
ds16->cap = strlen(cmdline->txt);
ds16->len = ds16->cap;
std_copy(ds16->data, cmdline->txt, ds16->len);
perform(ds16);
tiny_free(ds16);
cmdline->txt[0] = '\0';
return true;
}
static void init_ui() {
windowTree = tiny_calloc(1, sizeof(*windowTree));
ui = k3MScreen();
ui->x = 0;
ui->y = 0;
ui->w = 320;
ui->h = 240;
cmdline = k3MTextInput(NULL, 14, "Enter command...", "");
cmdline->x = 0;
cmdline->y = 226;
cmdline->w = 320;
cmdline->h = 14;
k3MRegisterEventHandler(cmdline, k3M_EVENT_COMPLETE, input_enter, NULL, 0);
k3MAddChild(ui, cmdline);
ui->keyboardFocus = (struct k3MObj*) cmdline;
}
uint32_t scancode_to_codepoint(bool shift, uint8_t scancode) {
uint32_t ret = 0;
if(scancode >= LK_A && scancode <= LK_Z) {
ret = scancode - LK_A + (shift ? 'A' : 'a');
} else if(scancode == LK_SPACE) {
ret = ' ';
} else if(scancode >= LK_0 && scancode <= LK_9) {
ret = scancode - LK_0 + '0';
} else if(scancode == LK_SLASH) {
ret = '/';
} else if(scancode == LK_COMMA) {
ret = ',';
} else if(scancode == LK_PERIOD) {
ret = '.';
}
return ret;
}
void startc() {
@ -877,7 +742,14 @@ void startc() {
drawdesk(0, 0, 320, 240);
ui->onRender((struct GObj*) ui);
{
struct k3MEvent ev = {
.original = ui,
.target = ui,
.code = k3M_EVENT_DRAW,
};
k3MEventSend(&ev);
}
while(1) {
KEvent kev;
@ -919,7 +791,29 @@ void startc() {
focus_next();
}
} else {
ui->onKey((struct GObj*) ui, (struct GKeyEvent) {.scancode = keyBuf[keyBufIndex].scancode, .press = keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS, .shift = shift, .alt = alt});
struct k3MEvent ev;
ev = (struct k3MEvent) {
.original = (void*) ui,
.target = (void*) ui,
.code = (keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS) ? k3M_EVENT_KEY_PRESS : k3M_EVENT_KEY_RELEASE,
.key = { .num = keyBuf[keyBufIndex].scancode },
};
k3MEventSend(&ev);
if(keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS) {
uint32_t codepoint = scancode_to_codepoint(shift, keyBuf[keyBufIndex].scancode);
ev = (struct k3MEvent) {
.original = (void*) ui,
.target = (void*) ui,
.code = k3M_EVENT_INPUT,
.input = { .code = codepoint },
};
k3MEventSend(&ev);
}
}
if(keyBuf[keyBufIndex].scancode == LK_LEFT_SHIFT) {
@ -943,8 +837,8 @@ void startc() {
alt &= ~ALT_LEFT;
if(sysNothingElseWasPressed) {
cmdline->focus ^= 1;
windowTree->focus ^= 1;
//cmdline->focus ^= 1;
//windowTree->focus ^= 1;
}
}
} else if(keyBuf[keyBufIndex].scancode == LK_LEFT_SYS) {
@ -968,7 +862,13 @@ void startc() {
dirtyY1 = INT32_MAX;
dirtyY2 = INT32_MIN;
}
ui->onRender((struct GObj*) ui);
struct k3MEvent ev = {
.original = ui,
.target = ui,
.code = k3M_EVENT_DRAW,
};
k3MEventSend(&ev);
}
memory_barrier();

View File

@ -9,37 +9,7 @@
#include"tiny.h"
#include"io.h"
#include"fileswindow.h"
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
#include"k3menu.h"
__attribute__((optimize("Ofast"))) static void b2hex(uint8_t b, char *ret) {
uint8_t top = b >> 4;
@ -52,24 +22,32 @@ __attribute__((optimize("Ofast"))) static void b2hex(uint8_t b, char *ret) {
static void show_help_window() {
if(!is_free_space()) return;
static const char txt[] = "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around.";
/*static const char txt[] = "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around.";
struct GLabel *l = glabel_new(0, 0, 0, 0, g_dynstr16_new(sizeof(txt) - 1, sizeof(txt) - 1, txt), 1);
static const char name[] = "Welcome to Luma";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0);
add_window(w);
add_window(w);*/
struct GWindow *gw = add_window("Welcome to Luma");
struct k3MLabel *lbl = k3MLabel(NULL, 14, "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around.");
k3MenuSetBounds(lbl, 0, 20, 320, 204);
k3MAddChild(gw->panel, lbl);
dirty_obj(gw->whole);
}
static void show_log_window() {
if(!is_free_space()) return;
struct GLabel *l = glabel_new(0, 0, 0, 0, log_get(), 0);
/*struct GLabel *l = glabel_new(0, 0, 0, 0, log_get(), 0);
static const char name[] = "System Logs";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0);
add_window(w);
add_window(w);*/
}
static void e9(const char *buf, size_t len) {
@ -301,7 +279,7 @@ void perform(DynStr16 *cmd) {
show_log_window();
} else if(cmd->len > 2 && cmd->data[0] == 'g' && cmd->data[1] == 'o' && cmd->data[2] == ' ') {
attempt_program_launch(cmd->data + 3, cmd->len - 3);
} else if(windowTreeFocus && windowTreeFocus->window) {
} /*else if(windowTreeFocus && windowTreeFocus->window) {
uint8_t *space = (uint8_t*) std_bytefind(cmd->len, (char*) cmd->data, ' ');
size_t end = space ? space - cmd->data : cmd->len;
@ -318,7 +296,7 @@ void perform(DynStr16 *cmd) {
break;
}
} else {
}*/ else {
// Failed.
}
}

View File

@ -7,7 +7,7 @@
#include"logserver.h"
static void gtext_render(struct GObj *_) {
/*static void gtext_render(struct GObj *_) {
struct GText *this = (void*) _;
LumaVidCommand *cmd = VidLink;
@ -444,7 +444,7 @@ void glist_clear(struct GList *this) {
tiny_free(this->children);
this->children = NULL;
this->cursor = 0;
}
}*/
DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data) {
DynStr16 *ret = tiny_malloc(sizeof(*ret) + cap);

View File

@ -2,11 +2,7 @@
#include"../std.h"
#include"../ps2/api.h"
typedef uint16_t Coord;
struct GObj;
struct GContainer;
#include"k3menu.h"
#define SHIFT_LEFT 1
#define SHIFT_RIGHT 2
@ -14,58 +10,6 @@ struct GContainer;
#define ALT_RIGHT 2
#define SYS_LEFT 1
#define SYS_RIGHT 2
struct GKeyEvent {
uint8_t scancode;
uint8_t press;
uint8_t shift;
uint8_t alt;
uint8_t sys;
};
typedef void(*RenderFunc)(struct GObj*);
typedef void(*KeyReactFunc)(struct GObj*, struct GKeyEvent);
typedef void(*FitterFunc)(struct GObj*);
typedef void(*DestroyFunc)(struct GObj*);
struct GObj {
RenderFunc onRender;
KeyReactFunc onKey;
DestroyFunc destroy;
FitterFunc fitter;
Coord x, y;
Coord w, h;
uint8_t focus;
void *ud;
};
struct GText {
struct GObj;
DynStr16 *placeholder;
DynStr16 *data;
};
struct GText *gtext_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *placeholder, DynStr16 *str);
typedef uint8_t GContainerChildMeta;
struct GContainerChild {
GContainerChildMeta meta;
struct GObj *obj;
};
struct GContainer {
struct GObj;
size_t childCount;
struct GContainerChild *children;
uint8_t meta;
};
struct GContainer *gcont_new(Coord x, Coord y, Coord w, Coord h, FitterFunc fitter);
int gcont_add(struct GContainer*, GContainerChildMeta, struct GObj*);
void gcont_set(struct GContainer*, size_t index, GContainerChildMeta, struct GObj*);
void gcont_del(struct GContainer*, size_t index);
void gcont_splitter_v(struct GObj*);
void gcont_splitter_h(struct GObj*);
typedef int(*GCMDFunc)(void*, const DynStr16 *line);
struct Command {
@ -78,44 +22,14 @@ struct CommandList {
struct Command *array;
};
struct GWindow {
struct GObj;
/*struct GWindow {
struct k3MObj;
DynStr16 *name;
struct GObj *child;
size_t owner;
struct CommandList cmds;
};
struct GWindow *gwindow_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *name, struct GObj *child, size_t owner);
int gwindow_regcmd(struct GWindow*, Str16 *cmd, void *ud, GCMDFunc handler);
struct GLabel {
struct GObj;
DynStr16 *data;
int owned;
};
struct GLabel *glabel_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *data, int owned);
struct GListChild {
DynStr16 *text;
void *ud;
uint8_t selected;
};
struct GList {
struct GObj;
size_t childCount;
struct GListChild *children;
size_t cursor;
};
struct GList *glist_new(Coord x, Coord y, Coord w, Coord h);
int glist_add(struct GList*, DynStr16*, void *ud);
void glist_clear(struct GList*);
int gwindow_regcmd(struct GWindow*, Str16 *cmd, void *ud, GCMDFunc handler);*/
DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data);
DynStr16 *g_dynstr16_append(DynStr16*, uint16_t len, const void *data);

View File

@ -5,17 +5,18 @@
extern void *FSLink;
extern void *VidLink;
struct WTreeNode {
char vertical;
struct GWindow *window;
struct WTreeNode *parent;
struct WTreeNode *first;
struct WTreeNode *second;
};
extern struct WTreeNode *windowTreeFocus;
struct GWindow {
struct k3MObj *whole;
struct k3MLabel *title;
struct k3MObj *panel;
// k3Menu only supports one "focused" element per k3MScreen,
// but we want to save these when people Alt+Tab
struct k3MObj *focus;
};
struct GWindow *add_window(const char *title);
int add_window(struct GWindow *w);
int is_free_space();
void dirty(int x, int y, int w, int h);
void dirty_obj(struct GObj*);
void dirty_obj(struct k3MObj*);