mirror of
https://codeberg.org/adnano/wmenu.git
synced 2025-10-29 05:40:20 -04:00
Separate menu state from Wayland state
This commit is contained in:
parent
6a39269d2e
commit
6284eea24b
7 changed files with 577 additions and 508 deletions
179
menu.c
179
menu.c
|
|
@ -1,5 +1,4 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -19,10 +18,8 @@
|
|||
#include "menu.h"
|
||||
|
||||
#include "pango.h"
|
||||
#include "pool-buffer.h"
|
||||
#include "render.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "wayland.h"
|
||||
|
||||
// Creates and returns a new menu.
|
||||
struct menu *menu_create() {
|
||||
|
|
@ -38,38 +35,6 @@ struct menu *menu_create() {
|
|||
return menu;
|
||||
}
|
||||
|
||||
// Creates and returns a new keyboard.
|
||||
struct keyboard *keyboard_create(struct menu *menu, struct wl_keyboard *wl_keyboard) {
|
||||
struct keyboard *keyboard = calloc(1, sizeof(struct keyboard));
|
||||
keyboard->menu = menu;
|
||||
keyboard->keyboard = wl_keyboard;
|
||||
keyboard->context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
assert(keyboard->context != NULL);
|
||||
keyboard->repeat_timer = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
assert(keyboard->repeat_timer != -1);
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
// Sets the current keyboard.
|
||||
void menu_set_keyboard(struct menu *menu, struct keyboard *keyboard) {
|
||||
menu->keyboard = keyboard;
|
||||
}
|
||||
|
||||
// Creates and returns a new output.
|
||||
struct output *output_create(struct menu *menu, struct wl_output *wl_output) {
|
||||
struct output *output = calloc(1, sizeof(struct output));
|
||||
output->menu = menu;
|
||||
output->output = wl_output;
|
||||
output->scale = 1;
|
||||
return output;
|
||||
}
|
||||
|
||||
// Adds an output to the output list.
|
||||
void menu_add_output(struct menu *menu, struct output *output) {
|
||||
output->next = menu->output_list;
|
||||
menu->output_list = output;
|
||||
}
|
||||
|
||||
static bool parse_color(const char *color, uint32_t *result) {
|
||||
if (color[0] == '#') {
|
||||
++color;
|
||||
|
|
@ -170,6 +135,22 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
|
|||
menu->padding = height / 2;
|
||||
}
|
||||
|
||||
// Add an item to the menu.
|
||||
void menu_add_item(struct menu *menu, char *text) {
|
||||
struct item *item = calloc(1, sizeof *item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
item->text = text;
|
||||
|
||||
if (menu->lastitem) {
|
||||
menu->lastitem->next = item;
|
||||
} else {
|
||||
menu->items = item;
|
||||
}
|
||||
menu->lastitem = item;
|
||||
}
|
||||
|
||||
static void append_page(struct page *page, struct page **first, struct page **last) {
|
||||
if (*last) {
|
||||
(*last)->next = page;
|
||||
|
|
@ -246,7 +227,7 @@ static const char *fstrstr(struct menu *menu, const char *s, const char *sub) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void append_item(struct item *item, struct item **first, struct item **last) {
|
||||
static void append_match(struct item *item, struct item **first, struct item **last) {
|
||||
if (*last) {
|
||||
(*last)->next_match = item;
|
||||
} else {
|
||||
|
|
@ -300,11 +281,11 @@ static void match_items(struct menu *menu) {
|
|||
continue;
|
||||
}
|
||||
if (!tokc || !menu->strncmp(menu->input, item->text, input_len + 1)) {
|
||||
append_item(item, &lexact, &exactend);
|
||||
append_match(item, &lexact, &exactend);
|
||||
} else if (!menu->strncmp(tokv[0], item->text, tok_len)) {
|
||||
append_item(item, &lprefix, &prefixend);
|
||||
append_match(item, &lprefix, &prefixend);
|
||||
} else {
|
||||
append_item(item, &lsubstr, &substrend);
|
||||
append_match(item, &lsubstr, &substrend);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,45 +320,27 @@ static void match_items(struct menu *menu) {
|
|||
}
|
||||
}
|
||||
|
||||
// Read menu items from standard input.
|
||||
void read_menu_items(struct menu *menu) {
|
||||
if (menu->passwd) {
|
||||
// Don't read standard input in password mode
|
||||
calc_widths(menu);
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[sizeof menu->input];
|
||||
struct item **next = &menu->items;
|
||||
while (fgets(buf, sizeof buf, stdin)) {
|
||||
char *p = strchr(buf, '\n');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
}
|
||||
struct item *item = calloc(1, sizeof *item);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
item->text = strdup(buf);
|
||||
|
||||
*next = item;
|
||||
next = &item->next;
|
||||
}
|
||||
|
||||
// Process menu items.
|
||||
void menu_process_items(struct menu *menu) {
|
||||
calc_widths(menu);
|
||||
match_items(menu);
|
||||
}
|
||||
|
||||
static void insert(struct menu *menu, const char *s, ssize_t n) {
|
||||
if (strlen(menu->input) + n > sizeof menu->input - 1) {
|
||||
static void insert(struct menu *menu, const char *text, ssize_t len) {
|
||||
if (strlen(menu->input) + len > sizeof menu->input - 1) {
|
||||
return;
|
||||
}
|
||||
memmove(menu->input + menu->cursor + n, menu->input + menu->cursor,
|
||||
sizeof menu->input - menu->cursor - MAX(n, 0));
|
||||
if (n > 0 && s != NULL) {
|
||||
memcpy(menu->input + menu->cursor, s, n);
|
||||
memmove(menu->input + menu->cursor + len, menu->input + menu->cursor,
|
||||
sizeof menu->input - menu->cursor - MAX(len, 0));
|
||||
if (len > 0 && text != NULL) {
|
||||
memcpy(menu->input + menu->cursor, text, len);
|
||||
}
|
||||
menu->cursor += n;
|
||||
menu->cursor += len;
|
||||
}
|
||||
|
||||
// Add pasted text to the menu input.
|
||||
void menu_paste(struct menu *menu, const char *text, ssize_t len) {
|
||||
insert(menu, text, len);
|
||||
}
|
||||
|
||||
static size_t nextrune(struct menu *menu, int incr) {
|
||||
|
|
@ -417,14 +380,12 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
return;
|
||||
}
|
||||
|
||||
bool ctrl = xkb_state_mod_name_is_active(menu->keyboard->state,
|
||||
XKB_MOD_NAME_CTRL,
|
||||
struct xkb_state *state = context_get_xkb_state(menu->context);
|
||||
bool ctrl = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
|
||||
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
|
||||
bool meta = xkb_state_mod_name_is_active(menu->keyboard->state,
|
||||
XKB_MOD_NAME_ALT,
|
||||
bool meta = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT,
|
||||
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
|
||||
bool shift = xkb_state_mod_name_is_active(menu->keyboard->state,
|
||||
XKB_MOD_NAME_SHIFT,
|
||||
bool shift = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT,
|
||||
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
|
||||
|
||||
size_t len = strlen(menu->input);
|
||||
|
|
@ -501,32 +462,9 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
return;
|
||||
case XKB_KEY_Y:
|
||||
// Paste clipboard
|
||||
if (!menu->data_offer) {
|
||||
if (!context_paste(menu->context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int fds[2];
|
||||
if (pipe(fds) == -1) {
|
||||
// Pipe failed
|
||||
return;
|
||||
}
|
||||
wl_data_offer_receive(menu->data_offer, "text/plain", fds[1]);
|
||||
close(fds[1]);
|
||||
|
||||
wl_display_roundtrip(menu->display);
|
||||
|
||||
while (true) {
|
||||
char buf[1024];
|
||||
ssize_t n = read(fds[0], buf, sizeof(buf));
|
||||
if (n <= 0) {
|
||||
break;
|
||||
}
|
||||
insert(menu, buf, n);
|
||||
}
|
||||
close(fds[0]);
|
||||
|
||||
wl_data_offer_destroy(menu->data_offer);
|
||||
menu->data_offer = NULL;
|
||||
match_items(menu);
|
||||
render_menu(menu);
|
||||
return;
|
||||
|
|
@ -696,26 +634,6 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
|||
}
|
||||
}
|
||||
|
||||
// Frees the keyboard.
|
||||
static void free_keyboard(struct keyboard *keyboard) {
|
||||
wl_keyboard_release(keyboard->keyboard);
|
||||
xkb_state_unref(keyboard->state);
|
||||
xkb_keymap_unref(keyboard->keymap);
|
||||
xkb_context_unref(keyboard->context);
|
||||
free(keyboard);
|
||||
}
|
||||
|
||||
// Frees the outputs.
|
||||
static void free_outputs(struct menu *menu) {
|
||||
struct output *next = menu->output_list;
|
||||
while (next) {
|
||||
struct output *output = next;
|
||||
next = output->next;
|
||||
wl_output_destroy(output->output);
|
||||
free(output);
|
||||
}
|
||||
}
|
||||
|
||||
// Frees menu pages.
|
||||
static void free_pages(struct menu *menu) {
|
||||
struct page *next = menu->pages;
|
||||
|
|
@ -739,26 +657,9 @@ static void free_items(struct menu *menu) {
|
|||
|
||||
// Destroys the menu, freeing memory associated with it.
|
||||
void menu_destroy(struct menu *menu) {
|
||||
wl_registry_destroy(menu->registry);
|
||||
wl_compositor_destroy(menu->compositor);
|
||||
wl_shm_destroy(menu->shm);
|
||||
wl_seat_destroy(menu->seat);
|
||||
wl_data_device_manager_destroy(menu->data_device_manager);
|
||||
zwlr_layer_shell_v1_destroy(menu->layer_shell);
|
||||
free_outputs(menu);
|
||||
|
||||
free_keyboard(menu->keyboard);
|
||||
wl_data_device_destroy(menu->data_device);
|
||||
wl_surface_destroy(menu->surface);
|
||||
zwlr_layer_surface_v1_destroy(menu->layer_surface);
|
||||
xdg_activation_v1_destroy(menu->activation);
|
||||
|
||||
free_pages(menu);
|
||||
free_items(menu);
|
||||
|
||||
destroy_buffer(&menu->buffers[0]);
|
||||
destroy_buffer(&menu->buffers[1]);
|
||||
|
||||
wl_display_disconnect(menu->display);
|
||||
free(menu);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue