From 6ff2faf4af8881a54b4e1f69e655d9f6d63b2835 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 1 Oct 2017 17:46:30 -0400 Subject: [PATCH] Add key repeating back in with Jtk Problem though: A change in modifiers between key press and release will lead to a different keyval, which indexes differently into g_key_statuses, leading to infinite key repeats. So we maybe should revert to storing modifier state separately from keycode to handle this. --- src/gui/Window.cc | 93 ++++++++++++++++++---------------------- src/gui/jtk/Jtk_event.cc | 2 + src/gui/jtk/Jtk_event.h | 2 + src/gui/jtk/Jtk_timer.cc | 20 ++++++++- src/gui/jtk/Jtk_timer.h | 3 +- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/gui/Window.cc b/src/gui/Window.cc index 6b0300e..4463824 100644 --- a/src/gui/Window.cc +++ b/src/gui/Window.cc @@ -5,20 +5,27 @@ #include #include "jes_icon-32x32.h" #include +#include #define INITIAL_WIDTH 800 #define INITIAL_HEIGHT 800 #define FONT_SIZE 16 -#if 0 -struct +#define TIMER_TYPE_KEY_REPEAT 1u + +struct KeyStatus { - SDL_TimerID timer_id; - SDL_Keycode keysym; + size_t timer_id; + uint32_t keyval; bool pressed; bool event_pending; -} Key_Statuses[SDL_NUM_SCANCODES]; -#endif + + KeyStatus() + { + pressed = false; + } +}; +std::unordered_map g_key_statuses; /** * Initialize OpenGL. @@ -156,33 +163,6 @@ void Window::run_event_loop() } } -#if 0 -Uint32 Key_Repeat(Uint32 interval, void * param) -{ - if (Key_Statuses[(uintptr_t)param].pressed) - { - if (!Key_Statuses[(uintptr_t)param].event_pending) - { - SDL_Event event; - - event.user.code = 0; - event.user.data1 = (void *)(uintptr_t)Key_Statuses[(uintptr_t)param].keysym; - event.user.data2 = param; - event.type = SDL_USEREVENT; - - SDL_PushEvent(&event); - Key_Statuses[(uintptr_t)param].event_pending = true; - } - - return 25u; - } - else - { - return 0u; - } -} -#endif - /** * Handle a Jtk event. */ @@ -197,32 +177,46 @@ void Window::handle_event(Jtk_Event & event) #endif case JTK_EVENT_KEY_PRESS: -#if 0 - if (event.key.repeat == 0) { - Key_Statuses[event.key.keysym.scancode].pressed = true; - Key_Statuses[event.key.keysym.scancode].keysym = event.key.keysym.sym; - Key_Statuses[event.key.keysym.scancode].timer_id = SDL_AddTimer(300, Key_Repeat, (void *)event.key.keysym.scancode); - handle_keysym(event.key.keysym.sym); + KeyStatus & key_status = g_key_statuses[event.key.key]; + key_status.pressed = true; + key_status.keyval = event.key.key; + key_status.timer_id = Jtk_AddTimer(300u, 25u, + (void *)TIMER_TYPE_KEY_REPEAT, &key_status); + handle_keypress(event.key.key); } -#endif - handle_keypress(event.key.key); break; case JTK_EVENT_KEY_RELEASE: -#if 0 - Key_Statuses[event.key.keysym.scancode].pressed = false; - if (Key_Statuses[event.key.keysym.scancode].timer_id != 0) { - SDL_RemoveTimer(Key_Statuses[event.key.keysym.scancode].timer_id); - Key_Statuses[event.key.keysym.scancode].timer_id = 0; + KeyStatus & key_status = g_key_statuses[event.key.key]; + if (key_status.pressed) + { + Jtk_RemoveTimer(key_status.timer_id); + key_status.pressed = false; + } } -#endif break; case JTK_EVENT_WINDOW_EXPOSE: m_redraw_requested = true; break; + + case JTK_EVENT_TIMER: + switch ((uintptr_t)event.timer.user1) + { + case TIMER_TYPE_KEY_REPEAT: + { + KeyStatus * key_status = (KeyStatus *)event.timer.user2; + if (key_status->pressed) + { + handle_keypress(key_status->keyval); + } + } + break; + } + break; + #if 0 case SDL_WINDOWEVENT: switch (event.window.event) @@ -237,11 +231,6 @@ void Window::handle_event(Jtk_Event & event) } break; - case SDL_USEREVENT: - Key_Statuses[(uintptr_t)event.user.data2].event_pending = false; - handle_keysym((uint32_t)(uintptr_t)event.user.data1); - break; - case SDL_MOUSEWHEEL: if (event.wheel.y > 0) { diff --git a/src/gui/jtk/Jtk_event.cc b/src/gui/jtk/Jtk_event.cc index 8bab1bd..899d0c0 100644 --- a/src/gui/jtk/Jtk_event.cc +++ b/src/gui/jtk/Jtk_event.cc @@ -253,6 +253,8 @@ void Jtk_WaitEvent(Jtk_Event * event) { event->type = JTK_EVENT_TIMER; event->timer.timer_id = timer_id; + event->timer.user1 = Jtk_GetTimerUserData(timer_id, 0u); + event->timer.user2 = Jtk_GetTimerUserData(timer_id, 1u); Jtk_ServiceTimer(timer_id); return; } diff --git a/src/gui/jtk/Jtk_event.h b/src/gui/jtk/Jtk_event.h index d093226..89d6f05 100644 --- a/src/gui/jtk/Jtk_event.h +++ b/src/gui/jtk/Jtk_event.h @@ -25,6 +25,8 @@ typedef struct typedef struct { size_t timer_id; + void * user1; + void * user2; } Jtk_TimerEvent; typedef struct diff --git a/src/gui/jtk/Jtk_timer.cc b/src/gui/jtk/Jtk_timer.cc index 4f4f2ce..4be3a85 100644 --- a/src/gui/jtk/Jtk_timer.cc +++ b/src/gui/jtk/Jtk_timer.cc @@ -8,6 +8,7 @@ typedef struct uint64_t next; /**< Time the timer next expires (us). */ uint64_t interval; /**< Timer interval (us). */ size_t id; /**< Timer ID. */ + void * user[2]; /**< User data pointers. */ } Timer; /** Vector used to allocate timer IDs. */ @@ -37,11 +38,17 @@ static size_t AllocateTimerID() * @param interval * Interval time in milliseconds. A value of 0 indicates that the timer * is not periodic. + * @param user1 + * User data pointer 1. This value is not used by Jtk but can be retrieved by + * the user when a timer expires. + * @param user2 + * User data pointer 2. This value is not used by Jtk but can be retrieved by + * the user when a timer expires. * * @return * Timer ID. */ -size_t Jtk_AddTimer(uint32_t delay, uint32_t interval) +size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2) { uint64_t current_system_time = Jtk_UsTime(); size_t timer_id = AllocateTimerID(); @@ -49,6 +56,8 @@ size_t Jtk_AddTimer(uint32_t delay, uint32_t interval) timer->next = current_system_time + (delay * 1000u); timer->interval = interval * 1000u; timer->id = timer_id; + timer->user[0] = user1; + timer->user[1] = user2; g_timers[timer_id] = timer; g_active_timers.push_back(timer); return timer_id; @@ -137,3 +146,12 @@ size_t Jtk_GetExpiredTimer() } return (size_t)-1; } + +void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index) +{ + if (timer_id < g_timers.size()) + { + return g_timers[timer_id]->user[index]; + } + return nullptr; +} diff --git a/src/gui/jtk/Jtk_timer.h b/src/gui/jtk/Jtk_timer.h index ae6c93d..d3a4e6a 100644 --- a/src/gui/jtk/Jtk_timer.h +++ b/src/gui/jtk/Jtk_timer.h @@ -4,10 +4,11 @@ #include #include -size_t Jtk_AddTimer(uint32_t delay, uint32_t interval); +size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2); void Jtk_RemoveTimer(size_t timer_id); uint64_t Jtk_TimeToNextTimerExpiration(); void Jtk_ServiceTimer(size_t timer_id); size_t Jtk_GetExpiredTimer(); +void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index); #endif