Browse Source

Show the on-screen keyboard if we don't have active keyboard input

Active keyboard input is based on the input the user has most recently sent.

Fixes https://github.com/libsdl-org/SDL/issues/12595

(cherry picked from commit cbb83be895a463cb9a20f2ec5b11f33bdf98e5dc)
Sam Lantinga 1 month ago
parent
commit
9e1675671d

+ 17 - 0
src/events/SDL_keyboard.c

@@ -70,6 +70,7 @@ typedef struct SDL_Keyboard
 static SDL_Keyboard SDL_keyboard;
 static int SDL_keyboard_count;
 static SDL_KeyboardInstance *SDL_keyboards;
+static bool SDL_keyboard_active;
 
 static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
@@ -214,6 +215,20 @@ const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
     return SDL_GetPersistentString(SDL_keyboards[keyboard_index].name);
 }
 
+void SDL_SetKeyboardActive(bool active)
+{
+    SDL_keyboard_active = active;
+}
+
+bool SDL_HasActiveKeyboard(void)
+{
+    if (!SDL_HasKeyboard()) {
+        // No keyboards to be active
+        return false;
+    }
+    return SDL_keyboard_active;
+}
+
 void SDL_ResetKeyboard(void)
 {
     SDL_Keyboard *keyboard = &SDL_keyboard;
@@ -556,6 +571,8 @@ static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keyb
     }
 
     if (source == KEYBOARD_HARDWARE) {
+        // Primary input appears to be a keyboard
+        SDL_SetKeyboardActive(true);
         keyboard->hardware_timestamp = SDL_GetTicks();
     } else if (source == KEYBOARD_AUTORELEASE) {
         keyboard->autorelease_pending = true;

+ 6 - 0
src/events/SDL_keyboard_c.h

@@ -43,6 +43,12 @@ extern void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, bool se
 // A keyboard has been removed from the system
 extern void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, bool send_event);
 
+// Set whether keyboard input is active
+extern void SDL_SetKeyboardActive(bool active);
+
+// Get whether keyboard input is active
+extern bool SDL_HasActiveKeyboard(void);
+
 // Set the mapping of scancode to key codes
 extern void SDL_SetKeymap(SDL_Keymap *keymap, bool send_event);
 

+ 19 - 0
src/joystick/SDL_joystick.c

@@ -427,6 +427,13 @@ static SDL_vidpid_list zero_centered_devices = {
         return result;                                          \
     }
 
+#define CHECK_JOYSTICK_VIRTUAL(joystick, result)                \
+    if (!joystick->is_virtual) {                                \
+        SDL_SetError("joystick isn't virtual");                 \
+        SDL_UnlockJoysticks();                                  \
+        return result;                                          \
+    }
+
 bool SDL_JoysticksInitialized(void)
 {
     return SDL_joysticks_initialized;
@@ -1115,6 +1122,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
     joystick->attached = true;
     joystick->led_expiration = SDL_GetTicks();
     joystick->battery_percent = -1;
+    joystick->is_virtual = (driver == &SDL_VIRTUAL_JoystickDriver);
 
     if (!driver->Open(joystick, device_index)) {
         SDL_SetObjectValid(joystick, SDL_OBJECT_TYPE_JOYSTICK, false);
@@ -1247,6 +1255,7 @@ bool SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value)
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SetJoystickVirtualAxisInner(joystick, axis, value);
@@ -1266,6 +1275,7 @@ bool SDL_SetJoystickVirtualBall(SDL_Joystick *joystick, int ball, Sint16 xrel, S
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SetJoystickVirtualBallInner(joystick, ball, xrel, yrel);
@@ -1285,6 +1295,7 @@ bool SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, bool down)
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SetJoystickVirtualButtonInner(joystick, button, down);
@@ -1304,6 +1315,7 @@ bool SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value)
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SetJoystickVirtualHatInner(joystick, hat, value);
@@ -1323,6 +1335,7 @@ bool SDL_SetJoystickVirtualTouchpad(SDL_Joystick *joystick, int touchpad, int fi
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SetJoystickVirtualTouchpadInner(joystick, touchpad, finger, down, x, y, pressure);
@@ -1342,6 +1355,7 @@ bool SDL_SendJoystickVirtualSensorData(SDL_Joystick *joystick, SDL_SensorType ty
     SDL_LockJoysticks();
     {
         CHECK_JOYSTICK_MAGIC(joystick, false);
+        CHECK_JOYSTICK_VIRTUAL(joystick, false);
 
 #ifdef SDL_JOYSTICK_VIRTUAL
         result = SDL_SendJoystickVirtualSensorDataInner(joystick, type, sensor_timestamp, data, num_values);
@@ -2354,6 +2368,11 @@ void SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butt
         return;
     }
 
+    if (!joystick->is_virtual) {
+        // Primary input appears to be a joystick
+        SDL_SetKeyboardActive(false);
+    }
+
     /* We ignore events if we don't have keyboard focus, except for button
      * release. */
     if (SDL_PrivateJoystickShouldIgnoreEvent()) {

+ 1 - 0
src/joystick/SDL_sysjoystick.h

@@ -84,6 +84,7 @@ struct SDL_Joystick
     Uint16 firmware_version _guarded;    // Firmware version, if available
     Uint64 steam_handle _guarded;        // Steam controller API handle
     bool swap_face_buttons _guarded;     // Whether we should swap face buttons
+    bool is_virtual _guarded;            // Whether this is a virtual joystick
 
     int naxes _guarded; // Number of axis controls on the joystick
     SDL_JoystickAxisInfo *axes _guarded;

+ 1 - 1
src/video/SDL_video.c

@@ -5405,7 +5405,7 @@ bool SDL_GetTextInputMultiline(SDL_PropertiesID props)
 static bool AutoShowingScreenKeyboard(void)
 {
     const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD);
-    if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) ||
+    if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasActiveKeyboard()) ||
         SDL_GetStringBoolean(hint, false)) {
         return true;
     } else {