@@ -58,6 +58,15 @@ struct gc_client_state {
58
58
uint32_t keyboard_serial;
59
59
// custom Ctrl modifier
60
60
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
61
70
};
62
71
// graphics window state (instanced)
63
72
struct gw_client_state {
@@ -377,6 +386,9 @@ class WLGraphicsWindow : public osgViewer::GraphicsWindow {
377
386
}
378
387
virtual void swapBuffersImplementation () {
379
388
eglSwapBuffers (_gw.gc ->egl_display , _gw.egl_surface );
389
+ // pump any async logic
390
+ checkAsyncWork ();
391
+ // pump any Wayland messages
380
392
wl_display_dispatch_pending (_gw.gc ->display );
381
393
}
382
394
@@ -486,6 +498,7 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
486
498
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
487
499
obj->_gc .keyboard_surface = surface;
488
500
obj->_gc .keyboard_serial = serial;
501
+ obj->_gc .keyboard_ctrl = false ;
489
502
WLGWlog (1 ) << " <keyboard enter: " << surface << " >" << std::endl;
490
503
// dump pressed keys
491
504
uint32_t * pkey = (uint32_t *)keys->data ;
@@ -498,6 +511,7 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
498
511
static void keyboard_leave (void * data, wl_keyboard* wl_keyboard, uint32_t serial, wl_surface* surface) {
499
512
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
500
513
obj->_gc .keyboard_surface = nullptr ;
514
+ obj->_gc .keyboard_state = KEYBOARD_IDLE;
501
515
WLGWlog (0 ) << " <keyboard leave: " << surface << " >" << std::endl;
502
516
}
503
517
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
521
535
WLGWlog (0 ) << " <keyboard map: format=" << format << " , fd=" << fd << " , size=" << size << " , map=" << obj->_gc .xkb_keymap << " , state=" << obj->_gc .xkb_state << " >" << std::endl;
522
536
}
523
537
static void keyboard_repeat (void * data, wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {
538
+ WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
524
539
WLGWlog (0 ) << " <keyboard repeat: rate=" << rate << " , delay=" << delay << " >" << std::endl;
540
+ obj->_gc .keyboard_repeat = 1000 /rate;
541
+ obj->_gc .keyboard_delay = delay;
525
542
}
526
543
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) {
527
544
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
@@ -549,6 +566,9 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
549
566
win->getEventQueue ()->keyRelease ((int )sym);
550
567
WLGWlog (0 ) << (state?" <keypress: " :" <keyrelease: " ) << key << " =>" << sym << " >" << std::endl;
551
568
}
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;
552
572
}
553
573
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) {
554
574
WLGWlog (0 ) << " <pointer enter: " << surface << " >" << std::endl;
@@ -864,6 +884,41 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
864
884
uint32_t getLastKeySerial () {
865
885
return _gc.keyboard_serial ;
866
886
}
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
+ }
867
922
};
868
923
869
924
// statically register our new windowing system at run-time
@@ -886,6 +941,10 @@ uint32_t getWaylandLastKeySerial() {
886
941
com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi .get ();
887
942
return wsi ? wsi->getLastKeySerial () : 0 ;
888
943
}
944
+ void checkAsyncWork () {
945
+ com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi .get ();
946
+ if (wsi) wsi->checkAsyncWork ();
947
+ }
889
948
struct wl_display * getWaylandDisplay () {
890
949
com::ashbysoft::WLWindowingSystemInterface* wsi = com::ashbysoft::s_proxy_WLWindowingSystemInterface._wsi .get ();
891
950
return wsi ? wsi->getDisplay () : nullptr ;
0 commit comments