Skip to content

Commit 1a37ca3

Browse files
committed
GPU Wayland Display: Handle Key Repeats
1 parent dddc6ab commit 1a37ca3

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontendWayland.cxx‎

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,35 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
234234
GPUDisplayFrontendWayland* me = (GPUDisplayFrontendWayland*)data;
235235
int32_t symbol = me->GetKey(key, state);
236236
int32_t keyPress = (symbol >= 'a' && symbol <= 'z') ? symbol + 'A' - 'a' : symbol;
237-
if (state == XKB_KEY_DOWN) {
237+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
238238
me->mKeys[keyPress] = true;
239239
me->mKeysShift[keyPress] = me->mKeys[KEY_SHIFT];
240240
me->HandleKey(symbol);
241+
if (symbol && me->mRepeatRate > 0 && me->mXKBkeymap && xkb_keymap_key_repeats(me->mXKBkeymap, key + 8)) { // Wayland compositors do not repeat keys, the client must do it
242+
me->mRepeatKeyCode = key;
243+
me->mRepeatSymbol = symbol;
244+
me->mRepeatNext = std::chrono::steady_clock::now() + std::chrono::milliseconds(me->mRepeatDelay);
245+
}
241246
} else {
242247
me->mKeys[keyPress] = false;
243248
me->mKeysShift[keyPress] = false;
249+
if ((int64_t)key == me->mRepeatKeyCode) {
250+
me->mRepeatKeyCode = -1;
251+
}
244252
}
245253
};
246254
auto keyboard_modifiers = [](void* data, wl_keyboard* wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
247255
GPUDisplayFrontendWayland* me = (GPUDisplayFrontendWayland*)data;
248256
xkb_state_update_mask(me->mXKBstate, mods_depressed, mods_latched, mods_locked, 0, 0, group);
249257
};
250-
auto keyboard_repat = [](void* data, wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {};
258+
auto keyboard_repat = [](void* data, wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {
259+
GPUDisplayFrontendWayland* me = (GPUDisplayFrontendWayland*)data;
260+
me->mRepeatRate = rate;
261+
me->mRepeatDelay = delay;
262+
if (rate <= 0) {
263+
me->mRepeatKeyCode = -1;
264+
}
265+
};
251266
mKeyboardListener = wl_keyboard_listener{.keymap = keyboard_keymap, .enter = keyboard_enter, .leave = keyboard_leave, .key = keyboard_key, .modifiers = keyboard_modifiers, .repeat_info = keyboard_repat};
252267

253268
auto xdg_wm_base_ping = [](void* data, struct xdg_wm_base* xdg_wm_base, uint32_t serial) {
@@ -524,6 +539,7 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
524539
break;
525540
}
526541
HandleSendKeys();
542+
handleKeyRepeat();
527543
if (!mSuspended) { // Window not visible, compositor would not release swapchain images
528544
DrawGLScene();
529545
}
@@ -655,6 +671,18 @@ void GPUDisplayFrontendWayland::updateSize()
655671
}
656672
}
657673

674+
void GPUDisplayFrontendWayland::handleKeyRepeat()
675+
{
676+
if (mRepeatKeyCode < 0) {
677+
return;
678+
}
679+
const auto now = std::chrono::steady_clock::now();
680+
while (now >= mRepeatNext && mRepeatKeyCode >= 0) {
681+
HandleKey(mRepeatSymbol);
682+
mRepeatNext += std::chrono::microseconds(1000000 / mRepeatRate);
683+
}
684+
}
685+
658686
void GPUDisplayFrontendWayland::applyScroll()
659687
{
660688
mMouseWheel += mHasAxisValue120 ? (mAxisValue120 * -100 / 120) : (int32_t)(mAxisValue * (-100. / 15.));

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontendWayland.h‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ class GPUDisplayFrontendWayland : public GPUDisplayFrontend
4949
private:
5050
int32_t FrontendMain() override;
5151
int32_t GetKey(uint32_t key, uint32_t state);
52-
void updateScale(); // Buffer scale from wl_surface.preferred_buffer_scale, or max scale of the outputs the surface is on (older compositors)
53-
void updateSize(); // Physical size = logical size * scale, resizes the scene if changed
54-
void applyScroll(); // Apply scroll events of one wl_pointer.frame: high-resolution wheel (120 = 1 notch = 100 mMouseWheel units) if available, otherwise continuous axis (touchpad, ~15 units per notch)
52+
void updateScale(); // Buffer scale from wl_surface.preferred_buffer_scale, or max scale of the outputs the surface is on (older compositors)
53+
void updateSize(); // Physical size = logical size * scale, resizes the scene if changed
54+
void handleKeyRepeat(); // Call HandleKey for the held key according to wl_keyboard.repeat_info
55+
void applyScroll(); // Apply scroll events of one wl_pointer.frame: high-resolution wheel (120 = 1 notch = 100 mMouseWheel units) if available, otherwise continuous axis (touchpad, ~15 units per notch)
5556

5657
struct OutputInfo {
5758
wl_output* output;
@@ -113,6 +114,12 @@ class GPUDisplayFrontendWayland : public GPUDisplayFrontend
113114
bool mCanFullscreen = true;
114115
bool mCanMaximize = true;
115116

117+
int32_t mRepeatRate = 0; // Keys per second, 0 = no repeat
118+
int32_t mRepeatDelay = 0; // ms before the first repeat
119+
int64_t mRepeatKeyCode = -1; // Evdev key code of the held key to repeat, -1 = none
120+
int32_t mRepeatSymbol = 0;
121+
std::chrono::steady_clock::time_point mRepeatNext;
122+
116123
double mAxisValue = 0; // Accumulated scroll values of one wl_pointer.frame
117124
int32_t mAxisValue120 = 0;
118125
bool mHasAxisValue120 = false;

0 commit comments

Comments
 (0)