diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 7d923d1..212eef9 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -346,7 +346,7 @@ typedef struct wayland_protocol { void* context; } wayland_protocol_t; -typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*); +typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*, MwU32 version); typedef void(wl_destroy_func)(struct _MwLLWayland* wayland, wayland_protocol_t* data); typedef struct wayland_protocol_callback_table { @@ -567,6 +567,14 @@ struct _MwLLWayland { MwBool moving; + MwI64 keyboard_rate; + MwI32 keyboard_delay; + int last_pressed_key; + MwBool holding_key; + MwU64 next_elapsed; + struct timespec start_time; + struct timespec end_time; + cairo_surface_t* front_cs; cairo_surface_t* back_cs; cairo_t* front_cairo; diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index e6d6bd1..607ce82 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -42,7 +42,7 @@ static void new_protocol(void* data, struct wl_registry* registry, wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { - shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data)); + shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { self->common.supports_transparency = MwTRUE; @@ -313,7 +313,7 @@ struct zwp_primary_selection_source_v1_listener zwp_primary_selection_source_v1_ }; /* wl_data_device_manager setup function */ -static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->clipboard_manager.wl = wl_registry_bind(wayland->registry, name, &wl_data_device_manager_interface, 2); wayland->clipboard_source.wl = wl_data_device_manager_create_data_source(wayland->clipboard_manager.wl); @@ -346,7 +346,7 @@ static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* waylan } /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->clipboard_manager.zwp = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); wayland->clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(wayland->clipboard_manager.zwp); @@ -374,7 +374,7 @@ static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _Mw } /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->pointer_constraints = wl_registry_bind(wayland->registry, name, &zwp_pointer_constraints_v1_interface, 1); return NULL; } @@ -507,7 +507,7 @@ struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener = relative_pointer_motion}; /* zwp_primary_selection_device_manager_v1 setup function */ -static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->relative_pointer_manager = wl_registry_bind(wayland->registry, name, &zwp_relative_pointer_manager_v1_interface, 1); return NULL; } @@ -718,7 +718,7 @@ static void keyboard_leave(void* data, static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, - MwU32 time, + MwU32 _time, MwU32 key, MwU32 state) { MwLL self = data; @@ -727,7 +727,7 @@ static void keyboard_key(void* data, (void)wl_keyboard; (void)serial; - (void)time; + (void)_time; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; @@ -832,9 +832,14 @@ static void keyboard_key(void* data, MwLLDispatch(topmost_parent, key, &key); topmost_parent = topmost_parent->wayland.parent; } + self->wayland.holding_key = MwTRUE; + self->wayland.last_pressed_key = key; } else { MwLLDispatch(self, key_released, &key); + self->wayland.holding_key = MwFALSE; } + clock_gettime(CLOCK_REALTIME, &self->wayland.start_time); + self->wayland.next_elapsed = self->wayland.keyboard_delay; } } } @@ -889,12 +894,25 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) { arrpush(self->wayland.clipboard_devices_wl, device_ctx_wl); }; +static void keyboard_repeat_info(void* data, + struct wl_keyboard* wl_keyboard, + int32_t rate, + int32_t delay) { + MwLL self = data; + + (void)wl_keyboard; + + self->wayland.keyboard_rate = rate; + self->wayland.keyboard_delay = delay; +}; + struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_keymap, - .enter = keyboard_enter, - .leave = keyboard_leave, - .key = keyboard_key, - .modifiers = keyboard_modifiers, + .keymap = keyboard_keymap, + .enter = keyboard_enter, + .leave = keyboard_leave, + .key = keyboard_key, + .modifiers = keyboard_modifiers, + .repeat_info = keyboard_repeat_info, }; /* `wl_seat.name` callback */ @@ -978,14 +996,15 @@ void xdg_wm_base_ping(void* data, }; /* wl_seat setup function */ -static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { +static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + MwU32 ver = (version >= 4) ? 4 : 1; proto->listener = malloc(sizeof(struct wl_seat_listener)); ((struct wl_seat_listener*)proto->listener)->name = wl_seat_name; ((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities; - wl_seat_add_listener(wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, 1), proto->listener, ll); + wl_seat_add_listener(wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, ver), proto->listener, ll); return proto; } @@ -996,7 +1015,7 @@ static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_prot } /* wl_output setup function */ -static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll) { +static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll, MwU32 version) { ll->wayland.output = wl_registry_bind(ll->wayland.registry, name, &wl_output_interface, 1); wl_output_add_listener(ll->wayland.output, &output_listener, ll); @@ -1009,7 +1028,7 @@ static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_pr } /* wl_compositor setup function */ -static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->compositor = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); return NULL; @@ -1021,7 +1040,7 @@ static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, waylan } /* wl_subcompositor setup function */ -static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } else { @@ -1037,7 +1056,7 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way } /* xdg_wm_base setup function */ -static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); @@ -1055,7 +1074,7 @@ static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_ } /* xdg_wm_base setup function */ -static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->context = wl_registry_bind(wayland->registry, name, &wp_viewporter_interface, 1); @@ -1068,7 +1087,7 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan } /* zxdg_decoration_manager_v1 setup function */ -static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); zxdg_decoration_manager_v1_context_t* ctx = malloc(sizeof(zxdg_decoration_manager_v1_context_t)); proto->listener = NULL; @@ -1087,7 +1106,7 @@ static void zxdg_decoration_manager_v1_interface_destroy(struct _MwLLWayland* wa } /* wl_shm setup function */ -static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland->framebuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); wayland->backbuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); wayland->cursor.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); @@ -1100,7 +1119,7 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto (void)data; } -static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->context = wl_registry_bind(wayland->registry, name, &xdg_toplevel_icon_manager_v1_interface, 1); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 99ce624..939c668 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -1146,6 +1146,22 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.setting_wh = 0; } + clock_gettime(CLOCK_REALTIME, &handle->wayland.end_time); + + if(handle->wayland.holding_key) { + double elapsed = ((double)(handle->wayland.end_time.tv_sec - handle->wayland.start_time.tv_sec) * 1.0e9 + + (double)(handle->wayland.end_time.tv_nsec - handle->wayland.start_time.tv_nsec)) / + 1000000.0; + if(elapsed >= handle->wayland.next_elapsed) { + MwLL topmost_parent = handle; + while(topmost_parent->wayland.parent) { + MwLLDispatch(topmost_parent, key, &handle->wayland.last_pressed_key); + topmost_parent = topmost_parent->wayland.parent; + } + handle->wayland.next_elapsed = elapsed + handle->wayland.keyboard_rate; + } + } + #ifdef USE_DBUS if(wl_call_tbl.has_dbus) { if(handle->wayland.dark_theme_detection) {