animated example
This commit is contained in:
parent
216972e73a
commit
c9fd1b1585
17 changed files with 576 additions and 465 deletions
|
|
@ -454,16 +454,32 @@ void Device::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, ui
|
|||
std::string buf;
|
||||
buf.resize(16);
|
||||
int n = xkb_state_key_get_utf8(xkb_state, keycode, buf.data(), 16);
|
||||
if (n > 0) {
|
||||
if ((unsigned char)buf[0] >= 0x20 && buf[0] != 0x7f) {
|
||||
buf.resize(n);
|
||||
focusedWindow->onTextInput.Invoke(buf);
|
||||
}
|
||||
std::string utf8;
|
||||
if (n > 0 && (unsigned char)buf[0] >= 0x20 && buf[0] != 0x7f) {
|
||||
buf.resize(n);
|
||||
utf8 = buf;
|
||||
focusedWindow->onTextInput.Invoke(utf8);
|
||||
}
|
||||
|
||||
// Replace the active repeat with this key — most recent press wins,
|
||||
// matching xkbcommon's typical behaviour and most desktop apps.
|
||||
keyRepeat.active = (keyRepeat.rate > 0);
|
||||
keyRepeat.key = crafterKey;
|
||||
keyRepeat.utf8 = std::move(utf8);
|
||||
keyRepeat.pressTime = std::chrono::steady_clock::now();
|
||||
keyRepeat.lastFireTime = keyRepeat.pressTime;
|
||||
} else {
|
||||
focusedWindow->heldkeys[(std::uint8_t)crafterKey] = false;
|
||||
focusedWindow->onKeyUp[(std::uint8_t)crafterKey].Invoke();
|
||||
focusedWindow->onAnyKeyUp.Invoke(crafterKey);
|
||||
|
||||
// If the released key was the one repeating, stop. Otherwise leave
|
||||
// the existing repeat alone (user pressed/released a modifier
|
||||
// mid-repeat etc.).
|
||||
if (keyRepeat.active && keyRepeat.key == crafterKey) {
|
||||
keyRepeat.active = false;
|
||||
keyRepeat.utf8.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,7 +488,36 @@ void Device::keyboard_modifiers(void *data, wl_keyboard *keyboard, uint32_t seri
|
|||
}
|
||||
|
||||
void Device::keyboard_repeat_info(void *data, wl_keyboard *keyboard, int32_t rate, int32_t delay) {
|
||||
keyRepeat.rate = rate;
|
||||
keyRepeat.delay = delay;
|
||||
if (rate <= 0) keyRepeat.active = false; // compositor disabled repeat
|
||||
}
|
||||
|
||||
void Device::TickKeyRepeats() {
|
||||
if (!keyRepeat.active || !focusedWindow) return;
|
||||
if (keyRepeat.rate <= 0) return;
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
using ms = std::chrono::milliseconds;
|
||||
auto sincePress = std::chrono::duration_cast<ms>(now - keyRepeat.pressTime).count();
|
||||
if (sincePress < keyRepeat.delay) return;
|
||||
|
||||
auto period = std::chrono::milliseconds(1000 / keyRepeat.rate);
|
||||
auto sinceLastFire = std::chrono::duration_cast<ms>(now - keyRepeat.lastFireTime).count();
|
||||
if (sinceLastFire < period.count()) return;
|
||||
|
||||
// Catch up — emit one event per missed period so a paused frame doesn't
|
||||
// make the repeat permanently lag behind.
|
||||
while (now - keyRepeat.lastFireTime >= period) {
|
||||
focusedWindow->onKeyDown[(std::uint8_t)keyRepeat.key].Invoke();
|
||||
focusedWindow->onAnyKeyDown.Invoke(keyRepeat.key);
|
||||
focusedWindow->onKeyHold[(std::uint8_t)keyRepeat.key].Invoke();
|
||||
focusedWindow->onAnyKeyHold.Invoke(keyRepeat.key);
|
||||
if (!keyRepeat.utf8.empty()) {
|
||||
focusedWindow->onTextInput.Invoke(keyRepeat.utf8);
|
||||
}
|
||||
keyRepeat.lastFireTime += period;
|
||||
}
|
||||
}
|
||||
|
||||
void Device::seat_handle_capabilities(void* data, wl_seat* seat, uint32_t capabilities) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue