|
|
|
|
@ -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;
|
|
|
|
|
|