From 287df44133911578edf60fed7adf139e77734be9 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Wed, 2 Sep 2015 22:47:48 -0700 Subject: [PATCH] Move tap delay to joystick variant - Keypad variant already has a key repeat threshold - Improved variant touch lifecycle naming --- src/video/gltouchjoy.c | 149 +++++----------------------------- src/video/gltouchjoy.h | 31 +++++--- src/video/gltouchjoy_joy.c | 154 +++++++++++++++++++++++++++++++++--- src/video/gltouchjoy_kpad.c | 50 +++++++++--- 4 files changed, 224 insertions(+), 160 deletions(-) diff --git a/src/video/gltouchjoy.c b/src/video/gltouchjoy.c index 5aa46d3f..3910e835 100644 --- a/src/video/gltouchjoy.c +++ b/src/video/gltouchjoy.c @@ -15,13 +15,6 @@ #error this is a touch interface module, possibly you mean to not compile this at all? #endif -#define DEBUG_TOUCH_JOY 0 -#if DEBUG_TOUCH_JOY -# define TOUCH_JOY_LOG(...) LOG(__VA_ARGS__) -#else -# define TOUCH_JOY_LOG(...) -#endif - #define MODEL_DEPTH -1/32.f #define TRACKING_NONE (-1) @@ -48,7 +41,6 @@ #define BUTTON_OBJ_HALF_H (BUTTON_OBJ_H/2.f) #define BUTTON_SWITCH_THRESHOLD_DEFAULT 22 -#define BUTTON_TAP_DELAY_NANOS_DEFAULT 50000000 GLTouchJoyGlobals joyglobals = { 0 }; GLTouchJoyAxes axes = { 0 }; @@ -199,76 +191,6 @@ static inline void _setup_button_object_with_char(char newChar) { // ---------------------------------------------------------------------------- -// Tap Delay Thread : delays processing of touch-down so that a different joystick button/key can be fired - -static inline void _signal_tap_delay(void) { - pthread_mutex_lock(&buttons.tapDelayMutex); - pthread_cond_signal(&buttons.tapDelayCond); - pthread_mutex_unlock(&buttons.tapDelayMutex); -} - -static void *_button_tap_delayed_thread(void *dummyptr) { - LOG(">>> [DELAYEDTAP] thread start ..."); - - pthread_mutex_lock(&buttons.tapDelayMutex); - - do { - pthread_cond_wait(&buttons.tapDelayCond, &buttons.tapDelayMutex); - TOUCH_JOY_LOG(">>> [DELAYEDTAP] begin ..."); - - if (UNLIKELY(joyglobals.isShuttingDown)) { - break; - } - - struct timespec ts = { .tv_sec=0, .tv_nsec=buttons.tapDelayNanos }; - - // sleep for the configured delay time - pthread_mutex_unlock(&buttons.tapDelayMutex); - nanosleep(&ts, NULL); - pthread_mutex_lock(&buttons.tapDelayMutex); - - // wait until touch up/cancel - do { - - // now set the emulator's joystick button values (or keypad value) - uint8_t displayChar = variant.curr->buttonPress(); - _setup_button_object_with_char(displayChar); - - if ( (buttons.trackingIndex == TRACKING_NONE) || joyglobals.isShuttingDown) { - break; - } - - pthread_cond_wait(&buttons.tapDelayCond, &buttons.tapDelayMutex); - - if ( (buttons.trackingIndex == TRACKING_NONE) || joyglobals.isShuttingDown) { - break; - } - TOUCH_JOY_LOG(">>> [DELAYEDTAP] looping ..."); - } while (1); - - if (UNLIKELY(joyglobals.isShuttingDown)) { - break; - } - - // delay the ending of button tap or touch/move event by the configured delay time - pthread_mutex_unlock(&buttons.tapDelayMutex); - nanosleep(&ts, NULL); - pthread_mutex_lock(&buttons.tapDelayMutex); - - variant.curr->buttonRelease(); - - TOUCH_JOY_LOG(">>> [DELAYEDTAP] end ..."); - } while (1); - - pthread_mutex_unlock(&buttons.tapDelayMutex); - - LOG(">>> [DELAYEDTAP] thread exit ..."); - - return NULL; -} - -// ---------------------------------------------------------------------------- - static inline void resetState() { LOG("%s", ""); axes.trackingIndex = TRACKING_NONE; @@ -286,8 +208,6 @@ static void gltouchjoy_setup(void) { mdlDestroyModel(&buttons.model); joyglobals.isShuttingDown = false; - assert((buttons.tapDelayThreadId == 0) && "setup called multiple times!"); - pthread_create(&buttons.tapDelayThreadId, NULL, (void *)&_button_tap_delayed_thread, (void *)NULL); axes.model = mdlCreateQuad(-1.05, -1.0, AXIS_OBJ_W, AXIS_OBJ_H, MODEL_DEPTH, AXIS_FB_WIDTH, AXIS_FB_HEIGHT, (GLCustom){ .create = &_create_touchjoy_hud, @@ -319,6 +239,9 @@ static void gltouchjoy_setup(void) { return; } + variant.joys->setup(&_setup_button_object_with_char); + variant.kpad->setup(&_setup_button_object_with_char); + struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); axes.timingBegin = now; @@ -336,15 +259,10 @@ static void gltouchjoy_shutdown(void) { resetState(); joyglobals.isAvailable = false; - joyglobals.isShuttingDown = true; - pthread_cond_signal(&buttons.tapDelayCond); - if (pthread_join(buttons.tapDelayThreadId, NULL)) { - ERRLOG("OOPS: pthread_join tap delay thread ..."); - } - buttons.tapDelayThreadId = 0; - buttons.tapDelayMutex = (pthread_mutex_t){ 0 }; - buttons.tapDelayCond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; + + variant.joys->shutdown(); + variant.kpad->shutdown(); mdlDestroyModel(&axes.model); mdlDestroyModel(&buttons.model); @@ -495,9 +413,6 @@ static inline void _axis_touch_down(int x, int y) { } static inline void _button_touch_down(int x, int y) { - variant.curr->setCurrButtonValue(buttons.touchDownChar, buttons.touchDownScancode); - _signal_tap_delay(); - buttons.centerX = x; buttons.centerY = y; @@ -505,11 +420,12 @@ static inline void _button_touch_down(int x, int y) { buttons.modelDirty = true; TOUCH_JOY_LOG("---TOUCH %sDOWN (buttons index %d) center:(%d,%d) -> buttons(0x%02X,0x%02X)", (action == TOUCH_DOWN ? "" : "POINTER "), buttons.trackingIndex, buttons.centerX, buttons.centerY, joy_button0, joy_button1); + variant.curr->buttonDown(); } static inline void _axis_move(int x, int y) { - x = (x - axes.centerX); - y = (y - axes.centerY); + x -= axes.centerX; + y -= axes.centerY; TOUCH_JOY_LOG("---TOUCH MOVE ...tracking axis:%d (%d,%d) -> joy(0x%02X,0x%02X)", axes.trackingIndex, x, y, joy_x, joy_y); variant.curr->axisMove(x, y); } @@ -517,21 +433,8 @@ static inline void _axis_move(int x, int y) { static inline void _button_move(int x, int y) { x -= buttons.centerX; y -= buttons.centerY; - if ((y < -joyglobals.switchThreshold) || (y > joyglobals.switchThreshold)) { - touchjoy_button_type_t theButtonChar = -1; - int theButtonScancode = -1; - if (y < 0) { - theButtonChar = buttons.northChar; - theButtonScancode = buttons.northScancode; - } else { - theButtonChar = buttons.southChar; - theButtonScancode = buttons.southScancode; - } - - variant.curr->setCurrButtonValue(theButtonChar, theButtonScancode); - _signal_tap_delay(); - TOUCH_JOY_LOG("+++TOUCH MOVE ...tracking button:%d (%d,%d) -> buttons(0x%02X,0x%02X)", buttons.trackingIndex, x, y, joy_button0, joy_button1); - } + TOUCH_JOY_LOG("+++TOUCH MOVE ...tracking button:%d (%d,%d) -> buttons(0x%02X,0x%02X)", buttons.trackingIndex, x, y, joy_button0, joy_button1); + variant.curr->buttonMove(x, y); } static inline void _axis_touch_up(int x, int y) { @@ -544,8 +447,8 @@ static inline void _axis_touch_up(int x, int y) { TOUCH_JOY_LOG("---TOUCH %sUP (axis went up)%s", (action == TOUCH_UP ? "" : "POINTER "), (resetIndex ? " (reset buttons index!)" : "")); #endif LOG("%s", ""); - x = (x - axes.centerX); - y = (y - axes.centerY); + x -= axes.centerX; + y -= axes.centerY; if (buttons.trackingIndex > axes.trackingIndex) { LOG("!!! : DECREMENTING buttons.trackingIndex"); --buttons.trackingIndex; @@ -554,7 +457,7 @@ static inline void _axis_touch_up(int x, int y) { axes.trackingIndex = TRACKING_NONE; } -static inline void _button_touch_up(void) { +static inline void _button_touch_up(int x, int y) { #if DEBUG_TOUCH_JOY bool resetIndex = false; if (axes.trackingIndex > buttons.trackingIndex) { @@ -564,12 +467,14 @@ static inline void _button_touch_up(void) { TOUCH_JOY_LOG("---TOUCH %sUP (buttons went up)%s", (action == TOUCH_UP ? "" : "POINTER "), (resetIndex ? " (reset axis index!)" : "")); #endif LOG("%s", ""); + x -= buttons.centerX; + y -= buttons.centerY; if (axes.trackingIndex > buttons.trackingIndex) { LOG("!!! : DECREMENTING axes.trackingIndex"); --axes.trackingIndex; } + variant.curr->buttonUp(x, y); buttons.trackingIndex = TRACKING_NONE; - _signal_tap_delay(); } @@ -648,7 +553,9 @@ static int64_t gltouchjoy_onTouchEvent(interface_touch_event_t action, int point int y = (int)y_coords[axes.trackingIndex]; _axis_touch_up(x, y); } else if (pointer_idx == buttons.trackingIndex) { - _button_touch_up(); + int x = (int)x_coords[buttons.trackingIndex]; + int y = (int)y_coords[buttons.trackingIndex]; + _button_touch_up(x, y); } else { if (pointer_count == 1) { LOG("!!! : RESETTING TOUCH JOYSTICK STATE MACHINE"); @@ -764,16 +671,6 @@ static void gltouchjoy_setTouchButtonTypes( _setup_button_object_with_char(currButtonDisplayChar); } -static void gltouchjoy_setTapDelay(float secs) { - if (UNLIKELY(secs < 0.f)) { - ERRLOG("Clamping tap delay to 0.0 secs"); - } - if (UNLIKELY(secs > 1.f)) { - ERRLOG("Clamping tap delay to 1.0 secs"); - } - buttons.tapDelayNanos = (unsigned int)((float)NANOSECONDS_PER_SECOND * secs); -} - static void gltouchjoy_setTouchAxisSensitivity(float multiplier) { axes.multiplier = multiplier; } @@ -883,11 +780,6 @@ static void _init_gltouchjoy(void) { buttons.activeChar = MOUSETEXT_OPENAPPLE; - buttons.tapDelayThreadId = 0; - buttons.tapDelayMutex = (pthread_mutex_t){ 0 }; - buttons.tapDelayCond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; - buttons.tapDelayNanos = BUTTON_TAP_DELAY_NANOS_DEFAULT; - joyglobals.isEnabled = true; joyglobals.ownsScreen = true; joyglobals.showControls = true; @@ -904,7 +796,6 @@ static void _init_gltouchjoy(void) { joydriver_ownsScreen = &gltouchjoy_ownsScreen; joydriver_setShowControls = &gltouchjoy_setShowControls; joydriver_setTouchButtonTypes = &gltouchjoy_setTouchButtonTypes; - joydriver_setTapDelay = &gltouchjoy_setTapDelay; joydriver_setTouchAxisSensitivity = &gltouchjoy_setTouchAxisSensitivity; joydriver_setButtonSwitchThreshold = &gltouchjoy_setButtonSwitchThreshold; joydriver_setTouchVariant = &gltouchjoy_setTouchVariant; diff --git a/src/video/gltouchjoy.h b/src/video/gltouchjoy.h index 0fb9e2a5..9c52dd75 100644 --- a/src/video/gltouchjoy.h +++ b/src/video/gltouchjoy.h @@ -17,6 +17,13 @@ #include "video/glhudmodel.h" #include "video/glnode.h" +#define DEBUG_TOUCH_JOY 0 +#if DEBUG_TOUCH_JOY +# define TOUCH_JOY_LOG(...) LOG(__VA_ARGS__) +#else +# define TOUCH_JOY_LOG(...) +#endif + // globals typedef struct GLTouchJoyGlobals { @@ -75,23 +82,23 @@ typedef struct GLTouchJoyButtons { int trackingIndex; struct timespec timingBegin; - pthread_t tapDelayThreadId; - pthread_mutex_t tapDelayMutex; - pthread_cond_t tapDelayCond; - unsigned int tapDelayNanos; - } GLTouchJoyButtons; extern GLTouchJoyButtons buttons; typedef struct GLTouchJoyVariant { touchjoy_variant_t (*variant)(void); - void (*resetState)(void); - void (*setCurrButtonValue)(touchjoy_button_type_t theButtonChar, int theButtonScancode); - uint8_t (*buttonPress)(void); - void (*buttonRelease)(void); - void (*axisDown)(void); - void (*axisMove)(int dx, int dy); - void (*axisUp)(int dx, int dy); + void (*resetState)(void); + void (*setup)(void (*buttonDrawCallback)(char newChar)); + void (*shutdown)(void); + + void (*buttonDown)(void); + void (*buttonMove)(int dx, int dy); + void (*buttonUp)(int dx, int dy); + + void (*axisDown)(void); + void (*axisMove)(int dx, int dy); + void (*axisUp)(int dx, int dy); + } GLTouchJoyVariant; // registers a touch joystick variant with manager diff --git a/src/video/gltouchjoy_joy.c b/src/video/gltouchjoy_joy.c index c60caccb..33c750c8 100644 --- a/src/video/gltouchjoy_joy.c +++ b/src/video/gltouchjoy_joy.c @@ -15,14 +15,25 @@ #error this is a touch interface module, possibly you mean to not compile this at all? #endif +#define BUTTON_TAP_DELAY_NANOS_DEFAULT 50000000 + static GLTouchJoyVariant happyHappyJoyJoy = { 0 }; static struct { uint8_t currJoyButtonValue0; uint8_t currJoyButtonValue1; uint8_t currButtonDisplayChar; + void (*buttonDrawCallback)(char newChar); + + bool trackingButton; + pthread_t tapDelayThreadId; + pthread_mutex_t tapDelayMutex; + pthread_cond_t tapDelayCond; + unsigned int tapDelayNanos; } joys; +// ---------------------------------------------------------------------------- + static touchjoy_variant_t touchjoy_variant(void) { return EMULATED_JOYSTICK; } @@ -45,6 +56,93 @@ static void touchjoy_resetState(void) { _reset_buttons_state(); } +// ---------------------------------------------------------------------------- + +// Tap Delay Thread : delays processing of touch-down so that a different joystick button can be fired + +static inline void _signal_tap_delay(void) { + pthread_mutex_lock(&joys.tapDelayMutex); + pthread_cond_signal(&joys.tapDelayCond); + pthread_mutex_unlock(&joys.tapDelayMutex); +} + +static void *_button_tap_delayed_thread(void *dummyptr) { + LOG(">>> [DELAYEDTAP] thread start ..."); + + pthread_mutex_lock(&joys.tapDelayMutex); + + do { + pthread_cond_wait(&joys.tapDelayCond, &joys.tapDelayMutex); + TOUCH_JOY_LOG(">>> [DELAYEDTAP] begin ..."); + + if (UNLIKELY(joyglobals.isShuttingDown)) { + break; + } + + struct timespec ts = { .tv_sec=0, .tv_nsec=joys.tapDelayNanos }; + + // sleep for the configured delay time + pthread_mutex_unlock(&joys.tapDelayMutex); + nanosleep(&ts, NULL); + pthread_mutex_lock(&joys.tapDelayMutex); + + // wait until touch up/cancel + do { + + // now set the joystick button values + joy_button0 = joys.currJoyButtonValue0; + joy_button1 = joys.currJoyButtonValue1; + joys.buttonDrawCallback(joys.currButtonDisplayChar); + + if (!joys.trackingButton || joyglobals.isShuttingDown) { + break; + } + + pthread_cond_wait(&joys.tapDelayCond, &joys.tapDelayMutex); + + if (!joys.trackingButton || joyglobals.isShuttingDown) { + break; + } + TOUCH_JOY_LOG(">>> [DELAYEDTAP] looping ..."); + } while (1); + + if (UNLIKELY(joyglobals.isShuttingDown)) { + break; + } + + // delay the ending of button tap or touch/move event by the configured delay time + pthread_mutex_unlock(&joys.tapDelayMutex); + nanosleep(&ts, NULL); + pthread_mutex_lock(&joys.tapDelayMutex); + + _reset_buttons_state(); + + TOUCH_JOY_LOG(">>> [DELAYEDTAP] end ..."); + } while (1); + + pthread_mutex_unlock(&joys.tapDelayMutex); + + LOG(">>> [DELAYEDTAP] thread exit ..."); + + return NULL; +} + +static void touchjoy_setup(void (*buttonDrawCallback)(char newChar)) { + assert((joys.tapDelayThreadId == 0) && "setup called multiple times!"); + joys.buttonDrawCallback = buttonDrawCallback; + pthread_create(&joys.tapDelayThreadId, NULL, (void *)&_button_tap_delayed_thread, (void *)NULL); +} + +static void touchjoy_shutdown(void) { + pthread_cond_signal(&joys.tapDelayCond); + if (pthread_join(joys.tapDelayThreadId, NULL)) { + ERRLOG("OOPS: pthread_join tap delay thread ..."); + } + joys.tapDelayThreadId = 0; + joys.tapDelayMutex = (pthread_mutex_t){ 0 }; + joys.tapDelayCond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; +} + // ---------------------------------------------------------------------------- // axis state @@ -85,7 +183,7 @@ static void touchjoy_axisUp(int x, int y) { // ---------------------------------------------------------------------------- // button state -static void touchjoy_setCurrButtonValue(touchjoy_button_type_t theButtonChar, int theButtonScancode) { +static void _set_current_button_state(touchjoy_button_type_t theButtonChar, int theButtonScancode) { if (theButtonChar == TOUCH_BUTTON0) { joys.currJoyButtonValue0 = 0x80; joys.currJoyButtonValue1 = 0; @@ -105,14 +203,42 @@ static void touchjoy_setCurrButtonValue(touchjoy_button_type_t theButtonChar, in } } -static uint8_t touchjoy_buttonPress(void) { - joy_button0 = joys.currJoyButtonValue0; - joy_button1 = joys.currJoyButtonValue1; - return joys.currButtonDisplayChar; +static void touchjoy_buttonDown(void) { + _set_current_button_state(buttons.touchDownChar, buttons.touchDownScancode); + joys.trackingButton = true; + _signal_tap_delay(); } -static void touchjoy_buttonRelease(void) { - _reset_buttons_state(); +static void touchjoy_buttonMove(int dx, int dy) { + if ((dy < -joyglobals.switchThreshold) || (dy > joyglobals.switchThreshold)) { + touchjoy_button_type_t theButtonChar = -1; + int theButtonScancode = -1; + if (dy < 0) { + theButtonChar = buttons.northChar; + theButtonScancode = buttons.northScancode; + } else { + theButtonChar = buttons.southChar; + theButtonScancode = buttons.southScancode; + } + + _set_current_button_state(theButtonChar, theButtonScancode); + _signal_tap_delay(); + } +} + +static void touchjoy_buttonUp(int dx, int dy) { + joys.trackingButton = false; + _signal_tap_delay(); +} + +static void gltouchjoy_setTapDelay(float secs) { + if (UNLIKELY(secs < 0.f)) { + ERRLOG("Clamping tap delay to 0.0 secs"); + } + if (UNLIKELY(secs > 1.f)) { + ERRLOG("Clamping tap delay to 1.0 secs"); + } + joys.tapDelayNanos = (unsigned int)((float)NANOSECONDS_PER_SECOND * secs); } // ---------------------------------------------------------------------------- @@ -123,15 +249,23 @@ static void _init_gltouchjoy_joy(void) { happyHappyJoyJoy.variant = &touchjoy_variant, happyHappyJoyJoy.resetState = &touchjoy_resetState, + happyHappyJoyJoy.setup = &touchjoy_setup, + happyHappyJoyJoy.shutdown = &touchjoy_shutdown, - happyHappyJoyJoy.setCurrButtonValue = &touchjoy_setCurrButtonValue, - happyHappyJoyJoy.buttonPress = &touchjoy_buttonPress, - happyHappyJoyJoy.buttonRelease = &touchjoy_buttonRelease, + happyHappyJoyJoy.buttonDown = &touchjoy_buttonDown, + happyHappyJoyJoy.buttonMove = &touchjoy_buttonMove, + happyHappyJoyJoy.buttonUp = &touchjoy_buttonUp, happyHappyJoyJoy.axisDown = &touchjoy_axisDown, happyHappyJoyJoy.axisMove = &touchjoy_axisMove, happyHappyJoyJoy.axisUp = &touchjoy_axisUp, + joys.tapDelayMutex = (pthread_mutex_t){ 0 }; + joys.tapDelayCond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; + joys.tapDelayNanos = BUTTON_TAP_DELAY_NANOS_DEFAULT; + + joydriver_setTapDelay = &gltouchjoy_setTapDelay; + gltouchjoy_registerVariant(EMULATED_JOYSTICK, &happyHappyJoyJoy); } diff --git a/src/video/gltouchjoy_kpad.c b/src/video/gltouchjoy_kpad.c index 8faed3e5..4dc36d7a 100644 --- a/src/video/gltouchjoy_kpad.c +++ b/src/video/gltouchjoy_kpad.c @@ -50,6 +50,7 @@ static struct { keypad_octant_t axisCurrentOctant; uint8_t currButtonDisplayChar; + void (*buttonDrawCallback)(char newChar); // index of repeating scancodes to fire keypad_fire_t fireIdx; @@ -162,6 +163,10 @@ static void touchkpad_keyboardReadCallback(void) { } } + if (fired == REPEAT_BUTTON) { + kpad.buttonDrawCallback(kpad.currButtonDisplayChar); + } + bool lockedAxis = _callback_sourceTryLock(&kpad.axisLock); if (lockedAxis) { if (fired == REPEAT_AXIS || fired == REPEAT_AXIS_ALT) { @@ -227,6 +232,14 @@ static void touchkpad_resetState(void) { c_keys_handle_input(buttons.southScancode, /*pressed:*/false, /*ASCII:*/false); } +static void touchkpad_setup(void (*buttonDrawCallback)(char newChar)) { + kpad.buttonDrawCallback = buttonDrawCallback; +} + +static void touchkpad_shutdown(void) { + // ... +} + // ---------------------------------------------------------------------------- // axis key(s) state @@ -465,7 +478,7 @@ static void touchkpad_axisUp(int dx, int dy) { // ---------------------------------------------------------------------------- // button key state -static void touchkpad_setCurrButtonValue(touchjoy_button_type_t theButtonChar, int theButtonScancode) { +static void _set_current_button_state(touchjoy_button_type_t theButtonChar, int theButtonScancode) { LOG("%s", ""); if (theButtonChar >= 0) { kpad.currButtonDisplayChar = theButtonChar; @@ -476,23 +489,40 @@ static void touchkpad_setCurrButtonValue(touchjoy_button_type_t theButtonChar, i } } -static uint8_t touchkpad_buttonPress(void) { - LOG("%s", ""); +static void touchkpad_buttonDown(void) { if (!kpad.buttonBegan) { - // avoid multiple locks on extra buttonPress() kpad.buttonBegan = true; _touch_sourceBegin(&kpad.buttonLock); } + _set_current_button_state(buttons.touchDownChar, buttons.touchDownScancode); if (kpad.scancodes[REPEAT_BUTTON] >= 0) { LOG("->BUTT : %d/'%c'", kpad.scancodes[REPEAT_BUTTON], kpad.currButtonDisplayChar); clock_gettime(CLOCK_MONOTONIC, &kpad.timingBegins[REPEAT_BUTTON]); keydriver_keyboardReadCallback = &touchkpad_keyboardReadCallback; } - return kpad.currButtonDisplayChar; } -static void touchkpad_buttonRelease(void) { +static void touchkpad_buttonMove(int dx, int dy) { + // Currently this is the same logic as the "regular" joystick variant ... but we could likely be more creative here + // in a future revision, like having a full octant of key possibilities ... (for example, playing Bolo with a friend + // on the same tablet, one driving, the other shooting and controlling the turret) + if ((dy < -joyglobals.switchThreshold) || (dy > joyglobals.switchThreshold)) { + touchjoy_button_type_t theButtonChar = -1; + int theButtonScancode = -1; + if (dy < 0) { + theButtonChar = buttons.northChar; + theButtonScancode = buttons.northScancode; + } else { + theButtonChar = buttons.southChar; + theButtonScancode = buttons.southScancode; + } + _set_current_button_state(theButtonChar, theButtonScancode); + } +} + +static void touchkpad_buttonUp(int dx, int dy) { LOG("%s", ""); + touchkpad_buttonMove(dx, dy); kpad.timingBegins[REPEAT_BUTTON] = (struct timespec){ 0 }; if (kpad.buttonBegan) { kpad.buttonBegan = false; @@ -521,10 +551,12 @@ static void _init_gltouchjoy_kpad(void) { kpadJoy.variant = &touchkpad_variant, kpadJoy.resetState = &touchkpad_resetState, + kpadJoy.setup = &touchkpad_setup, + kpadJoy.shutdown = &touchkpad_shutdown, - kpadJoy.setCurrButtonValue = &touchkpad_setCurrButtonValue, - kpadJoy.buttonPress = &touchkpad_buttonPress, - kpadJoy.buttonRelease = &touchkpad_buttonRelease, + kpadJoy.buttonDown = &touchkpad_buttonDown, + kpadJoy.buttonMove = &touchkpad_buttonMove, + kpadJoy.buttonUp = &touchkpad_buttonUp, kpadJoy.axisDown = &touchkpad_axisDown, kpadJoy.axisMove = &touchkpad_axisMove,