diff --git a/LICENSE b/LICENSE index 921ddb0..26ff2da 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -Copyright (c) 2023-2024 sewn +Copyright (c) 2023-2025 sewn Copyright (c) 2015 Eric Pruitt Copyright (c) 2024 Forrest Bushstone Copyright (c) 2018-2019 Henrik Nyman diff --git a/drwl.h b/drwl.h index a506247..5b36f34 100644 --- a/drwl.h +++ b/drwl.h @@ -1,7 +1,7 @@ /* * drwl - https://codeberg.org/sewn/drwl * - * Copyright (c) 2023-2024 sewn + * Copyright (c) 2023-2025 sewn * Copyright (c) 2024 notchoc * * Permission is hereby granted, free of charge, to any person obtaining @@ -81,7 +81,6 @@ utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) static int drwl_init(void) { - fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); } diff --git a/mew.c b/mew.c index b6ee87d..44aaf89 100644 --- a/mew.c +++ b/mew.c @@ -284,7 +284,7 @@ drawmenu(void) errno = 0; if (!(buf = bufpool_getbuf(&pool, shm, mw, mh))) - die("failed to find available buffer"); + die(errno ? "bufpool_getbuf:" : "no buffer available"); drwl_setimage(drw, buf->image); drwl_setscheme(drw, colors[SchemeNorm]); @@ -419,7 +419,7 @@ insert(const char *str, ssize_t n) return; /* move existing text out of the way, insert new text, and update cursor */ memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); - if (n > 0) + if (str) memcpy(&text[cursor], str, n); cursor += n; match(); @@ -694,6 +694,20 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, kbd.xkb_state = xkb_state_new(kbd.xkb_keymap); } +static void +keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface) +{ + /* + * In dmenu(1), if the keyboard cannot be grabbed, it will + * immediately exit. This is done before dmenu is initialized, + * but can't be the same for Wayland. If a new layer surface + * wants keyboard, it will get keyboard, set_exclusivity doesn't + * seem to work. + */ + die("lost keyboard"); +} + static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) @@ -754,7 +768,7 @@ keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard, static const struct wl_keyboard_listener keyboard_listener = { .keymap = keyboard_handle_keymap, .enter = noop, - .leave = noop, + .leave = keyboard_handle_leave, .key = keyboard_handle_key, .modifiers = keyboard_handle_modifiers, .repeat_info = keyboard_handle_repeat_info, @@ -770,6 +784,7 @@ layer_surface_handle_configure(void *data, struct zwlr_layer_surface_v1 *layer_s mw = width * scale; mh = height * scale; inputw = mw / 3; /* input width: ~33% of output width */ + match(); zwlr_layer_surface_v1_ack_configure(layer_surface, serial); drawmenu(); } @@ -789,14 +804,12 @@ static void surface_handle_preferred_scale(void *data, struct wl_surface *wl_surface, int32_t factor) { + if (scale == factor) + return; scale = factor; loadfonts(); - /* FIXME: - * Use a callback to ensure the 'configure' event - * is sent before the draw, which changes the dimensions - * properly for the update in scale. - */ + /* the scale of the surface is only known after an initial draw, not before :( */ zwlr_layer_surface_v1_set_size(layer_surface, 0, mh / scale); redraw(); } @@ -923,33 +936,19 @@ run(void) { kbd.repeat.timer, POLLIN }, }; - match(); - + running = 1; while (running) { - if (wl_display_prepare_read(display) < 0) - if (wl_display_dispatch_pending(display) < 0) - die("wl_display_dispatch_pending:"); + wl_display_flush(display); - if (wl_display_flush(display) < 0) - die("wl_display_flush:"); - - if (poll(pfds, LENGTH(pfds), -1) < 0) { - wl_display_cancel_read(display); + if (poll(pfds, LENGTH(pfds), -1) < 0) die("poll:"); - } + + if (pfds[0].revents & POLLIN) + if (wl_display_dispatch(display) < 0) + die("display dispatch failed"); if (pfds[1].revents & POLLIN) keyboard_repeat(); - - if (!(pfds[0].revents & POLLIN)) { - wl_display_cancel_read(display); - continue; - } - - if (wl_display_read_events(display) < 0) - die("wl_display_read_events:"); - if (wl_display_dispatch_pending(display) < 0) - die("wl_display_dispatch_pending:"); } } @@ -995,11 +994,10 @@ setup(void) (top ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ) | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, -1); - zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, true); + zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, 1); zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, NULL); wl_surface_commit(surface); - running = 1; } static void diff --git a/poolbuf.h b/poolbuf.h deleted file mode 100644 index b22d37f..0000000 --- a/poolbuf.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * poolbuf - https://codeberg.org/sewn/drwl - * - * Copyright (c) 2023-2024 sewn - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include - -typedef struct { - struct wl_buffer *wl_buf; - int32_t stride; - int32_t size; - void *data; -} PoolBuf; - -#if defined(__linux__) || defined(___FreeBSD__) -#ifdef __linux__ -#include -#endif -#define __POOLBUF_HAS_MEMFD_CREATE -int memfd_create(const char *, unsigned); -#else -static void -randname(char *buf) -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - long r = ts.tv_nsec; - for (int i = 0; i < 6; ++i) { - buf[i] = 'A'+(r&15)+(r&16)*2; - r >>= 5; - } -} - -static int -create_shm(void) -{ - char name[] = "/poolbuf-XXXXXX"; - int retries = 100; - - do { - randname(name + sizeof(name) - 7); - --retries; - int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) { - shm_unlink(name); - return fd; - } - } while (retries > 0 && errno == EEXIST); - return -1; -} -#endif - -static void -poolbuf_destroy(PoolBuf *buf) -{ - wl_buffer_destroy(buf->wl_buf); - munmap(buf->data, buf->size); - free(buf); -} - -static void -poolbuf_buffer_release(void *data, struct wl_buffer *wl_buffer) -{ - PoolBuf *buf = data; - poolbuf_destroy(buf); -} - -static struct wl_buffer_listener poolbuf_buffer_listener = { - .release = poolbuf_buffer_release, -}; - -/* Caller must call poolbuf_destroy after finalizing usage if norelease is passed */ -static PoolBuf * -poolbuf_create(struct wl_shm *shm, - int32_t width, int32_t height, int32_t stride, int norelease) -{ - int fd; - void *data; - struct wl_shm_pool *shm_pool; - struct wl_buffer *wl_buf; - int32_t size = stride * height; - PoolBuf *buf; - -#ifdef __POOLBUF_HAS_MEMFD_CREATE - fd = memfd_create("poolbuf-shm-buffer-pool", - MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); -#else - fd = create_shm(); -#endif - if (fd < 0) - return NULL; - - if ((ftruncate(fd, size)) < 0) { - close(fd); - return NULL; - } - - data = mmap(NULL, size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) { - close(fd); - return NULL; - } - - shm_pool = wl_shm_create_pool(shm, fd, size); - wl_buf = wl_shm_pool_create_buffer(shm_pool, 0, - width, height, stride, WL_SHM_FORMAT_ARGB8888); - wl_shm_pool_destroy(shm_pool); - close(fd); - - buf = calloc(1, sizeof(PoolBuf)); - buf->wl_buf = wl_buf; - buf->stride = stride; - buf->size = size; - buf->data = data; - if (!norelease) - wl_buffer_add_listener(wl_buf, &poolbuf_buffer_listener, buf); - return buf; -}