Skip to content

Commit 8f5ff97

Browse files
committed
keyboard repeat logic
1 parent b5f9144 commit 8f5ff97

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/osgViewer/GraphicsWindowWayland.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ struct gc_client_state {
5858
uint32_t keyboard_serial;
5959
// custom Ctrl modifier
6060
bool keyboard_ctrl;
61+
// repeat state
62+
int32_t keyboard_repeat;
63+
int32_t keyboard_delay;
64+
uint64_t keyboard_tick;
65+
int keyboard_state;
66+
int keyboard_last;
67+
#define KEYBOARD_IDLE 0
68+
#define KEYBOARD_DELAY 1
69+
#define KEYBOARD_REPEAT 2
6170
};
6271
// graphics window state (instanced)
6372
struct gw_client_state {
@@ -377,6 +386,9 @@ class WLGraphicsWindow : public osgViewer::GraphicsWindow {
377386
}
378387
virtual void swapBuffersImplementation() {
379388
eglSwapBuffers(_gw.gc->egl_display, _gw.egl_surface);
389+
// pump any async logic
390+
checkAsyncWork();
391+
// pump any Wayland messages
380392
wl_display_dispatch_pending(_gw.gc->display);
381393
}
382394

@@ -486,6 +498,7 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
486498
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
487499
obj->_gc.keyboard_surface = surface;
488500
obj->_gc.keyboard_serial = serial;
501+
obj->_gc.keyboard_ctrl = false;
489502
WLGWlog(1) << "<keyboard enter: " << surface << ">" << std::endl;
490503
// dump pressed keys
491504
uint32_t* pkey = (uint32_t*)keys->data;
@@ -498,6 +511,7 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
498511
static void keyboard_leave(void* data, wl_keyboard* wl_keyboard, uint32_t serial, wl_surface* surface) {
499512
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
500513
obj->_gc.keyboard_surface = nullptr;
514+
obj->_gc.keyboard_state = KEYBOARD_IDLE;
501515
WLGWlog(0) << "<keyboard leave: " << surface << ">" << std::endl;
502516
}
503517
static void keyboard_map(void* data, wl_keyboard* wl_keyboard, uint32_t format, int32_t fd, uint32_t size) {
@@ -521,7 +535,10 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
521535
WLGWlog(0) << "<keyboard map: format=" << format << ", fd=" << fd << ", size=" << size << ", map=" << obj->_gc.xkb_keymap << ", state=" << obj->_gc.xkb_state << ">" << std::endl;
522536
}
523537
static void keyboard_repeat(void* data, wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {
538+
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
524539
WLGWlog(0) << "<keyboard repeat: rate=" << rate << ", delay=" << delay << ">" << std::endl;
540+
obj->_gc.keyboard_repeat = 1000/rate;
541+
obj->_gc.keyboard_delay = delay;
525542
}
526543
static void 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) {
527544
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
@@ -549,6 +566,9 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
549566
win->getEventQueue()->keyRelease((int)sym);
550567
WLGWlog(0) << (state?"<keypress: ":"<keyrelease: ") << key << "=>" << sym << ">" << std::endl;
551568
}
569+
// any new keypress always puts us in DELAY state for repeats, releasing any key stops repeats
570+
obj->_gc.keyboard_state = state ? KEYBOARD_DELAY : KEYBOARD_IDLE;
571+
obj->_gc.keyboard_last = (int)sym;
552572
}
553573
static void pointer_enter(void *data, wl_pointer* wl_pointer, uint32_t serial, wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
554574
WLGWlog(0) << "<pointer enter: " << surface << ">" << std::endl;
@@ -864,6 +884,41 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
864884
uint32_t getLastKeySerial() {
865885
return _gc.keyboard_serial;
866886
}
887+
888+
// async work pump
889+
void checkAsyncWork(void) {
890+
// keyboard repeat?
891+
if (KEYBOARD_IDLE==_gc.keyboard_state) {
892+
// while idle, record current tick..
893+
_gc.keyboard_tick = tickMs();
894+
} else if (KEYBOARD_DELAY==_gc.keyboard_state) {
895+
// while in delay, wait for specified time
896+
uint64_t now = tickMs();
897+
if (now>_gc.keyboard_tick+(uint64_t)_gc.keyboard_delay) {
898+
// start repeating from now
899+
_gc.keyboard_state = KEYBOARD_REPEAT;
900+
_gc.keyboard_tick = now;
901+
}
902+
} else {
903+
// while in repeat, time to issue another repeat?
904+
uint64_t now = tickMs();
905+
if (now>_gc.keyboard_tick+(uint64_t)_gc.keyboard_repeat) {
906+
// yep - send release then press events
907+
auto win = get_window(_gc.keyboard_surface);
908+
win->getEventQueue()->keyRelease(_gc.keyboard_last);
909+
win->getEventQueue()->keyPress(_gc.keyboard_last);
910+
_gc.keyboard_tick = now;
911+
WLGWlog(0) << "<keyboard repeat: " << _gc.keyboard_last << ">" << std::endl;
912+
}
913+
}
914+
}
915+
916+
private:
917+
uint64_t tickMs(void) {
918+
struct timespec ts;
919+
clock_gettime(CLOCK_MONOTONIC, &ts);
920+
return (ts.tv_sec * 1000)+(ts.tv_nsec/1000000);
921+
}
867922
};
868923

869924
// statically register our new windowing system at run-time
@@ -886,6 +941,10 @@ uint32_t getWaylandLastKeySerial() {
886941
com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi.get();
887942
return wsi ? wsi->getLastKeySerial() : 0;
888943
}
944+
void checkAsyncWork() {
945+
com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi.get();
946+
if (wsi) wsi->checkAsyncWork();
947+
}
889948
struct wl_display* getWaylandDisplay() {
890949
com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi.get();
891950
return wsi ? wsi->getDisplay() : nullptr;

src/osgViewer/GraphicsWindowWayland.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
struct wl_data_device* getWaylandDataDevice();
99
struct wl_data_source* getWaylandDataSource();
1010
uint32_t getWaylandLastKeySerial();
11+
void checkAsyncWork();
1112
struct wl_display* getWaylandDisplay();
1213
#ifdef __cplusplus
1314
}

0 commit comments

Comments
 (0)