Add more rendering functions

This commit is contained in:
adnano 2024-02-26 16:44:23 -05:00
parent f9167689dc
commit 96b3c0ef26

118
main.c
View file

@ -87,7 +87,7 @@ struct menu {
uint32_t promptbg, promptfg; uint32_t promptbg, promptfg;
uint32_t selectionbg, selectionfg; uint32_t selectionbg, selectionfg;
char text[BUFSIZ]; char input[BUFSIZ];
size_t cursor; size_t cursor;
int repeat_timer; int repeat_timer;
@ -199,15 +199,15 @@ static void match_items(struct menu *menu) {
menu->matches_end = NULL; menu->matches_end = NULL;
menu->sel = NULL; menu->sel = NULL;
size_t len = strlen(menu->text); size_t len = strlen(menu->input);
struct item *item; struct item *item;
for (item = menu->items; item; item = item->next) { for (item = menu->items; item; item = item->next) {
if (!menu->strncmp(menu->text, item->text, len + 1)) { if (!menu->strncmp(menu->input, item->text, len + 1)) {
append_item(item, &lexact, &exactend); append_item(item, &lexact, &exactend);
} else if (!menu->strncmp(menu->text, item->text, len)) { } else if (!menu->strncmp(menu->input, item->text, len)) {
append_item(item, &lprefix, &prefixend); append_item(item, &lprefix, &prefixend);
} else if (fstrstr(menu, item->text, menu->text)) { } else if (fstrstr(menu, item->text, menu->input)) {
append_item(item, &lsubstr, &substrend); append_item(item, &lsubstr, &substrend);
} }
} }
@ -242,13 +242,13 @@ static void match_items(struct menu *menu) {
} }
static void insert(struct menu *menu, const char *s, ssize_t n) { static void insert(struct menu *menu, const char *s, ssize_t n) {
if (strlen(menu->text) + n > sizeof menu->text - 1) { if (strlen(menu->input) + n > sizeof menu->input - 1) {
return; return;
} }
memmove(menu->text + menu->cursor + n, menu->text + menu->cursor, memmove(menu->input + menu->cursor + n, menu->input + menu->cursor,
sizeof menu->text - menu->cursor - MAX(n, 0)); sizeof menu->input - menu->cursor - MAX(n, 0));
if (n > 0 && s != NULL) { if (n > 0 && s != NULL) {
memcpy(menu->text + menu->cursor, s, n); memcpy(menu->input + menu->cursor, s, n);
} }
menu->cursor += n; menu->cursor += n;
} }
@ -256,8 +256,8 @@ static void insert(struct menu *menu, const char *s, ssize_t n) {
static size_t nextrune(struct menu *menu, int incr) { static size_t nextrune(struct menu *menu, int incr) {
size_t n, len; size_t n, len;
len = strlen(menu->text); len = strlen(menu->input);
for(n = menu->cursor + incr; n < len && (menu->text[n] & 0xc0) == 0x80; n += incr); for(n = menu->cursor + incr; n < len && (menu->input[n] & 0xc0) == 0x80; n += incr);
return n; return n;
} }
@ -267,7 +267,7 @@ static void calc_widths(struct menu *menu) {
// Calculate prompt width // Calculate prompt width
if (menu->prompt) { if (menu->prompt) {
menu->promptw = text_width(cairo, menu->font, menu->prompt); menu->promptw = text_width(cairo, menu->font, menu->prompt) + menu->padding + menu->padding/2;
} else { } else {
menu->promptw = 0; menu->promptw = 0;
} }
@ -293,6 +293,7 @@ static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
(color >> (0*8) & 0xFF) / 255.0); (color >> (0*8) & 0xFF) / 255.0);
} }
// Renders text to cairo.
static int render_text(struct menu *menu, cairo_t *cairo, const char *str, static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
int x, int y, int width, uint32_t bg_color, uint32_t fg_color, int x, int y, int width, uint32_t bg_color, uint32_t fg_color,
int left_padding, int right_padding) { int left_padding, int right_padding) {
@ -316,6 +317,34 @@ static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
return width; return width;
} }
// Renders the prompt message.
static void render_prompt(struct menu *menu, cairo_t *cairo) {
if (!menu->prompt) {
return;
}
render_text(menu, cairo, menu->prompt, 0, 0, 0,
menu->promptbg, menu->promptfg, menu->padding, menu->padding/2);
}
// Renders the input text.
static void render_input(struct menu *menu, cairo_t *cairo) {
render_text(menu, cairo, menu->input, menu->promptw, 0, 0,
0, menu->foreground, menu->padding, menu->padding);
}
// Renders a cursor for the input field.
static void render_cursor(struct menu *menu, cairo_t *cairo) {
const int cursor_width = 2;
const int cursor_margin = 2;
int cursor_pos = menu->promptw + menu->padding
+ text_width(cairo, menu->font, menu->input)
- text_width(cairo, menu->font, &menu->input[menu->cursor])
- cursor_width / 2;
cairo_rectangle(cairo, cursor_pos, cursor_margin, cursor_width,
menu->line_height - 2 * cursor_margin);
cairo_fill(cairo);
}
// Renders a single menu item horizontally. // Renders a single menu item horizontally.
static int render_horizontal_item(struct menu *menu, cairo_t *cairo, struct item *item, int x) { static int render_horizontal_item(struct menu *menu, cairo_t *cairo, struct item *item, int x) {
uint32_t bg_color = menu->sel == item ? menu->selectionbg : menu->background; uint32_t bg_color = menu->sel == item ? menu->selectionbg : menu->background;
@ -362,41 +391,22 @@ static void render_vertical_page(struct menu *menu, cairo_t *cairo, struct page
} }
} }
static void render_to_cairo(struct menu *menu, cairo_t *cairo) { // Renders the menu to cairo.
// Draw background static void render_menu(struct menu *menu, cairo_t *cairo) {
// Render background
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_set_source_u32(cairo, menu->background); cairo_set_source_u32(cairo, menu->background);
cairo_paint(cairo); cairo_paint(cairo);
int x = 0; // Render prompt and input
render_prompt(menu, cairo);
// Draw prompt render_input(menu, cairo);
if (menu->prompt) { render_cursor(menu, cairo);
x += render_text(menu, cairo, menu->prompt, 0, 0, 0,
menu->promptbg, menu->promptfg, menu->padding, menu->padding/2);
}
// Draw input
render_text(menu, cairo, menu->text, x, 0, 0,
0, menu->foreground, menu->padding, menu->padding);
// Draw cursor
{
const int cursor_width = 2;
const int cursor_margin = 2;
int cursor_pos = x + menu->padding
+ text_width(cairo, menu->font, menu->text)
- text_width(cairo, menu->font, &menu->text[menu->cursor])
- cursor_width / 2;
cairo_rectangle(cairo, cursor_pos, cursor_margin, cursor_width,
menu->line_height - 2 * cursor_margin);
cairo_fill(cairo);
}
// Render selected page
if (!menu->sel) { if (!menu->sel) {
return; return;
} }
// Draw matches
if (menu->vertical) { if (menu->vertical) {
render_vertical_page(menu, cairo, menu->sel->page); render_vertical_page(menu, cairo, menu->sel->page);
} else { } else {
@ -417,7 +427,7 @@ static void render_frame(struct menu *menu) {
cairo_paint(cairo); cairo_paint(cairo);
cairo_restore(cairo); cairo_restore(cairo);
render_to_cairo(menu, cairo); render_menu(menu, cairo);
int scale = menu->output ? menu->output->scale : 1; int scale = menu->output ? menu->output->scale : 1;
menu->current = get_next_buffer(menu->shm, menu->current = get_next_buffer(menu->shm,
@ -537,7 +547,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_SHIFT,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
size_t len = strlen(menu->text); size_t len = strlen(menu->input);
if (ctrl) { if (ctrl) {
// Emacs-style line editing bindings // Emacs-style line editing bindings
@ -588,7 +598,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
case XKB_KEY_k: case XKB_KEY_k:
// Delete right // Delete right
menu->text[menu->cursor] = '\0'; menu->input[menu->cursor] = '\0';
match_items(menu); match_items(menu);
render_frame(menu); render_frame(menu);
return; return;
@ -600,10 +610,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
return; return;
case XKB_KEY_w: case XKB_KEY_w:
// Delete word // Delete word
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] == ' ') { while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
insert(menu, NULL, nextrune(menu, -1) - menu->cursor); insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
} }
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') { while (menu->cursor > 0 && menu->input[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);
@ -643,10 +653,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
case XKB_KEY_Left: case XKB_KEY_Left:
case XKB_KEY_KP_Left: case XKB_KEY_KP_Left:
// Move to beginning of word // Move to beginning of word
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] == ' ') { while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
menu->cursor = nextrune(menu, -1); menu->cursor = nextrune(menu, -1);
} }
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') { while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') {
menu->cursor = nextrune(menu, -1); menu->cursor = nextrune(menu, -1);
} }
render_frame(menu); render_frame(menu);
@ -654,10 +664,10 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
case XKB_KEY_Right: case XKB_KEY_Right:
case XKB_KEY_KP_Right: case XKB_KEY_KP_Right:
// Move to end of word // Move to end of word
while (menu->cursor < len && menu->text[menu->cursor] == ' ') { while (menu->cursor < len && menu->input[menu->cursor] == ' ') {
menu->cursor = nextrune(menu, +1); menu->cursor = nextrune(menu, +1);
} }
while (menu->cursor < len && menu->text[menu->cursor] != ' ') { while (menu->cursor < len && menu->input[menu->cursor] != ' ') {
menu->cursor = nextrune(menu, +1); menu->cursor = nextrune(menu, +1);
} }
render_frame(menu); render_frame(menu);
@ -676,11 +686,11 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
case XKB_KEY_Return: case XKB_KEY_Return:
case XKB_KEY_KP_Enter: case XKB_KEY_KP_Enter:
if (shift) { if (shift) {
puts(menu->text); puts(menu->input);
fflush(stdout); fflush(stdout);
menu->run = false; menu->run = false;
} else { } else {
char *text = menu->sel ? menu->sel->text : menu->text; char *text = menu->sel ? menu->sel->text : menu->input;
puts(text); puts(text);
fflush(stdout); fflush(stdout);
if (!ctrl) { if (!ctrl) {
@ -767,9 +777,9 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
if (!menu->sel) { if (!menu->sel) {
return; return;
} }
menu->cursor = strnlen(menu->sel->text, sizeof menu->text - 1); menu->cursor = strnlen(menu->sel->text, sizeof menu->input - 1);
memcpy(menu->text, menu->sel->text, menu->cursor); memcpy(menu->input, menu->sel->text, menu->cursor);
menu->text[menu->cursor] = '\0'; menu->input[menu->cursor] = '\0';
match_items(menu); match_items(menu);
render_frame(menu); render_frame(menu);
break; break;
@ -908,7 +918,7 @@ static const struct wl_registry_listener registry_listener = {
}; };
static void read_stdin(struct menu *menu) { static void read_stdin(struct menu *menu) {
char buf[sizeof menu->text], *p; char buf[sizeof menu->input], *p;
struct item *item, **end; struct item *item, **end;
for(end = &menu->items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) { for(end = &menu->items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) {