Render menu after surface enter event

This fixes an issue where the first visible frame is blurry on
fractional scale displays.
This commit is contained in:
adnano 2025-03-01 07:04:00 -05:00
parent eec775fad7
commit fc69aa6e2b
4 changed files with 38 additions and 23 deletions

49
menu.c
View file

@ -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. // Render menu items.
void menu_render_items(struct menu *menu) { void menu_render_items(struct menu *menu) {
calc_widths(menu); calc_widths(menu);
@ -498,13 +503,13 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
// Delete right // Delete right
menu->input[menu->cursor] = '\0'; menu->input[menu->cursor] = '\0';
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_u: case XKB_KEY_u:
// Delete left // Delete left
insert(menu, NULL, 0 - menu->cursor); insert(menu, NULL, 0 - menu->cursor);
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_w: case XKB_KEY_w:
// Delete word // 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); insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
} }
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_Y: case XKB_KEY_Y:
// Paste clipboard // Paste clipboard
@ -523,17 +528,17 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
return; return;
} }
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_Left: case XKB_KEY_Left:
case XKB_KEY_KP_Left: case XKB_KEY_KP_Left:
movewordedge(menu, -1); movewordedge(menu, -1);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_Right: case XKB_KEY_Right:
case XKB_KEY_KP_Right: case XKB_KEY_KP_Right:
movewordedge(menu, +1); movewordedge(menu, +1);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_Return: case XKB_KEY_Return:
@ -547,11 +552,11 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
switch (sym) { switch (sym) {
case XKB_KEY_b: case XKB_KEY_b:
movewordedge(menu, -1); movewordedge(menu, -1);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_f: case XKB_KEY_f:
movewordedge(menu, +1); movewordedge(menu, +1);
render_menu(menu); menu_invalidate(menu);
return; return;
case XKB_KEY_g: case XKB_KEY_g:
sym = XKB_KEY_Home; 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: case XKB_KEY_KP_Up:
if (menu->sel && menu->sel->prev_match) { if (menu->sel && menu->sel->prev_match) {
menu->sel = menu->sel->prev_match; menu->sel = menu->sel->prev_match;
render_menu(menu); menu_invalidate(menu);
} else if (menu->cursor > 0) { } else if (menu->cursor > 0) {
menu->cursor = nextrune(menu, -1); menu->cursor = nextrune(menu, -1);
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_Right: 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: case XKB_KEY_KP_Down:
if (menu->cursor < len) { if (menu->cursor < len) {
menu->cursor = nextrune(menu, +1); menu->cursor = nextrune(menu, +1);
render_menu(menu); menu_invalidate(menu);
} else if (menu->sel && menu->sel->next_match) { } else if (menu->sel && menu->sel->next_match) {
menu->sel = menu->sel->next_match; menu->sel = menu->sel->next_match;
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_Prior: case XKB_KEY_Prior:
case XKB_KEY_KP_Prior: case XKB_KEY_KP_Prior:
if (menu->sel && menu->sel->page->prev) { if (menu->sel && menu->sel->page->prev) {
menu->sel = menu->sel->page->prev->first; menu->sel = menu->sel->page->prev->first;
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_Next: case XKB_KEY_Next:
case XKB_KEY_KP_Next: case XKB_KEY_KP_Next:
if (menu->sel && menu->sel->page->next) { if (menu->sel && menu->sel->page->next) {
menu->sel = menu->sel->page->next->first; menu->sel = menu->sel->page->next->first;
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_Home: case XKB_KEY_Home:
case XKB_KEY_KP_Home: case XKB_KEY_KP_Home:
if (menu->sel == menu->matches) { if (menu->sel == menu->matches) {
menu->cursor = 0; menu->cursor = 0;
render_menu(menu); menu_invalidate(menu);
} else { } else {
menu->sel = menu->matches; menu->sel = menu->matches;
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_End: case XKB_KEY_End:
case XKB_KEY_KP_End: case XKB_KEY_KP_End:
if (menu->cursor < len) { if (menu->cursor < len) {
menu->cursor = len; menu->cursor = len;
render_menu(menu); menu_invalidate(menu);
} else { } else {
menu->sel = menu->matches_end; menu->sel = menu->matches_end;
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_BackSpace: case XKB_KEY_BackSpace:
if (menu->cursor > 0) { if (menu->cursor > 0) {
insert(menu, NULL, nextrune(menu, -1) - menu->cursor); insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
} }
break; break;
case XKB_KEY_Delete: 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); menu->cursor = nextrune(menu, +1);
insert(menu, NULL, nextrune(menu, -1) - menu->cursor); insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
break; break;
case XKB_KEY_Tab: case XKB_KEY_Tab:
if (!menu->sel) { 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); memcpy(menu->input, menu->sel->text, menu->cursor);
menu->input[menu->cursor] = '\0'; menu->input[menu->cursor] = '\0';
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
break; break;
case XKB_KEY_Escape: case XKB_KEY_Escape:
menu->exit = true; 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)) { if (xkb_keysym_to_utf8(sym, buf, 8)) {
insert(menu, buf, strnlen(buf, 8)); insert(menu, buf, strnlen(buf, 8));
match_items(menu); match_items(menu);
render_menu(menu); menu_invalidate(menu);
} }
} }
} }

2
menu.h
View file

@ -64,6 +64,7 @@ struct menu {
int promptw; int promptw;
int left_arrow; int left_arrow;
int right_arrow; int right_arrow;
bool rendered;
char input[BUFSIZ]; char input[BUFSIZ];
size_t cursor; 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_getopts(struct menu *menu, int argc, char *argv[]);
void menu_add_item(struct menu *menu, char *text); void menu_add_item(struct menu *menu, char *text);
void menu_sort_and_deduplicate(struct menu *menu); void menu_sort_and_deduplicate(struct menu *menu);
void menu_invalidate(struct menu *menu);
void menu_render_items(struct menu *menu); void menu_render_items(struct menu *menu);
void menu_paste(struct menu *menu, const char *text, ssize_t len); 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, void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,

View file

@ -207,4 +207,6 @@ void render_menu(struct menu *menu) {
wl_surface_attach(surface, buffer->buffer, 0, 0); wl_surface_attach(surface, buffer->buffer, 0, 0);
wl_surface_damage(surface, 0, 0, menu->width, menu->height); wl_surface_damage(surface, 0, 0, menu->width, menu->height);
wl_surface_commit(surface); wl_surface_commit(surface);
menu->rendered = true;
} }

View file

@ -3,7 +3,6 @@
#include <errno.h> #include <errno.h>
#include <poll.h> #include <poll.h>
#include <stdbool.h> #include <stdbool.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -18,6 +17,7 @@
#include "menu.h" #include "menu.h"
#include "pool-buffer.h" #include "pool-buffer.h"
#include "render.h"
#include "wayland.h" #include "wayland.h"
#include "xdg-activation-v1-client-protocol.h" #include "xdg-activation-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-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) { static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *wl_output) {
struct wl_context *context = data; struct wl_context *context = data;
context->output = wl_output_get_user_data(wl_output); context->output = wl_output_get_user_data(wl_output);
menu_invalidate(context->menu);
} }
static const struct wl_surface_listener surface_listener = { static const struct wl_surface_listener surface_listener = {
@ -492,6 +493,11 @@ int menu_run(struct menu *menu) {
if (fds[1].revents & POLLIN) { if (fds[1].revents & POLLIN) {
keyboard_repeat(context->keyboard); keyboard_repeat(context->keyboard);
} }
// Render the menu if necessary
if (!menu->rendered) {
render_menu(menu);
}
} }
context_destroy(context); context_destroy(context);