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/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 diff --git a/src/cmd/devdraw/wayland.c b/src/cmd/devdraw/wayland.c index 253e427a..0b13cf65 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. @@ -65,11 +70,14 @@ struct WaylandClient { struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; - // 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; + // Initial configure call is complete + int configured; + + // 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; @@ -156,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); @@ -368,10 +376,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"); @@ -418,27 +427,57 @@ 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; -// 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) { +static void wl_callback_key_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); - // Request another callback for the next frame. - // TODO: Only request a callback if we are still repeating a key. - wl_callback_destroy(wl_callback); + 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) { + 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; + } + 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; @@ -453,17 +492,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, @@ -594,6 +636,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; @@ -612,8 +657,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); @@ -766,12 +816,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, @@ -788,12 +842,24 @@ 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 = { @@ -848,8 +914,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*) { @@ -981,7 +1048,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 +1092,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); } @@ -1049,6 +1126,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); @@ -1058,9 +1137,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); @@ -1091,6 +1167,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; 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..f10d3b6b --- /dev/null +++ b/src/cmd/fontsrv/wayland.c @@ -0,0 +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" 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