@@ -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)
6372struct 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+ }
889948struct wl_display * getWaylandDisplay () {
890949 com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi .get ();
891950 return wsi ? wsi->getDisplay () : nullptr ;
0 commit comments