From a0ccd6149c0c389be36cb811bb86bb1489d690c3 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 15 May 2023 23:25:36 +0200 Subject: [PATCH] fixup! Add display server. --- display/display-code.c | 101 +++++++++++++++++++++++----- display/window.c | 145 +++++++++++++++++++++++++++++------------ display/window.h | 3 + 3 files changed, 189 insertions(+), 60 deletions(-) diff --git a/display/display-code.c b/display/display-code.c index f886b279..f8c97fbe 100644 --- a/display/display-code.c +++ b/display/display-code.c @@ -409,17 +409,7 @@ void display_keyboard_event(struct display* display, uint32_t codepoint) if ( (display->key_lalt && kbkey == KBKEY_F4) /* || (display->key_lctrl && kbkey == KBKEY_Q)*/ ) { - struct event_keyboard event; - event.window_id = display->active_window->window_id; - - struct display_packet_header header; - header.message_id = EVENT_QUIT; - header.message_length = sizeof(event); - - assert(window->connection); - - connection_schedule_transmit(window->connection, &header, sizeof(header)); - connection_schedule_transmit(window->connection, &event, sizeof(event)); + window_quit(window); return; } @@ -546,14 +536,27 @@ void display_mouse_event(struct display* display, uint8_t byte) display->pointer_x += xm; display->pointer_y += ym; + bool clipped_edge = false; if ( display->pointer_x < 0 ) + { display->pointer_x = 0; + clipped_edge = true; + } if ( display->pointer_y < 0 ) + { display->pointer_y = 0; - if ( display->screen_width <= (size_t) display->pointer_x ) + clipped_edge = true; + } + if ( display->screen_width < (size_t) display->pointer_x ) + { display->pointer_x = display->screen_width; - if ( display->screen_height <= (size_t) display->pointer_y ) + clipped_edge = true; + } + if ( display->screen_height < (size_t) display->pointer_y ) + { display->pointer_y = display->screen_height; + clipped_edge = true; + } xm = display->pointer_x - old_pointer_x; ym = display->pointer_y - old_pointer_y; @@ -592,8 +595,23 @@ void display_mouse_event(struct display* display, uint8_t byte) window_pointer_x < (ssize_t) window->width && 0 <= window_pointer_y && window_pointer_y <= (ssize_t) TITLE_HEIGHT) ) - display->mouse_state = MOUSE_STATE_TITLE_MOVE; - else if ( window_pointer_x < 0 && window_pointer_y < 0 ) + { + size_t border_width = window_border_width(window); + size_t button_width = FONT_WIDTH * 2; + ssize_t buttons_x = window->width - border_width + - button_width * 3 + 1; + ssize_t rel_x = window_pointer_x - buttons_x; + if ( 0 <= rel_x && rel_x < (ssize_t) button_width ) + { + // TODO Minimize window. + } + else if ( 0 <= rel_x && rel_x < (ssize_t) button_width * 2 ) + window_toggle_maximized(window); + else if ( 0 <= rel_x && rel_x < (ssize_t) button_width * 3 ) + window_quit(window); + else + display->mouse_state = MOUSE_STATE_TITLE_MOVE; + } else if ( window_pointer_x < 0 && window_pointer_y < 0 ) display->mouse_state = MOUSE_STATE_RESIZE_TOP_LEFT; else if ( window_pointer_x < 0 && 0 <= window_pointer_y && @@ -623,13 +641,60 @@ void display_mouse_event(struct display* display, uint8_t byte) } if ( xm || ym ) { + bool floating = window->window_state == WINDOW_STATE_REGULAR; + bool on_edge = display->pointer_x == 0 + || display->pointer_y == 0 + || display->pointer_x + == (ssize_t) display->screen_width + || display->pointer_y + == (ssize_t) display->screen_height; switch ( display->mouse_state ) { case MOUSE_STATE_NONE: break; case MOUSE_STATE_TITLE_MOVE: - if ( window->window_state != WINDOW_STATE_REGULAR ) - window_restore(window); - window_move(window, window->left + xm, window->top + ym); + if ( clipped_edge ) + { + // I'd declare those in function scope but I'm afraid of + // messing with the code too much. + ssize_t x = display->pointer_x; + ssize_t y = display->pointer_y; + + ssize_t sw = display->screen_width; + ssize_t sh = display->screen_height; + + ssize_t corner_size = (sw < sh ? sw : sh) / 4; + if ( x < corner_size && y < corner_size ) + window_tile_top_left(window); + else if (sw - x < corner_size && y < corner_size ) + window_tile_top_right(window); + else if ( x < corner_size && sh - y < corner_size ) + window_tile_bottom_left(window); + else if (sw - x < corner_size && sh - y < corner_size ) + window_tile_bottom_right(window); + else if (x == 0) + window_tile_left(window); + else if (x == sw) + window_tile_right(window); + else if (y == 0) + window_tile_top(window); + else if (y == sh) + window_tile_bottom(window); + } + else if (floating || !on_edge) + { + if ( !floating ) + { + // The current behaviour of window_restore becomes + // awkward with tiling gestures. I could change the + // function itself, especially since this is currently + // its only callsite, but the old behaviour could be + // nice for a future untile hotkey. Thus, this hack. + window_restore(window); + window->top = display->pointer_y - TITLE_HEIGHT / 2; + window->left = display->pointer_x - window->width / 2; + } + window_move(window, window->left + xm, window->top + ym); + } break; case MOUSE_STATE_RESIZE_TOP_LEFT: window_drag_resize(window, xm, ym, -xm, -ym); diff --git a/display/window.c b/display/window.c index f7fdec12..53b27a1e 100644 --- a/display/window.c +++ b/display/window.c @@ -101,62 +101,97 @@ void window_render_frame(struct window* window) } const char* tt = window->title ? window->title : ""; - size_t tt_max_width = window->width - 2 * BORDER_WIDTH; - size_t tt_desired_width = render_text_width(tt); - size_t tt_width = tt_desired_width < tt_max_width ? tt_desired_width : tt_max_width; + ssize_t tt_width = render_text_width(tt); // Potentially adjusted later. size_t tt_height = FONT_HEIGHT; - size_t tt_pos_x = BORDER_WIDTH + (tt_max_width - tt_width) / 2; size_t tt_pos_y = (TITLE_HEIGHT - FONT_HEIGHT) / 2 + 2; uint32_t tt_color = title_color; - render_text(framebuffer_crop(window->buffer, tt_pos_x, tt_pos_y, tt_width, tt_height), tt, tt_color); - size_t border_width = maximized ? BORDER_WIDTH / 2 : BORDER_WIDTH; - size_t button_size = FONT_WIDTH - 1; - size_t button_spacing = FONT_WIDTH; + size_t border_width = window_border_width(window); + size_t button_width = FONT_WIDTH * 2; + size_t button_height = FONT_HEIGHT; + ssize_t buttons_x = window->width - border_width - button_width * 3 + 1; struct framebuffer buttons_fb = - framebuffer_crop(window->buffer, - window->width - border_width - (FONT_HEIGHT - button_size) / 2 - 5 * button_spacing, - tt_pos_y, tt_width, tt_height); - size_t buttons_top = (FONT_HEIGHT - button_size) / 2; + framebuffer_crop(window->buffer, buttons_x, + tt_pos_y, button_width * 3, tt_height); + size_t button_size = FONT_WIDTH - 1; +#if 0 + for (size_t x = 0; x < button_width; x++) + for (size_t y = 0; y < button_height; y++) + framebuffer_set_pixel(buttons_fb, button_width * 0 + x, y, 0xFF8080FF); + for (size_t x = 0; x < button_width; x++) + for (size_t y = 0; y < button_height; y++) + framebuffer_set_pixel(buttons_fb, button_width * 1 + x, y, 0xFFFF8080); + for (size_t x = 0; x < button_width; x++) + for (size_t y = 0; y < button_height; y++) + framebuffer_set_pixel(buttons_fb, button_width * 2 + x, y, 0xFF8080FF); +#endif for ( size_t i = 0; i < button_size; i++ ) { - framebuffer_set_pixel(buttons_fb, 0 * button_spacing + i, - buttons_top + button_size - 1, tt_color); - framebuffer_set_pixel(buttons_fb, 0 * button_spacing + i, - buttons_top + button_size - 2, tt_color); + size_t bx = button_width * 0 + (button_width - button_size) / 2; + size_t by = (button_height - button_size) / 2; + framebuffer_set_pixel(buttons_fb, bx + i, + by + button_size - 1, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i, + by + button_size - 2, tt_color); } for ( size_t i = 0; i < button_size; i++ ) { - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i, - buttons_top, tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i, - buttons_top + button_size - 1 , tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing, - buttons_top + i, tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + button_size - 1, - buttons_top + i, tt_color); + size_t bx = button_width * 1 + (button_width - button_size) / 2; + size_t by = (button_height - button_size) / 2; + framebuffer_set_pixel(buttons_fb, bx + i, + by, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i, + by + button_size - 1 , tt_color); + framebuffer_set_pixel(buttons_fb, bx, + by + i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + button_size - 1, + by + i, tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i, - buttons_top + 1, tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + i, - buttons_top + button_size - 2 , tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + 1, - buttons_top + i, tt_color); - framebuffer_set_pixel(buttons_fb, 2 * button_spacing + button_size - 2, - buttons_top + i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i, + by + 1, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i, + by + button_size - 2 , tt_color); + framebuffer_set_pixel(buttons_fb, bx + 1, + by + i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + button_size - 2, + by + i, tt_color); } for ( size_t i = 0; i < button_size; i++ ) { - framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i, - buttons_top + i, tt_color); - framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i, - buttons_top + button_size - 1 - i, tt_color); + size_t bx = button_width * 2 + (button_width - button_size) / 2; + size_t by = (button_height - button_size) / 2; + framebuffer_set_pixel(buttons_fb, bx + i, + by + i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i, + by + button_size - 1 - i, tt_color); - framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i + 1, - buttons_top + i, tt_color); - framebuffer_set_pixel(buttons_fb, 4 * button_spacing + i + 1, - buttons_top + button_size - 1 - i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i - 1, + by + i, tt_color); + framebuffer_set_pixel(buttons_fb, bx + i - 1, + by + button_size - 1 - i, tt_color); } + + ssize_t q = 500 - window->width; + ssize_t q_width = 200; + q = q < q_width ? q : q_width; + q = 0 < q ? q : 0; + ssize_t center_over = window->width - (button_width * 3 * q / q_width); + ssize_t tt_pos_x = (center_over - tt_width) / 2; +#if 0 + for (int y = 0; y < 10; y++) + { + framebuffer_set_pixel(window->buffer, window->width / 2, y, 0xFFFF0000); + framebuffer_set_pixel(window->buffer, (window->width - button_width * 3) / 2, y, 0xFFFF0000); + framebuffer_set_pixel(window->buffer, center_over/2, y, 0xFFFF00FF); + } +#endif + if ( tt_pos_x < (ssize_t)border_width ) + { + tt_pos_x = border_width; + tt_width = buttons_x - border_width; + tt_width = 0 < tt_width ? tt_width : 0; + } + render_text(framebuffer_crop(window->buffer, tt_pos_x, tt_pos_y, tt_width, tt_height), tt, tt_color); } void window_move(struct window* window, size_t left, size_t top) @@ -172,7 +207,7 @@ void window_client_resize(struct window* window, if ( window->window_state != WINDOW_STATE_MINIMIZED ) window->window_state = WINDOW_STATE_REGULAR; - free(window->buffer.buffer); + struct framebuffer old_fb = window->buffer; window->width = client_width + BORDER_WIDTH + BORDER_WIDTH; window->height = client_height + TITLE_HEIGHT + BORDER_WIDTH; @@ -182,7 +217,12 @@ void window_client_resize(struct window* window, window->buffer.pitch = window->width; window->buffer.buffer = (uint32_t*) malloc(sizeof(uint32_t) * window->width * window->height); - memset(window->buffer.buffer, 0, sizeof(uint32_t) * window->width * window->height); + for ( size_t y = 0; y < window->height; y++ ) + for ( size_t x = 0; x < window->width; x++ ) + framebuffer_set_pixel(window->buffer, x, y, + framebuffer_get_pixel(old_fb, x, y)); + + free(old_fb.buffer); window_render_frame(window); window_notify_client_resize(window); @@ -243,6 +283,21 @@ void window_initialize(struct window* window, window_client_resize(window, 0, 0); } +void window_quit(struct window* window) +{ + struct event_keyboard event; + event.window_id = window->window_id; + + struct display_packet_header header; + header.message_id = EVENT_QUIT; + header.message_length = sizeof(event); + + assert(window->connection); + + connection_schedule_transmit(window->connection, &header, sizeof(header)); + connection_schedule_transmit(window->connection, &event, sizeof(event)); +} + void window_destroy(struct window* window) { display_remove_window(window->display, window); @@ -480,3 +535,9 @@ void window_notify_client_resize(struct window* window) connection_schedule_transmit(window->connection, &header, sizeof(header)); connection_schedule_transmit(window->connection, &event, sizeof(event)); } + +size_t window_border_width(const struct window* window) +{ + bool maximized = window->window_state != WINDOW_STATE_REGULAR; + return maximized ? BORDER_WIDTH / 2 : BORDER_WIDTH; +} diff --git a/display/window.h b/display/window.h index f954e8c1..ade21ba2 100644 --- a/display/window.h +++ b/display/window.h @@ -80,6 +80,7 @@ void window_move(struct window* window, size_t left, size_t top); void window_resize(struct window* window, size_t width, size_t height); void window_client_resize(struct window* window, size_t client_width, size_t client_height); void window_initialize(struct window* window, struct connection* connection, struct display* display, uint32_t window_id); +void window_quit(struct window* window); void window_destroy(struct window* window); void window_drag_resize(struct window* window, int ld, int td, int wd, int hd); void window_on_display_resolution_change(struct window* window, struct display* display); @@ -101,4 +102,6 @@ void window_tile_bottom_left(struct window* window); void window_tile_bottom_right(struct window* window); void window_notify_client_resize(struct window* window); +size_t window_border_width(const struct window* window); + #endif