diff options
Diffstat (limited to 'src/kernel/window.c')
-rw-r--r-- | src/kernel/window.c | 131 |
1 files changed, 96 insertions, 35 deletions
diff --git a/src/kernel/window.c b/src/kernel/window.c index e7cf30d..bc36578 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -71,6 +71,49 @@ static void load_mode_params() { ); } +static inline void blit_pixel(uint32_t *into, struct pixel from) { + *into &= pix_clear_mask; + *into |= (from.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; + *into |= (from.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; + *into |= (from.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; +} + +static uint16_t mouse_y; +static uint16_t mouse_x; + +#define MOUSE_WIDTH 8 +#define MOUSE_HEIGHT 8 + +#define B {.r = 0, .g = 0, .b = 0, .pad = 0} +#define W {.r = 255, .g = 255, .b = 255, .pad = 0} +#define T {.pad = 1} + +static const struct pixel mouse_image[] = { + W, W, W, W, W, W, T, T, + W, B, B, B, W, T, T, T, + W, B, B, B, W, W, T, T, + W, B, B, B, B, W, W, T, + W, W, W, B, B, B, W, T, + W, T, W, W, B, B, B, W, + T, T, T, W, W, B, W, W, + T, T, T, T, W, W, W, T +}; + +static void blit_mouse() { + uint16_t y_max = mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height - mouse_y : MOUSE_HEIGHT; + uint16_t x_max = mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width - mouse_x : MOUSE_WIDTH; + void *row = VBE_MODE_INFO->frame_buf + mouse_y * VBE_MODE_INFO->pitch + mouse_x * (VBE_MODE_INFO->bpp / 8); + for (uint16_t y = 0; y < y_max; ++y) { + uint32_t *out_pix = row; + for (uint16_t x = 0; x < x_max; ++x) { + if (!mouse_image[y * MOUSE_WIDTH + x].pad) + blit_pixel(out_pix, mouse_image[y * MOUSE_WIDTH + x]); + out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8); + } + row += VBE_MODE_INFO->pitch; + } +} + static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) { void *row = VBE_MODE_INFO->frame_buf + y_min * VBE_MODE_INFO->pitch + x_min * (VBE_MODE_INFO->bpp / 8); const struct super_pixel *from_row = buffer + y_min * VBE_MODE_INFO->width + x_min; @@ -78,16 +121,17 @@ static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) uint32_t *out_pix = row; const struct super_pixel *from = from_row; for (uint16_t x = x_min; x < x_max; ++x) { - *out_pix &= pix_clear_mask; - *out_pix |= (from->p.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; - *out_pix |= (from->p.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; - *out_pix |= (from->p.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; + blit_pixel(out_pix, from->p); out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8); ++from; } row += VBE_MODE_INFO->pitch; from_row += VBE_MODE_INFO->width; } + + if ((y_min < mouse_y) && (y_max > mouse_y) && + (x_min < mouse_x) && (x_max > mouse_x)) + blit_mouse(); } #define POWER_OFF_MESSAGE_PITCH 45 @@ -343,8 +387,6 @@ static void send_action(struct window *w, struct window_action packet) { #define RUN_COMMAND_FILE "sys/winspace.rc" enum wm_action { - WM_SHUFFLE_UP, - WM_SHUFFLE_DOWN, WM_MOVE_LEFT, WM_MOVE_RIGHT, WM_MOVE_UP, @@ -355,8 +397,6 @@ enum wm_action { }; static struct key_packet keybinds[] = { - {.key_id = KEY_PAGE_DOWN, .modifiers = WINS}, - {.key_id = KEY_PAGE_UP, .modifiers = WINS}, {.key_id = KEY_LEFT_ARROW, .modifiers = WINS}, {.key_id = KEY_RIGHT_ARROW, .modifiers = WINS}, {.key_id = KEY_UP_ARROW, .modifiers = WINS}, @@ -393,6 +433,10 @@ void init_win() { paint_bg(); blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height); + mouse_x = (VBE_MODE_INFO->width - MOUSE_WIDTH) / 2; + mouse_y = (VBE_MODE_INFO->height - MOUSE_HEIGHT) / 2; + blit_mouse(); + const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE); if (!fid) PANIC("Couldn't open " RUN_COMMAND_FILE "."); @@ -425,34 +469,7 @@ void on_action(struct window_action packet) { for (uint8_t i = 0; i < N_WM_ACTIONS; ++i) if (fuzzy_key_match(keybinds[i], packet.as_key)) { switch_to_kernel_cr3(); - struct window *old_top, *old_bottom; switch (i) { - case WM_SHUFFLE_UP: - if (!top_window || !top_window->below) - break; - old_top = top_window; - old_bottom = bottom_window; - top_window = old_top->below; - top_window->above = 0; - old_top->below = 0; - old_top->above = old_bottom; - old_bottom->below = old_top; - bottom_window = old_top; - paint_and_above(bottom_window->above); - break; - case WM_SHUFFLE_DOWN: - if (!top_window || !top_window->below) - break; - old_top = top_window; - old_bottom = bottom_window; - bottom_window = old_bottom->above; - bottom_window->below = 0; - old_bottom->above = 0; - old_bottom->below = old_top; - old_top->above = old_bottom; - top_window = old_bottom; - paint_and_above(top_window); - break; case WM_MOVE_LEFT: if (top_window) { top_window->xpos -= MOVE_BY; @@ -487,4 +504,48 @@ void on_action(struct window_action packet) { if (top_window) send_action(top_window, packet); +} + +void move_mouse_by(int16_t y, int16_t x) { +//logf(LOG_INFO, "old mouse coords: (%d, %d)", mouse_x, mouse_y); + switch_to_kernel_cr3(); + blit(mouse_x, mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width : mouse_x + MOUSE_WIDTH, + mouse_y, mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height : mouse_y + MOUSE_HEIGHT); + mouse_y = (-y > mouse_y) ? 0 : (y + mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height) ? VBE_MODE_INFO->height - MOUSE_HEIGHT : y + mouse_y; + mouse_x = (-x > mouse_x) ? 0 : (x + mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width) ? VBE_MODE_INFO->width - MOUSE_WIDTH : x + mouse_x; + blit_mouse(); + switch_to_task_cr3(); +//logf(LOG_INFO, "new mouse coords: (%d, %d)", mouse_x, mouse_y); +} + +static void focus(struct window *w) { + send_action(top_window, (struct window_action){.action_type = FOCUS_LEAVE}); + + if (w->below) + w->below->above = w->above; + else + bottom_window = w->above; + w->above->below = w->below; + w->above = 0; + w->below = top_window; + top_window->above = w; + top_window = w; + + send_action(w, (struct window_action){.action_type = FOCUS_ENTER}); +} + +void mouse_button(enum mouse_button which, bool up) { + if (!top_window) + return; + + struct window *const clicked_on = buffer[mouse_y * VBE_MODE_INFO->width + mouse_x].from_window; + if (!clicked_on) + return; + + if (clicked_on != top_window) { + focus(clicked_on); + paint_and_above(clicked_on); + } + + send_action(clicked_on, (struct window_action){.action_type = up ? MOUSE_UP : MOUSE_DOWN, .as_mouse = {.y = mouse_y - clicked_on->ypos, .x = mouse_x - clicked_on->xpos, .which = which}}); }
\ No newline at end of file |