Render menu after surface enter event - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit fc69aa6e2bccca461a0bd0c10b448b64ccda1d42
 (DIR) parent eec775fad7f7b090e6de2dbfe0c242129fddba41
 (HTM) Author: adnano <me@adnano.co>
       Date:   Sat,  1 Mar 2025 07:04:00 -0500
       
       Render menu after surface enter event
       
       This fixes an issue where the first visible frame is blurry on
       fractional scale displays.
       
       Diffstat:
         M menu.c                              |      49 +++++++++++++++++--------------
         M menu.h                              |       2 ++
         M render.c                            |       2 ++
         M wayland.c                           |       8 +++++++-
       
       4 files changed, 38 insertions(+), 23 deletions(-)
       ---
 (DIR) diff --git a/menu.c b/menu.c
       @@ -376,6 +376,11 @@ static void match_items(struct menu *menu) {
                }
        }
        
       +// Marks the menu as needing to be rendered again.
       +void menu_invalidate(struct menu *menu) {
       +        menu->rendered = false;
       +}
       +
        // Render menu items.
        void menu_render_items(struct menu *menu) {
                calc_widths(menu);
       @@ -498,13 +503,13 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                                // Delete right
                                menu->input[menu->cursor] = '\0';
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_u:
                                // Delete left
                                insert(menu, NULL, 0 - menu->cursor);
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_w:
                                // Delete word
       @@ -515,7 +520,7 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                                        insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                                }
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_Y:
                                // Paste clipboard
       @@ -523,17 +528,17 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                                        return;
                                }
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_Left:
                        case XKB_KEY_KP_Left:
                                movewordedge(menu, -1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_Right:
                        case XKB_KEY_KP_Right:
                                movewordedge(menu, +1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
        
                        case XKB_KEY_Return:
       @@ -547,11 +552,11 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        switch (sym) {
                        case XKB_KEY_b:
                                movewordedge(menu, -1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_f:
                                movewordedge(menu, +1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                                return;
                        case XKB_KEY_g:
                                sym = XKB_KEY_Home;
       @@ -593,10 +598,10 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                case XKB_KEY_KP_Up:
                        if (menu->sel && menu->sel->prev_match) {
                                menu->sel = menu->sel->prev_match;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        } else if (menu->cursor > 0) {
                                menu->cursor = nextrune(menu, -1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_Right:
       @@ -605,51 +610,51 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                case XKB_KEY_KP_Down:
                        if (menu->cursor < len) {
                                menu->cursor = nextrune(menu, +1);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        } else if (menu->sel && menu->sel->next_match) {
                                menu->sel = menu->sel->next_match;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_Prior:
                case XKB_KEY_KP_Prior:
                        if (menu->sel && menu->sel->page->prev) {
                                menu->sel = menu->sel->page->prev->first;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_Next:
                case XKB_KEY_KP_Next:
                        if (menu->sel && menu->sel->page->next) {
                                menu->sel = menu->sel->page->next->first;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_Home:
                case XKB_KEY_KP_Home:
                        if (menu->sel == menu->matches) {
                                menu->cursor = 0;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        } else {
                                menu->sel = menu->matches;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_End:
                case XKB_KEY_KP_End:
                        if (menu->cursor < len) {
                                menu->cursor = len;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        } else {
                                menu->sel = menu->matches_end;
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_BackSpace:
                        if (menu->cursor > 0) {
                                insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                        break;
                case XKB_KEY_Delete:
       @@ -660,7 +665,7 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        menu->cursor = nextrune(menu, +1);
                        insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                        match_items(menu);
       -                render_menu(menu);
       +                menu_invalidate(menu);
                        break;
                case XKB_KEY_Tab:
                        if (!menu->sel) {
       @@ -670,7 +675,7 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        memcpy(menu->input, menu->sel->text, menu->cursor);
                        menu->input[menu->cursor] = '\0';
                        match_items(menu);
       -                render_menu(menu);
       +                menu_invalidate(menu);
                        break;
                case XKB_KEY_Escape:
                        menu->exit = true;
       @@ -680,7 +685,7 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        if (xkb_keysym_to_utf8(sym, buf, 8)) {
                                insert(menu, buf, strnlen(buf, 8));
                                match_items(menu);
       -                        render_menu(menu);
       +                        menu_invalidate(menu);
                        }
                }
        }
 (DIR) diff --git a/menu.h b/menu.h
       @@ -64,6 +64,7 @@ struct menu {
                int promptw;
                int left_arrow;
                int right_arrow;
       +        bool rendered;
        
                char input[BUFSIZ];
                size_t cursor;
       @@ -85,6 +86,7 @@ void menu_destroy(struct menu *menu);
        void menu_getopts(struct menu *menu, int argc, char *argv[]);
        void menu_add_item(struct menu *menu, char *text);
        void menu_sort_and_deduplicate(struct menu *menu);
       +void menu_invalidate(struct menu *menu);
        void menu_render_items(struct menu *menu);
        void menu_paste(struct menu *menu, const char *text, ssize_t len);
        void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
 (DIR) diff --git a/render.c b/render.c
       @@ -207,4 +207,6 @@ void render_menu(struct menu *menu) {
                wl_surface_attach(surface, buffer->buffer, 0, 0);
                wl_surface_damage(surface, 0, 0, menu->width, menu->height);
                wl_surface_commit(surface);
       +
       +        menu->rendered = true;
        }
 (DIR) diff --git a/wayland.c b/wayland.c
       @@ -3,7 +3,6 @@
        #include <errno.h>
        #include <poll.h>
        #include <stdbool.h>
       -#include <signal.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       @@ -18,6 +17,7 @@
        
        #include "menu.h"
        #include "pool-buffer.h"
       +#include "render.h"
        #include "wayland.h"
        #include "xdg-activation-v1-client-protocol.h"
        #include "wlr-layer-shell-unstable-v1-client-protocol.h"
       @@ -208,6 +208,7 @@ static void noop() {
        static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *wl_output) {
                struct wl_context *context = data;
                context->output = wl_output_get_user_data(wl_output);
       +        menu_invalidate(context->menu);
        }
        
        static const struct wl_surface_listener surface_listener = {
       @@ -492,6 +493,11 @@ int menu_run(struct menu *menu) {
                        if (fds[1].revents & POLLIN) {
                                keyboard_repeat(context->keyboard);
                        }
       +
       +                // Render the menu if necessary
       +                if (!menu->rendered) {
       +                        render_menu(menu);
       +                }
                }
        
                context_destroy(context);