From 61e362add9e1485bec1ab8261d729016850ec270 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 22 Oct 2024 08:11:37 -0400 Subject: [PATCH 1/9] mac: arrange for arm64 run on arm64 Makes 9term.app work again (not put you in an x86_64 jail). --- mac/9term.app/Contents/MacOS/9term | 8 ++++++-- mac/Plumb.app/Contents/MacOS/plumb | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mac/9term.app/Contents/MacOS/9term b/mac/9term.app/Contents/MacOS/9term index b5a46bc8..04eb042c 100755 --- a/mac/9term.app/Contents/MacOS/9term +++ b/mac/9term.app/Contents/MacOS/9term @@ -3,12 +3,16 @@ fshell=$(finger $(whoami) | sed -n 's/.*Shell: //p' | sed 1q) SHELL=${fshell:-$SHELL} PLAN9=${PLAN9:-/usr/local/plan9} cd $HOME +arch=x86_64 +if arch -arch arm64 date >/dev/null 2>&1; then + arch=arm64 +fi case "$SHELL" in */rc) echo ' if(! ~ $PLAN9/bin $path) path=($path $PLAN9/bin) - $PLAN9/bin/9term -l -W600x800 & + arch -arch '$arch' $PLAN9/bin/9term -l -W600x800 & ' | $SHELL -l exit 0 ;; @@ -24,6 +28,6 @@ if ! [[ :$PATH: =~ :$PLAN9/bin: ]] then PATH=$PATH:$PLAN9/bin fi -$PLAN9/bin/9term -l -W600x800 & +arch -arch $arch $PLAN9/bin/9term -l -W600x800 & exit 0 diff --git a/mac/Plumb.app/Contents/MacOS/plumb b/mac/Plumb.app/Contents/MacOS/plumb index 850ec0e0..b3f15330 100755 --- a/mac/Plumb.app/Contents/MacOS/plumb +++ b/mac/Plumb.app/Contents/MacOS/plumb @@ -3,6 +3,10 @@ if [ -e ~/.bashrc ] ; then . ~/.bashrc fi +arch=x86_64 +if arch -arch arm64 date >/dev/null 2>&1; then + arch=arm64 +fi PLAN9=${PLAN9:-/usr/local/plan9} bin=$PLAN9/bin @@ -10,5 +14,5 @@ IFS=$'\n' for file in $($bin/macargv) do - $bin/macedit "$file" + arch -arch $arch $bin/macedit "$file" done From 6dffdd6b08a805c68af5990d118294c29b59d5dc Mon Sep 17 00:00:00 2001 From: David Arroyo Date: Thu, 28 Nov 2024 16:30:25 +0100 Subject: [PATCH 2/9] Fix race condition on attach and mouse track on warp I tried running the wayland devdraw implementation on Sway 1.10, wlroots 0.18 and encountered the error: xdg_surface#13: error 3: xdg_surface has never been configured According to https://wayland.app/protocols/xdg-shell#xdg_surface , a client must commit a surface without a buffer, *wait* for the first configure request from the compositor, ack it, and *only then* can it proceed to attach a buffer to the surface and tell wayland to display it. This was caused by the following sequence of events: 1. devdraw starts, enters gfx_main 2. `gfx_main` calls `gfx_started`, which spawns the `serveproc` thread 3. `gfx_main` enters `wl_display_dispatch`, flushing any buffered requests to the compositor, and enters `wl_display_poll()` to wait for incoming messages 4. `serveproc` calls `rpc_attach`, sets up the surface, and buffers a commit. The race is between #3 and #4. If #3 happens first, the buffered commit just sits there until `rpc_flush` is called, which calls `wl_display_flush()`, but at that point a buffer is attached too quickly for the configure to happen. This commit fixes the race by adding a `configured` field to the WaylandClient and using it to guard `rpc_flush`. In addition, I found that mouse warping, at least in sway, would move the cursor but future mouse presses would register at the old location until I moved the mouse. So I added a call to gfx_mousetrack to the end of `rpc_setmouse`. --- src/cmd/devdraw/wayland.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 253e427a..5391d77e 100644 --- a/src/cmd/devdraw/wayland.c +++ b/src/cmd/devdraw/wayland.c @@ -65,6 +65,9 @@ struct WaylandClient { struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; + // Initial configure call is complete + int configured; + // A callback when wl_surface is ready for the next frame. // Currently this is not used for drawing, // but as a hack for implementing key repeat @@ -368,10 +371,11 @@ static const struct wl_buffer_listener wl_buffer_listener = { static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { DEBUG("xdg_surface_configure\n"); const Client* c = data; - const WaylandClient *wl = c->view; + WaylandClient *wl = (WaylandClient*) c->view; qlock(&wayland_lock); xdg_surface_ack_configure(wl->xdg_surface, serial); + wl->configured = 1; qunlock(&wayland_lock); DEBUG("xdg_surface_configure: returned\n"); @@ -981,7 +985,15 @@ static void rpc_setmouse(Client *c, Point p) { wl_surface_commit(wl->wl_surface); zwp_locked_pointer_v1_destroy(lock); + wl->mouse_x = wl_fixed_to_int(x) * wl_output_scale_factor; + wl->mouse_y = wl_fixed_to_int(y) * wl_output_scale_factor; + + int mx = wl->mouse_x; + int my = wl->mouse_y; + int mb = wl->buttons; + qunlock(&wayland_lock); + gfx_mousetrack(c, mx, my, mb, nsec()/1000000); } static void rpc_topwin(Client*) { @@ -1017,14 +1029,16 @@ static void rpc_flush(Client *c, Rectangle r) { WaylandClient *wl = (WaylandClient*) c->view; qlock(&wayland_lock); - int w = Dx(wl->memimage->r); - int h = Dy(wl->memimage->r); - WaylandBuffer *b = get_xrgb8888_buffer(w, h); - memcpy(b->data, (char*) wl->memimage->data->bdata, b->size); - wl_surface_attach(wl->wl_surface, b->wl_buffer, 0, 0); - wl_surface_damage_buffer(wl->wl_surface, r.min.x, r.min.y, Dx(r), Dy(r)); - wl_surface_commit(wl->wl_surface); - wl_display_flush(wl_display); + if (wl->configured) { + int w = Dx(wl->memimage->r); + int h = Dy(wl->memimage->r); + WaylandBuffer *b = get_xrgb8888_buffer(w, h); + memcpy(b->data, (char*) wl->memimage->data->bdata, b->size); + wl_surface_attach(wl->wl_surface, b->wl_buffer, 0, 0); + wl_surface_damage_buffer(wl->wl_surface, r.min.x, r.min.y, Dx(r), Dy(r)); + wl_surface_commit(wl->wl_surface); + wl_display_flush(wl_display); + } qunlock(&wayland_lock); } @@ -1091,6 +1105,7 @@ Memimage *rpc_attach(Client *c, char *label, char *winsize) { c->displaydpi = 110 * wl_output_scale_factor; wl_surface_set_buffer_scale(wl->wl_surface, wl_output_scale_factor); wl_surface_commit(wl->wl_surface); + wl_display_flush(wl_display); qunlock(&wayland_lock); return wl->memimage; From a5d6857a3b912b43c88ef298c28d13d4623f9ef0 Mon Sep 17 00:00:00 2001 From: Anthony Sorace Date: Wed, 29 Jan 2025 10:27:03 -0800 Subject: [PATCH 3/9] man: don't paginate when using nroff This tells bin/man to set the register L to very high to avoid pagination and updates tmac/tmac.an to use that value, if it's set, to set the page length. This is per Plan 9's rc/bin/man and sys/lib/tmac/tmac.an. --- bin/man | 11 ++++++----- tmac/tmac.an | 4 +++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/bin/man b/bin/man index 1b0a1a69..07051e19 100755 --- a/bin/man +++ b/bin/man @@ -18,6 +18,7 @@ fn roff { } if not { Nflag=-N + Lflag='-rL1000i' } if(~ $x *eqn*) preproc=($preproc eqn) @@ -26,15 +27,15 @@ fn roff { switch($#preproc) { case 0 - {echo -n $FONTS; cat $2< /dev/null} | troff $Nflag -$MAN + {echo -n $FONTS; cat $2< /dev/null} | troff $Nflag $Lflag -$MAN case 1 - {echo -n $FONTS; cat $2< /dev/null} | $preproc | troff $Nflag -$MAN + {echo -n $FONTS; cat $2< /dev/null} | $preproc | troff $Nflag $Lflag -$MAN case 2 - {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | troff $Nflag -$MAN + {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | troff $Nflag $Lflag -$MAN case 3 - {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | $preproc(3) | | troff $Nflag -$MAN + {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | $preproc(3) | | troff $Nflag $Lflag -$MAN case * - {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | $preproc(3) | | $preproc(4) | troff $Nflag -$MAN + {echo -n $FONTS; cat $2< /dev/null} | $preproc(1) | $preproc(2) | $preproc(3) | | $preproc(4) | troff $Nflag $Lflag -$MAN } } diff --git a/tmac/tmac.an b/tmac/tmac.an index 02b31bbf..39399840 100644 --- a/tmac/tmac.an +++ b/tmac/tmac.an @@ -479,7 +479,9 @@ .if t \{.ds R ® .ds S \s\n()S ..\} -.if n \{.nr )L 11i +.if n \{.ie \nL<=0 .nr )L 11i +.el \{.nr )L \nLu +.nr V 0\} .nr LL 6.5i .nr )O .463i .if '\*(.T'think' \{.nrLL 80n From 3fdc76f128a571b181417a07d78aedd7dbbbb72c Mon Sep 17 00:00:00 2001 From: David Arroyo Date: Sat, 1 Feb 2025 21:52:41 +0100 Subject: [PATCH 4/9] Fix unexpected devdraw crashes on sway I found sway 1.10 and wlroots 0.18.2 will occasionally generate wl_keyboard::keymap events with an empty keymap. I do not have a reliable reproduction for this, but it seems to occur when switching back and forth between workspaces with the keyboard. This also fixes the issue where devdraw can go into a busy loop if the compositor goes away and wl_display_dispatch() returns -1. --- src/cmd/devdraw/wayland.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 5391d77e..9683ff77 100644 --- a/src/cmd/devdraw/wayland.c +++ b/src/cmd/devdraw/wayland.c @@ -616,8 +616,13 @@ static const struct wl_pointer_listener pointer_listener = { void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { - DEBUG("wl_keyboard_keymap\n"); + DEBUG("wl_keyboard_keymap(format=%d, fd=%d, size=%d)\n", format, fd, size); char *keymap = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (keymap == MAP_FAILED) { + DEBUG("wl_keyboard_keymap: %s", strerror(errno)); + return; + } + Client* c = data; WaylandClient *wl = (WaylandClient*) c->view; qlock(&wayland_lock); @@ -852,8 +857,9 @@ void gfx_main(void) { entered_gfx_loop = 1; gfx_started(); DEBUG("gfx_main: entering loop\n"); - while (wl_display_dispatch(wl_display)) + while (wl_display_dispatch(wl_display) > 0 || errno == EAGAIN) ; + sysfatal("wl_display_dispatch: %r"); } static void rpc_resizeimg(Client*) { From 12e55a0733b2f200df6748a0912a1bc5459cf1e4 Mon Sep 17 00:00:00 2001 From: David Arroyo Date: Sun, 2 Feb 2025 11:05:21 +0100 Subject: [PATCH 5/9] Only register repeat callbacks when repeat active This change splits scroll repeat and key repeat into separate callbacks, and only registers them when a key is pressed or scrolling is active, respectively. The key repeat logic is changed to support key repetitions higher than the frame rate. The new logic will also accomodate key repeat parameters set by the compositor, although the comment about us not receiving that configuration event is still valid. --- src/cmd/devdraw/wayland.c | 123 ++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 9683ff77..7e4a0c01 100644 --- a/src/cmd/devdraw/wayland.c +++ b/src/cmd/devdraw/wayland.c @@ -50,7 +50,12 @@ struct WaylandClient { // State for key repeat for keyboard keys. int repeat_rune; - int repeat_next_ms; + int repeat_start_ms; + + // Key repeat configuration. Can be changed by + // wl_surface_repeat_info events. + int repeat_interval_ms; + int repeat_delay_ms; // State for "key repeat" for the mouse scroll wheel. // This allows touchpad devices to have accelerated scrolling. @@ -68,11 +73,11 @@ struct WaylandClient { // Initial configure call is complete int configured; - // A callback when wl_surface is ready for the next frame. - // Currently this is not used for drawing, - // but as a hack for implementing key repeat - // without needing to implement our own timer thread/events. - struct wl_callback *wl_callback; + // These are called each frame while the key is pressed + // or scrolling is active, to implement key repeat and + // inertial scrolling. + struct wl_callback *wl_key_repeat_callback; + struct wl_callback *wl_scroll_repeat_callback; // The mouse pointer and the surface for the current cursor. struct wl_pointer *wl_pointer; @@ -422,27 +427,59 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { .close = xdg_toplevel_close, }; -static const struct wl_callback_listener wl_callback_listener; +static const struct wl_callback_listener wl_callback_key_repeat_listener; + +static void wl_callback_key_repeat(void *data, struct wl_callback *wl_callback, uint32_t time) { + int dt = 0; + int repetitions = 0; + int repeat_rune = 0; -// The callback is called per-frame. -// It is currently only used to implement key repeat. -static void wl_callback_done(void *data, struct wl_callback *wl_callback, uint32_t time) { Client* c = data; WaylandClient *wl = (WaylandClient*) c->view; - qlock(&wayland_lock); - - // Request another callback for the next frame. - // TODO: Only request a callback if we are still repeating a key. wl_callback_destroy(wl_callback); + + qlock(&wayland_lock); + dt = time - wl->repeat_start_ms; + + if (!wl->repeat_interval_ms || !wl->repeat_rune) + goto done; + + // There is an initial delay for repetition to start, so + // repeat_start_ms can be in the future. + if (wl->repeat_start_ms > time || wl->repeat_interval_ms > dt) + goto next_frame; + + repeat_rune = wl->repeat_rune; + repetitions = dt / wl->repeat_interval_ms; + + // Incrementing this way, rather than setting start to now, + // avoids losing fractional time to integer division. + wl->repeat_start_ms += repetitions * wl->repeat_interval_ms; + +next_frame: wl_callback = wl_surface_frame(wl->wl_surface); - wl_callback_add_listener(wl_callback, &wl_callback_listener, c); + wl_callback_add_listener(wl_callback, &wl_callback_key_repeat_listener, c); wl_surface_commit(wl->wl_surface); - int repeat_rune = 0; - if (wl->repeat_rune && time >= wl->repeat_next_ms) { - repeat_rune = wl->repeat_rune; - wl->repeat_next_ms = time + key_repeat_ms; +done: + qunlock(&wayland_lock); + for(int i = 0; i < repetitions; i++) { + gfx_keystroke(c, repeat_rune); } +} + +static const struct wl_callback_listener wl_callback_key_repeat_listener = { + .done = wl_callback_key_repeat, +}; + +static const struct wl_callback_listener wl_callback_scroll_listener; + +static void wl_callback_scroll_repeat(void *data, struct wl_callback *wl_callback, uint32_t time) { + Client* c = data; + WaylandClient *wl = (WaylandClient*) c->view; + + wl_callback_destroy(wl_callback); + qlock(&wayland_lock); int x = wl->mouse_x; int y = wl->mouse_y; @@ -457,17 +494,20 @@ static void wl_callback_done(void *data, struct wl_callback *wl_callback, uint32 } } - qunlock(&wayland_lock); - if (repeat_rune) { - gfx_keystroke(c, repeat_rune); + if (wl->repeat_scroll_count > 0) { + wl_callback = wl_surface_frame(wl->wl_surface); + wl_callback_add_listener(wl_callback, &wl_callback_scroll_listener, c); + wl_surface_commit(wl->wl_surface); } + qunlock(&wayland_lock); + if (repeat_scroll_button) { gfx_mousetrack(c, x, y, repeat_scroll_button, (uint) time); } } -static const struct wl_callback_listener wl_callback_listener = { - .done = wl_callback_done, +static const struct wl_callback_listener wl_callback_scroll_listener = { + .done = wl_callback_scroll_repeat, }; void wl_pointer_enter(void *data,struct wl_pointer *wl_pointer, uint32_t serial, @@ -598,6 +638,9 @@ void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl->repeat_scroll_button = b; wl->repeat_scroll_count = mag; wl->repeat_scroll_next_ms = time + scroll_repeat_ms/wl->repeat_scroll_count; + wl->wl_scroll_repeat_callback = wl_surface_frame(wl->wl_surface); + wl_callback_add_listener(wl->wl_scroll_repeat_callback, + &wl_callback_scroll_listener, c); } b |= wl->buttons; @@ -775,12 +818,16 @@ void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, break; } - qunlock(&wayland_lock); - if (state == WL_KEYBOARD_KEY_STATE_PRESSED && rune != 0) { + if (wl->repeat_interval_ms && state == WL_KEYBOARD_KEY_STATE_PRESSED && rune != 0) { wl->repeat_rune = rune; - wl->repeat_next_ms = time + key_repeat_delay_ms; - gfx_keystroke(c, rune); + wl->repeat_start_ms = time + wl->repeat_delay_ms; + wl->wl_key_repeat_callback = wl_surface_frame(wl->wl_surface); + wl_callback_add_listener(wl->wl_key_repeat_callback, + &wl_callback_key_repeat_listener, c); } + qunlock(&wayland_lock); + if (state == WL_KEYBOARD_KEY_STATE_PRESSED && rune != 0) + gfx_keystroke(c, rune); } void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, @@ -797,12 +844,25 @@ void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, qunlock(&wayland_lock); } -// TODO: Use this to set key repeat. // Currently we don't bind the keyboard with the correct version to get this event. void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay) { DEBUG("wl_keyboard_repeat_info(rate=%d, delay=%d)\n", (int) rate, (int) delay); + Client* c = data; + WaylandClient *wl = (WaylandClient*) c->view; + int interval = 0; + + // rate is in keystrokes per second. Capping to 1k simplifies + // the code. + rate = rate > 1000 ? 1000 : rate; + if (rate > 0) + interval = 1000 / rate; + + qlock(&wayland_lock); + wl->repeat_interval_ms = interval; + wl->repeat_delay_ms = delay; + qunlock(&wayland_lock); } static const struct wl_keyboard_listener keyboard_listener = { @@ -1069,6 +1129,8 @@ Memimage *rpc_attach(Client *c, char *label, char *winsize) { c->impl = &wayland_impl; c->view = wl; + wl->repeat_interval_ms = key_repeat_ms; + wl->repeat_delay_ms = key_repeat_ms; wl->wl_surface = wl_compositor_create_surface(wl_compositor); wl->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, wl->wl_surface); @@ -1078,9 +1140,6 @@ Memimage *rpc_attach(Client *c, char *label, char *winsize) { xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, c); xdg_toplevel_set_title(wl->xdg_toplevel, label); - wl->wl_callback = wl_surface_frame(wl->wl_surface); - wl_callback_add_listener(wl->wl_callback, &wl_callback_listener, c); - wl->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(wl->wl_pointer, &pointer_listener, c); wl->wl_surface_cursor = wl_compositor_create_surface(wl_compositor); From 70a7a1c03677278afd42bb1c766753b277a98367 Mon Sep 17 00:00:00 2001 From: David Arroyo Date: Sat, 22 Feb 2025 12:33:49 +0100 Subject: [PATCH 6/9] Receive key repeat info from compositor Upgrade to version 4 of the wl_seat interface which adds the wl_keyboard::repeat_info event allowing the compositor to configure key repeat delay and rate. --- src/cmd/devdraw/wayland.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 7e4a0c01..909015de 100644 --- a/src/cmd/devdraw/wayland.c +++ b/src/cmd/devdraw/wayland.c @@ -164,7 +164,7 @@ static void registry_global(void *data, struct wl_registry *wl_registry, &xdg_wm_base_interface, 1); } else if (strcmp(interface, wl_seat_interface.name) == 0) { - wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 1); + wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { wl_data_device_manager = wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 2); @@ -844,7 +844,6 @@ void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, qunlock(&wayland_lock); } -// Currently we don't bind the keyboard with the correct version to get this event. void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay) { DEBUG("wl_keyboard_repeat_info(rate=%d, delay=%d)\n", From 08a4f8abe423f653c80ed5ec9c01315b58659578 Mon Sep 17 00:00:00 2001 From: David Arroyo Date: Tue, 18 Mar 2025 13:24:09 +0100 Subject: [PATCH 7/9] move declarations to first use --- src/cmd/devdraw/wayland.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 909015de..0b13cf65 100644 --- a/src/cmd/devdraw/wayland.c +++ b/src/cmd/devdraw/wayland.c @@ -430,33 +430,31 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { static const struct wl_callback_listener wl_callback_key_repeat_listener; static void wl_callback_key_repeat(void *data, struct wl_callback *wl_callback, uint32_t time) { - int dt = 0; - int repetitions = 0; - int repeat_rune = 0; - Client* c = data; WaylandClient *wl = (WaylandClient*) c->view; wl_callback_destroy(wl_callback); qlock(&wayland_lock); - dt = time - wl->repeat_start_ms; - if (!wl->repeat_interval_ms || !wl->repeat_rune) + int repetitions = 0; + int repeat_rune = wl->repeat_rune; + + if (wl->repeat_interval_ms == 0 || wl->repeat_rune == 0) { goto done; + } + + int dt = time - wl->repeat_start_ms; // There is an initial delay for repetition to start, so // repeat_start_ms can be in the future. - if (wl->repeat_start_ms > time || wl->repeat_interval_ms > dt) - goto next_frame; + if (wl->repeat_start_ms < time && wl->repeat_interval_ms <= dt) { + repetitions = dt / wl->repeat_interval_ms; - repeat_rune = wl->repeat_rune; - repetitions = dt / wl->repeat_interval_ms; + // Incrementing this way, rather than setting start to now, + // avoids losing fractional time to integer division. + wl->repeat_start_ms += repetitions * wl->repeat_interval_ms; + } - // Incrementing this way, rather than setting start to now, - // avoids losing fractional time to integer division. - wl->repeat_start_ms += repetitions * wl->repeat_interval_ms; - -next_frame: wl_callback = wl_surface_frame(wl->wl_surface); wl_callback_add_listener(wl_callback, &wl_callback_key_repeat_listener, c); wl_surface_commit(wl->wl_surface); From abad9e2dec4e90983724f77df4502891f6965875 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 13 Apr 2025 17:25:38 +0200 Subject: [PATCH 8/9] fix build when WSYSTYPE=wayland in local cfg --- src/cmd/fontsrv/freetyperules.sh | 2 +- src/cmd/fontsrv/mkwsysrules.sh | 2 +- src/cmd/fontsrv/wayland.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/cmd/fontsrv/wayland.c diff --git a/src/cmd/fontsrv/freetyperules.sh b/src/cmd/fontsrv/freetyperules.sh index 5ca91573..ed2c9b0e 100644 --- a/src/cmd/fontsrv/freetyperules.sh +++ b/src/cmd/fontsrv/freetyperules.sh @@ -1,6 +1,6 @@ #!/bin/sh -if [ "x$1" = "xx11" ]; then +if [ "x$1" = "xx11" -o "x$1" = "xwayland" ]; then if [ "x$2" = "x" ]; then i="-I/usr/include" else diff --git a/src/cmd/fontsrv/mkwsysrules.sh b/src/cmd/fontsrv/mkwsysrules.sh index 1b585c1a..a8cf5954 100644 --- a/src/cmd/fontsrv/mkwsysrules.sh +++ b/src/cmd/fontsrv/mkwsysrules.sh @@ -48,7 +48,7 @@ echo 'WSYSTYPE='$WSYSTYPE echo 'X11='$X11 echo 'X11H='$X11H -if [ $WSYSTYPE = x11 ]; then +if [ $WSYSTYPE = x11 -o $WSYSTYPE = wayland ]; then echo 'CFLAGS=$CFLAGS '$X11H echo 'HFILES=$HFILES $XHFILES' XO=`ls x11-*.c 2>/dev/null | sed 's/\.c$/.o/'` diff --git a/src/cmd/fontsrv/wayland.c b/src/cmd/fontsrv/wayland.c new file mode 100644 index 00000000..53a00c66 --- /dev/null +++ b/src/cmd/fontsrv/wayland.c @@ -0,0 +1 @@ +#include "x11.c" From ab8c5116d5507867e81e50d4607b924c22b2a76c Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 13 Apr 2025 20:37:42 +0200 Subject: [PATCH 9/9] short comment explaining the wayland.c include --- src/cmd/fontsrv/wayland.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/fontsrv/wayland.c b/src/cmd/fontsrv/wayland.c index 53a00c66..f10d3b6b 100644 --- a/src/cmd/fontsrv/wayland.c +++ b/src/cmd/fontsrv/wayland.c @@ -1 +1,3 @@ +// note: the fontsrv implementation for X11 and wayland are the same. +// this non-standard include is an alternative to copying the file. #include "x11.c"