Window stack
This commit is contained in:
parent
64ea01f46b
commit
703b2ec3f0
1 changed files with 67 additions and 50 deletions
117
src/app.c
117
src/app.c
|
|
@ -22,14 +22,20 @@ static struct tex fb_as_tex(void) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define APP_STACK_SIZE 10
|
|
||||||
struct app_instance {
|
struct app_instance {
|
||||||
struct app_template *template;
|
struct app_template *template;
|
||||||
struct rect pos;
|
struct rect pos;
|
||||||
void *app;
|
void *app;
|
||||||
struct tex framebuf;
|
struct tex framebuf;
|
||||||
} app_stack[10];
|
struct app_instance *next_app;
|
||||||
size_t app_stack_size = 0;
|
struct app_instance *prev_app;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Soon dynamic allocation
|
||||||
|
struct app_instance apps[32];
|
||||||
|
size_t free_idx = 0;
|
||||||
|
|
||||||
|
struct app_instance *app_root = NULL;
|
||||||
|
|
||||||
struct tex app_background;
|
struct tex app_background;
|
||||||
|
|
||||||
|
|
@ -75,41 +81,43 @@ void app_init_global(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct app_instance *app_find(void *app) {
|
static struct app_instance *app_find(void *app) {
|
||||||
for (int i = (int)app_stack_size - 1; i >= 0; i--) {
|
|
||||||
if (app_stack[i].app == app) {
|
if (app_root->app == app) {
|
||||||
return app_stack + i;
|
return app_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (struct app_instance *cursor = app_root->next_app; cursor != app_root; cursor = cursor->next_app) {
|
||||||
|
if (cursor->app == app) {
|
||||||
|
return cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_redraw_below(struct rect uncovered, size_t idx) {
|
static void app_redraw_below(struct rect uncovered, struct app_instance *ins) {
|
||||||
ASSERT(idx < app_stack_size);
|
|
||||||
struct tex fb_tex = fb_as_tex();
|
struct tex fb_tex = fb_as_tex();
|
||||||
tex_blit(&fb_tex, &app_background, &uncovered, &uncovered);
|
tex_blit(&fb_tex, &app_background, &uncovered, &uncovered);
|
||||||
for (size_t i = 0; i < idx; i++) {
|
for (struct app_instance *cursor = ins->next_app; cursor != ins; cursor = cursor->next_app) {
|
||||||
struct app_instance *ins = &app_stack[i];
|
|
||||||
struct rect local_src = uncovered;
|
struct rect local_src = uncovered;
|
||||||
struct rect local_dst = uncovered;
|
struct rect local_dst = uncovered;
|
||||||
rect_clamp(&local_src, &ins->pos);
|
rect_clamp(&local_src, &cursor->pos);
|
||||||
rect_clamp(&local_dst, &ins->pos);
|
rect_clamp(&local_dst, &cursor->pos);
|
||||||
rect_translate(&local_src, -ins->pos.x, -ins->pos.y);
|
rect_translate(&local_src, -cursor->pos.x, -cursor->pos.y);
|
||||||
tex_blit(&fb_tex, &ins->framebuf, &local_src, &local_dst);
|
tex_blit(&fb_tex, &cursor->framebuf, &local_src, &local_dst);
|
||||||
}
|
}
|
||||||
fb_damage(uncovered);
|
fb_damage(uncovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void app_redraw_above(struct rect uncovered, size_t idx) {
|
static void app_redraw_above(struct rect uncovered, struct app_instance *ins) {
|
||||||
ASSERT(idx < app_stack_size);
|
ASSERT(ins != NULL);
|
||||||
struct tex fb_tex = fb_as_tex();
|
struct tex fb_tex = fb_as_tex();
|
||||||
for (size_t i = idx + 1; i < app_stack_size; i++) {
|
for (struct app_instance *cursor = ins->prev_app; cursor != ins; cursor = cursor->prev_app) {
|
||||||
struct app_instance *ins = &app_stack[i];
|
|
||||||
struct rect local_src = uncovered;
|
struct rect local_src = uncovered;
|
||||||
struct rect local_dst = uncovered;
|
struct rect local_dst = uncovered;
|
||||||
rect_clamp(&local_src, &ins->pos);
|
rect_clamp(&local_src, &cursor->pos);
|
||||||
rect_clamp(&local_dst, &ins->pos);
|
rect_clamp(&local_dst, &cursor->pos);
|
||||||
rect_translate(&local_src, -ins->pos.x, -ins->pos.y);
|
rect_translate(&local_src, -cursor->pos.x, -cursor->pos.y);
|
||||||
tex_blit(&fb_tex, &ins->framebuf, &local_src, &local_dst);
|
tex_blit(&fb_tex, &cursor->framebuf, &local_src, &local_dst);
|
||||||
}
|
}
|
||||||
fb_damage(uncovered);
|
fb_damage(uncovered);
|
||||||
}
|
}
|
||||||
|
|
@ -142,9 +150,8 @@ void app_draw_rect(void *self, struct color col, const struct rect *rect) {
|
||||||
tex_fill_region(&my_view, col, rect);
|
tex_fill_region(&my_view, col, rect);
|
||||||
|
|
||||||
struct rect rect_global = app_rect_local_to_global(ins, rect);
|
struct rect rect_global = app_rect_local_to_global(ins, rect);
|
||||||
size_t own_idx = (ins - app_stack);
|
if (ins != app_root) {
|
||||||
if (own_idx < app_stack_size - 1) {
|
app_redraw_above(rect_global, ins);
|
||||||
app_redraw_above(rect_global, own_idx);
|
|
||||||
}
|
}
|
||||||
fb_damage(rect_global);
|
fb_damage(rect_global);
|
||||||
}
|
}
|
||||||
|
|
@ -162,9 +169,8 @@ void app_draw_texture(void *self, const struct tex *tex, int x, int y) {
|
||||||
|
|
||||||
struct rect rect_local = RECT_XYWH(x, y, tex->width, tex->height);
|
struct rect rect_local = RECT_XYWH(x, y, tex->width, tex->height);
|
||||||
struct rect rect_global = app_rect_local_to_global(ins, &rect_local);
|
struct rect rect_global = app_rect_local_to_global(ins, &rect_local);
|
||||||
size_t own_idx = (ins - app_stack);
|
if (ins != app_root) {
|
||||||
if (own_idx < app_stack_size - 1) {
|
app_redraw_above(rect_global, ins);
|
||||||
app_redraw_above(rect_global, own_idx);
|
|
||||||
}
|
}
|
||||||
fb_damage(rect_global);
|
fb_damage(rect_global);
|
||||||
}
|
}
|
||||||
|
|
@ -189,9 +195,10 @@ bool app_push(struct app_template *template, void *arg, struct rect *pos) {
|
||||||
};
|
};
|
||||||
struct ppn ppn;
|
struct ppn ppn;
|
||||||
ASSERT(ram_alloc_buffer(&ppn, req));
|
ASSERT(ram_alloc_buffer(&ppn, req));
|
||||||
ASSERT(app_stack_size < APP_STACK_SIZE);
|
|
||||||
// TODO this structure should be locked
|
// TODO this structure should be locked
|
||||||
app_stack[app_stack_size++] = (struct app_instance){
|
// 32 = length of apps[]
|
||||||
|
ASSERT(free_idx < 32);
|
||||||
|
apps[free_idx] = (struct app_instance){
|
||||||
.template = template,
|
.template = template,
|
||||||
.pos = actual_pos,
|
.pos = actual_pos,
|
||||||
.app = app,
|
.app = app,
|
||||||
|
|
@ -200,14 +207,23 @@ bool app_push(struct app_template *template, void *arg, struct rect *pos) {
|
||||||
RECT_HEIGHT(actual_pos),
|
RECT_HEIGHT(actual_pos),
|
||||||
ppn_to_pointer(ppn)
|
ppn_to_pointer(ppn)
|
||||||
),
|
),
|
||||||
|
.next_app = app_root != NULL ? app_root : &apps[free_idx],
|
||||||
|
.prev_app = app_root != NULL ? app_root->prev_app : &apps[free_idx]
|
||||||
};
|
};
|
||||||
|
if (app_root != NULL) {
|
||||||
|
app_root->prev_app->next_app = &apps[free_idx];
|
||||||
|
app_root->prev_app = &apps[free_idx];
|
||||||
|
}
|
||||||
|
app_root = &apps[free_idx];
|
||||||
|
free_idx++;
|
||||||
|
|
||||||
template->init(app);
|
template->init(app);
|
||||||
fb_refresh();
|
fb_refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *app_top(void) {
|
void *app_top(void) {
|
||||||
return (app_stack_size == 0) ? NULL : app_stack + app_stack_size - 1;
|
return app_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_pop(void) {
|
void app_pop(void) {
|
||||||
|
|
@ -219,64 +235,65 @@ void app_pop(void) {
|
||||||
ins->template->destroy(ins->app);
|
ins->template->destroy(ins->app);
|
||||||
ram_free(ppn_from_aligned_pa(pa_from_pointer(ins->framebuf.data)));
|
ram_free(ppn_from_aligned_pa(pa_from_pointer(ins->framebuf.data)));
|
||||||
|
|
||||||
// we know `app_stack_size` is at least 1 here, so the decrement is safe
|
app_redraw_below(uncovered, ins);
|
||||||
app_redraw_below(uncovered, app_stack_size - 1);
|
if (ins == ins->next_app) {
|
||||||
app_stack_size--;
|
app_root = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ins->next_app->prev_app = ins->prev_app;
|
||||||
|
ins->prev_app->next_app = ins->next_app;
|
||||||
|
app_root = ins->next_app;
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_translate(size_t app_idx, int dx, int dy) {
|
void app_translate(struct app_instance *ins, int dx, int dy) {
|
||||||
// TODO could optimize the uncovered
|
// TODO could optimize the uncovered
|
||||||
ASSERT(app_idx < app_stack_size);
|
|
||||||
struct app_instance *ins = &app_stack[app_idx];
|
|
||||||
const struct rect uncovered = ins->pos;
|
const struct rect uncovered = ins->pos;
|
||||||
rect_translate(&ins->pos, dx, dy);
|
rect_translate(&ins->pos, dx, dy);
|
||||||
struct tex fb_tex = fb_as_tex();
|
struct tex fb_tex = fb_as_tex();
|
||||||
// draw everything below, and then the current window
|
// draw everything below, and then the current window
|
||||||
app_redraw_below(uncovered, app_idx);
|
app_redraw_below(uncovered, ins);
|
||||||
tex_blit(&fb_tex, &ins->framebuf, NULL, &ins->pos);
|
tex_blit(&fb_tex, &ins->framebuf, NULL, &ins->pos);
|
||||||
fb_damage(ins->pos);
|
fb_damage(ins->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_key_event_listener(struct key_event event) {
|
void app_key_event_listener(struct key_event event) {
|
||||||
if (app_stack_size == 0) {
|
if (app_root == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct app_instance *ins = app_top();
|
struct app_instance *ins = app_top();
|
||||||
|
|
||||||
if (event.code == KEY_ARROW_LEFT && (event.mod & KEY_MOD_SHIFT)) {
|
if (event.code == KEY_ARROW_LEFT && (event.mod & KEY_MOD_SHIFT)) {
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
app_translate(app_stack_size - 1, -10, 0);
|
app_translate(ins, -10, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.code == KEY_ARROW_RIGHT && (event.mod & KEY_MOD_SHIFT)) {
|
if (event.code == KEY_ARROW_RIGHT && (event.mod & KEY_MOD_SHIFT)) {
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
app_translate(app_stack_size - 1, 10, 0);
|
app_translate(ins, 10, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.code == KEY_ARROW_UP && (event.mod & KEY_MOD_SHIFT)) {
|
if (event.code == KEY_ARROW_UP && (event.mod & KEY_MOD_SHIFT)) {
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
app_translate(app_stack_size - 1, 0, -10);
|
app_translate(ins, 0, -10);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.code == KEY_ARROW_DOWN && (event.mod & KEY_MOD_SHIFT)) {
|
if (event.code == KEY_ARROW_DOWN && (event.mod & KEY_MOD_SHIFT)) {
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
app_translate(app_stack_size - 1, 0, 10);
|
app_translate(ins, 0, 10);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.code == KEY_TAB && (event.mod & KEY_MOD_SHIFT)) {
|
if (event.code == KEY_TAB && (event.mod & KEY_MOD_SHIFT)) {
|
||||||
// select lowest app to be the current one now (natural rotation, easy for now)
|
// select next app to be the current one now (natural rotation, easy for now)
|
||||||
if (event.pressed && app_stack_size >= 2) {
|
if (event.pressed) {
|
||||||
struct app_instance lowest = app_stack[0];
|
app_root = app_root->next_app;
|
||||||
memmove(app_stack, app_stack + 1, (app_stack_size - 1) * sizeof(struct app_instance));
|
|
||||||
app_stack[app_stack_size - 1] = lowest;
|
|
||||||
// redraw this new top window
|
// redraw this new top window
|
||||||
struct tex fb_tex = fb_as_tex();
|
struct tex fb_tex = fb_as_tex();
|
||||||
tex_blit(&fb_tex, &lowest.framebuf, NULL, &lowest.pos);
|
tex_blit(&fb_tex, &app_root->framebuf, NULL, &app_root->pos);
|
||||||
fb_damage(lowest.pos);
|
fb_damage(app_root->pos);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue