early-access version 1611
This commit is contained in:
2801
externals/SDL/src/core/android/SDL_android.c
vendored
Executable file
2801
externals/SDL/src/core/android/SDL_android.c
vendored
Executable file
File diff suppressed because it is too large
Load Diff
147
externals/SDL/src/core/android/SDL_android.h
vendored
Executable file
147
externals/SDL/src/core/android/SDL_android.h
vendored
Executable file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#include <EGL/eglplatform.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_rect.h"
|
||||
#include "SDL_video.h"
|
||||
|
||||
/* Interface from the SDL library into the Android Java activity */
|
||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||
extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen);
|
||||
extern void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint);
|
||||
extern void Android_JNI_MinizeWindow(void);
|
||||
extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void);
|
||||
|
||||
extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
|
||||
extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
|
||||
extern void Android_JNI_HideTextInput(void);
|
||||
extern SDL_bool Android_JNI_IsScreenKeyboardShown(void);
|
||||
extern ANativeWindow* Android_JNI_GetNativeWindow(void);
|
||||
extern void Android_JNI_SetSurfaceViewFormat(int format);
|
||||
|
||||
extern SDL_DisplayOrientation Android_JNI_GetDisplayOrientation(void);
|
||||
extern int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi);
|
||||
|
||||
/* Audio support */
|
||||
extern int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec);
|
||||
extern void* Android_JNI_GetAudioBuffer(void);
|
||||
extern void Android_JNI_WriteAudioBuffer(void);
|
||||
extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen);
|
||||
extern void Android_JNI_FlushCapturedAudio(void);
|
||||
extern void Android_JNI_CloseAudioDevice(const int iscapture);
|
||||
extern void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id);
|
||||
|
||||
/* Detecting device type */
|
||||
extern SDL_bool Android_IsDeXMode(void);
|
||||
extern SDL_bool Android_IsChromebook(void);
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
|
||||
int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char* mode);
|
||||
Sint64 Android_JNI_FileSize(SDL_RWops* ctx);
|
||||
Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence);
|
||||
size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer, size_t size, size_t maxnum);
|
||||
size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
|
||||
int Android_JNI_FileClose(SDL_RWops* ctx);
|
||||
|
||||
/* Environment support */
|
||||
void Android_JNI_GetManifestEnvironmentVariables(void);
|
||||
|
||||
/* Clipboard support */
|
||||
int Android_JNI_SetClipboardText(const char* text);
|
||||
char* Android_JNI_GetClipboardText(void);
|
||||
SDL_bool Android_JNI_HasClipboardText(void);
|
||||
|
||||
/* Power support */
|
||||
int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
|
||||
|
||||
/* Joystick support */
|
||||
void Android_JNI_PollInputDevices(void);
|
||||
|
||||
/* Haptic support */
|
||||
void Android_JNI_PollHapticDevices(void);
|
||||
void Android_JNI_HapticRun(int device_id, float intensity, int length);
|
||||
void Android_JNI_HapticStop(int device_id);
|
||||
|
||||
/* Video */
|
||||
void Android_JNI_SuspendScreenSaver(SDL_bool suspend);
|
||||
|
||||
/* Touch support */
|
||||
void Android_JNI_InitTouch(void);
|
||||
|
||||
/* Threads */
|
||||
#include <jni.h>
|
||||
JNIEnv *Android_JNI_GetEnv(void);
|
||||
int Android_JNI_SetupThread(void);
|
||||
|
||||
/* Generic messages */
|
||||
int Android_JNI_SendMessage(int command, int param);
|
||||
|
||||
/* Init */
|
||||
JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls);
|
||||
|
||||
/* MessageBox */
|
||||
#include "SDL_messagebox.h"
|
||||
int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
/* Cursor support */
|
||||
int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y);
|
||||
SDL_bool Android_JNI_SetCustomCursor(int cursorID);
|
||||
SDL_bool Android_JNI_SetSystemCursor(int cursorID);
|
||||
|
||||
/* Relative mouse support */
|
||||
SDL_bool Android_JNI_SupportsRelativeMouse(void);
|
||||
SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled);
|
||||
|
||||
/* Request permission */
|
||||
SDL_bool Android_JNI_RequestPermission(const char *permission);
|
||||
|
||||
int SDL_GetAndroidSDKVersion(void);
|
||||
|
||||
SDL_bool SDL_IsAndroidTablet(void);
|
||||
SDL_bool SDL_IsAndroidTV(void);
|
||||
SDL_bool SDL_IsChromebook(void);
|
||||
SDL_bool SDL_IsDeXMode(void);
|
||||
|
||||
void Android_ActivityMutex_Lock(void);
|
||||
void Android_ActivityMutex_Unlock(void);
|
||||
void Android_ActivityMutex_Lock_Running(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
175
externals/SDL/src/core/android/keyinfotable.h
vendored
Executable file
175
externals/SDL/src/core/android/keyinfotable.h
vendored
Executable file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_KeyInfo
|
||||
#define _ANDROID_KeyInfo
|
||||
|
||||
#include "SDL_scancode.h"
|
||||
#include "SDL_keycode.h"
|
||||
|
||||
/*
|
||||
This file is used by the keyboard code in SDL_uikitview.m to convert between characters
|
||||
passed in from the iPhone's virtual keyboard, and tuples of SDL_Scancode and SDL_keymods.
|
||||
For example unicharToUIKeyInfoTable['a'] would give you the scan code and keymod for lower
|
||||
case a.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Scancode code;
|
||||
uint16_t mod;
|
||||
} AndroidKeyInfo;
|
||||
|
||||
/* So far only ASCII characters here */
|
||||
static AndroidKeyInfo unicharToAndroidKeyInfoTable[] = {
|
||||
/* 0 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 1 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 2 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 3 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 4 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 5 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 6 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 7 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 8 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 9 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 10 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 11 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 12 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 13 */ { SDL_SCANCODE_RETURN, 0 },
|
||||
/* 14 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 15 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 16 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 17 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 18 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 19 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 20 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 21 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 22 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 23 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 24 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 25 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 26 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 27 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 28 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 29 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 30 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 31 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 32 */ { SDL_SCANCODE_SPACE, 0 },
|
||||
/* 33 */ { SDL_SCANCODE_1, KMOD_SHIFT }, /* plus shift modifier '!' */
|
||||
/* 34 */ { SDL_SCANCODE_APOSTROPHE, KMOD_SHIFT }, /* plus shift modifier '"' */
|
||||
/* 35 */ { SDL_SCANCODE_3, KMOD_SHIFT }, /* plus shift modifier '#' */
|
||||
/* 36 */ { SDL_SCANCODE_4, KMOD_SHIFT }, /* plus shift modifier '$' */
|
||||
/* 37 */ { SDL_SCANCODE_5, KMOD_SHIFT }, /* plus shift modifier '%' */
|
||||
/* 38 */ { SDL_SCANCODE_7, KMOD_SHIFT }, /* plus shift modifier '&' */
|
||||
/* 39 */ { SDL_SCANCODE_APOSTROPHE, 0 }, /* ''' */
|
||||
/* 40 */ { SDL_SCANCODE_9, KMOD_SHIFT }, /* plus shift modifier '(' */
|
||||
/* 41 */ { SDL_SCANCODE_0, KMOD_SHIFT }, /* plus shift modifier ')' */
|
||||
/* 42 */ { SDL_SCANCODE_8, KMOD_SHIFT }, /* '*' */
|
||||
/* 43 */ { SDL_SCANCODE_EQUALS, KMOD_SHIFT }, /* plus shift modifier '+' */
|
||||
/* 44 */ { SDL_SCANCODE_COMMA, 0 }, /* ',' */
|
||||
/* 45 */ { SDL_SCANCODE_MINUS, 0 }, /* '-' */
|
||||
/* 46 */ { SDL_SCANCODE_PERIOD, 0 }, /* '.' */
|
||||
/* 47 */ { SDL_SCANCODE_SLASH, 0 }, /* '/' */
|
||||
/* 48 */ { SDL_SCANCODE_0, 0 },
|
||||
/* 49 */ { SDL_SCANCODE_1, 0 },
|
||||
/* 50 */ { SDL_SCANCODE_2, 0 },
|
||||
/* 51 */ { SDL_SCANCODE_3, 0 },
|
||||
/* 52 */ { SDL_SCANCODE_4, 0 },
|
||||
/* 53 */ { SDL_SCANCODE_5, 0 },
|
||||
/* 54 */ { SDL_SCANCODE_6, 0 },
|
||||
/* 55 */ { SDL_SCANCODE_7, 0 },
|
||||
/* 56 */ { SDL_SCANCODE_8, 0 },
|
||||
/* 57 */ { SDL_SCANCODE_9, 0 },
|
||||
/* 58 */ { SDL_SCANCODE_SEMICOLON, KMOD_SHIFT }, /* plus shift modifier ';' */
|
||||
/* 59 */ { SDL_SCANCODE_SEMICOLON, 0 },
|
||||
/* 60 */ { SDL_SCANCODE_COMMA, KMOD_SHIFT }, /* plus shift modifier '<' */
|
||||
/* 61 */ { SDL_SCANCODE_EQUALS, 0 },
|
||||
/* 62 */ { SDL_SCANCODE_PERIOD, KMOD_SHIFT }, /* plus shift modifier '>' */
|
||||
/* 63 */ { SDL_SCANCODE_SLASH, KMOD_SHIFT }, /* plus shift modifier '?' */
|
||||
/* 64 */ { SDL_SCANCODE_2, KMOD_SHIFT }, /* plus shift modifier '@' */
|
||||
/* 65 */ { SDL_SCANCODE_A, KMOD_SHIFT }, /* all the following need shift modifiers */
|
||||
/* 66 */ { SDL_SCANCODE_B, KMOD_SHIFT },
|
||||
/* 67 */ { SDL_SCANCODE_C, KMOD_SHIFT },
|
||||
/* 68 */ { SDL_SCANCODE_D, KMOD_SHIFT },
|
||||
/* 69 */ { SDL_SCANCODE_E, KMOD_SHIFT },
|
||||
/* 70 */ { SDL_SCANCODE_F, KMOD_SHIFT },
|
||||
/* 71 */ { SDL_SCANCODE_G, KMOD_SHIFT },
|
||||
/* 72 */ { SDL_SCANCODE_H, KMOD_SHIFT },
|
||||
/* 73 */ { SDL_SCANCODE_I, KMOD_SHIFT },
|
||||
/* 74 */ { SDL_SCANCODE_J, KMOD_SHIFT },
|
||||
/* 75 */ { SDL_SCANCODE_K, KMOD_SHIFT },
|
||||
/* 76 */ { SDL_SCANCODE_L, KMOD_SHIFT },
|
||||
/* 77 */ { SDL_SCANCODE_M, KMOD_SHIFT },
|
||||
/* 78 */ { SDL_SCANCODE_N, KMOD_SHIFT },
|
||||
/* 79 */ { SDL_SCANCODE_O, KMOD_SHIFT },
|
||||
/* 80 */ { SDL_SCANCODE_P, KMOD_SHIFT },
|
||||
/* 81 */ { SDL_SCANCODE_Q, KMOD_SHIFT },
|
||||
/* 82 */ { SDL_SCANCODE_R, KMOD_SHIFT },
|
||||
/* 83 */ { SDL_SCANCODE_S, KMOD_SHIFT },
|
||||
/* 84 */ { SDL_SCANCODE_T, KMOD_SHIFT },
|
||||
/* 85 */ { SDL_SCANCODE_U, KMOD_SHIFT },
|
||||
/* 86 */ { SDL_SCANCODE_V, KMOD_SHIFT },
|
||||
/* 87 */ { SDL_SCANCODE_W, KMOD_SHIFT },
|
||||
/* 88 */ { SDL_SCANCODE_X, KMOD_SHIFT },
|
||||
/* 89 */ { SDL_SCANCODE_Y, KMOD_SHIFT },
|
||||
/* 90 */ { SDL_SCANCODE_Z, KMOD_SHIFT },
|
||||
/* 91 */ { SDL_SCANCODE_LEFTBRACKET, 0 },
|
||||
/* 92 */ { SDL_SCANCODE_BACKSLASH, 0 },
|
||||
/* 93 */ { SDL_SCANCODE_RIGHTBRACKET, 0 },
|
||||
/* 94 */ { SDL_SCANCODE_6, KMOD_SHIFT }, /* plus shift modifier '^' */
|
||||
/* 95 */ { SDL_SCANCODE_MINUS, KMOD_SHIFT }, /* plus shift modifier '_' */
|
||||
/* 96 */ { SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* '`' */
|
||||
/* 97 */ { SDL_SCANCODE_A, 0 },
|
||||
/* 98 */ { SDL_SCANCODE_B, 0 },
|
||||
/* 99 */ { SDL_SCANCODE_C, 0 },
|
||||
/* 100 */{ SDL_SCANCODE_D, 0 },
|
||||
/* 101 */{ SDL_SCANCODE_E, 0 },
|
||||
/* 102 */{ SDL_SCANCODE_F, 0 },
|
||||
/* 103 */{ SDL_SCANCODE_G, 0 },
|
||||
/* 104 */{ SDL_SCANCODE_H, 0 },
|
||||
/* 105 */{ SDL_SCANCODE_I, 0 },
|
||||
/* 106 */{ SDL_SCANCODE_J, 0 },
|
||||
/* 107 */{ SDL_SCANCODE_K, 0 },
|
||||
/* 108 */{ SDL_SCANCODE_L, 0 },
|
||||
/* 109 */{ SDL_SCANCODE_M, 0 },
|
||||
/* 110 */{ SDL_SCANCODE_N, 0 },
|
||||
/* 111 */{ SDL_SCANCODE_O, 0 },
|
||||
/* 112 */{ SDL_SCANCODE_P, 0 },
|
||||
/* 113 */{ SDL_SCANCODE_Q, 0 },
|
||||
/* 114 */{ SDL_SCANCODE_R, 0 },
|
||||
/* 115 */{ SDL_SCANCODE_S, 0 },
|
||||
/* 116 */{ SDL_SCANCODE_T, 0 },
|
||||
/* 117 */{ SDL_SCANCODE_U, 0 },
|
||||
/* 118 */{ SDL_SCANCODE_V, 0 },
|
||||
/* 119 */{ SDL_SCANCODE_W, 0 },
|
||||
/* 120 */{ SDL_SCANCODE_X, 0 },
|
||||
/* 121 */{ SDL_SCANCODE_Y, 0 },
|
||||
/* 122 */{ SDL_SCANCODE_Z, 0 },
|
||||
/* 123 */{ SDL_SCANCODE_LEFTBRACKET, KMOD_SHIFT }, /* plus shift modifier '{' */
|
||||
/* 124 */{ SDL_SCANCODE_BACKSLASH, KMOD_SHIFT }, /* plus shift modifier '|' */
|
||||
/* 125 */{ SDL_SCANCODE_RIGHTBRACKET, KMOD_SHIFT }, /* plus shift modifier '}' */
|
||||
/* 126 */{ SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* plus shift modifier '~' */
|
||||
/* 127 */{ SDL_SCANCODE_BACKSPACE, KMOD_SHIFT }
|
||||
};
|
||||
|
||||
#endif /* _ANDROID_KeyInfo */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
359
externals/SDL/src/core/linux/SDL_dbus.c
vendored
Executable file
359
externals/SDL/src/core/linux/SDL_dbus.c
vendored
Executable file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_dbus.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* we never link directly to libdbus. */
|
||||
#include "SDL_loadso.h"
|
||||
static const char *dbus_library = "libdbus-1.so.3";
|
||||
static void *dbus_handle = NULL;
|
||||
static unsigned int screensaver_cookie = 0;
|
||||
static SDL_DBusContext dbus;
|
||||
|
||||
static int
|
||||
LoadDBUSSyms(void)
|
||||
{
|
||||
#define SDL_DBUS_SYM2(x, y) \
|
||||
if (!(dbus.x = SDL_LoadFunction(dbus_handle, #y))) return -1
|
||||
|
||||
#define SDL_DBUS_SYM(x) \
|
||||
SDL_DBUS_SYM2(x, dbus_##x)
|
||||
|
||||
SDL_DBUS_SYM(bus_get_private);
|
||||
SDL_DBUS_SYM(bus_register);
|
||||
SDL_DBUS_SYM(bus_add_match);
|
||||
SDL_DBUS_SYM(connection_open_private);
|
||||
SDL_DBUS_SYM(connection_set_exit_on_disconnect);
|
||||
SDL_DBUS_SYM(connection_get_is_connected);
|
||||
SDL_DBUS_SYM(connection_add_filter);
|
||||
SDL_DBUS_SYM(connection_try_register_object_path);
|
||||
SDL_DBUS_SYM(connection_send);
|
||||
SDL_DBUS_SYM(connection_send_with_reply_and_block);
|
||||
SDL_DBUS_SYM(connection_close);
|
||||
SDL_DBUS_SYM(connection_unref);
|
||||
SDL_DBUS_SYM(connection_flush);
|
||||
SDL_DBUS_SYM(connection_read_write);
|
||||
SDL_DBUS_SYM(connection_dispatch);
|
||||
SDL_DBUS_SYM(message_is_signal);
|
||||
SDL_DBUS_SYM(message_new_method_call);
|
||||
SDL_DBUS_SYM(message_append_args);
|
||||
SDL_DBUS_SYM(message_append_args_valist);
|
||||
SDL_DBUS_SYM(message_get_args);
|
||||
SDL_DBUS_SYM(message_get_args_valist);
|
||||
SDL_DBUS_SYM(message_iter_init);
|
||||
SDL_DBUS_SYM(message_iter_next);
|
||||
SDL_DBUS_SYM(message_iter_get_basic);
|
||||
SDL_DBUS_SYM(message_iter_get_arg_type);
|
||||
SDL_DBUS_SYM(message_iter_recurse);
|
||||
SDL_DBUS_SYM(message_unref);
|
||||
SDL_DBUS_SYM(error_init);
|
||||
SDL_DBUS_SYM(error_is_set);
|
||||
SDL_DBUS_SYM(error_free);
|
||||
SDL_DBUS_SYM(get_local_machine_id);
|
||||
SDL_DBUS_SYM(free);
|
||||
SDL_DBUS_SYM(free_string_array);
|
||||
SDL_DBUS_SYM(shutdown);
|
||||
|
||||
#undef SDL_DBUS_SYM
|
||||
#undef SDL_DBUS_SYM2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UnloadDBUSLibrary(void)
|
||||
{
|
||||
if (dbus_handle != NULL) {
|
||||
SDL_UnloadObject(dbus_handle);
|
||||
dbus_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadDBUSLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (dbus_handle == NULL) {
|
||||
dbus_handle = SDL_LoadObject(dbus_library);
|
||||
if (dbus_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
} else {
|
||||
retval = LoadDBUSSyms();
|
||||
if (retval < 0) {
|
||||
UnloadDBUSLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Init(void)
|
||||
{
|
||||
static SDL_bool is_dbus_available = SDL_TRUE;
|
||||
if (!is_dbus_available) {
|
||||
return; /* don't keep trying if this fails. */
|
||||
}
|
||||
|
||||
if (!dbus.session_conn) {
|
||||
DBusError err;
|
||||
|
||||
if (LoadDBUSLibrary() == -1) {
|
||||
is_dbus_available = SDL_FALSE; /* can't load at all? Don't keep trying. */
|
||||
return; /* oh well */
|
||||
}
|
||||
|
||||
dbus.error_init(&err);
|
||||
dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
|
||||
if (!dbus.error_is_set(&err)) {
|
||||
dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err);
|
||||
}
|
||||
if (dbus.error_is_set(&err)) {
|
||||
dbus.error_free(&err);
|
||||
SDL_DBus_Quit();
|
||||
is_dbus_available = SDL_FALSE;
|
||||
return; /* oh well */
|
||||
}
|
||||
dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
|
||||
dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Quit(void)
|
||||
{
|
||||
if (dbus.system_conn) {
|
||||
dbus.connection_close(dbus.system_conn);
|
||||
dbus.connection_unref(dbus.system_conn);
|
||||
}
|
||||
if (dbus.session_conn) {
|
||||
dbus.connection_close(dbus.session_conn);
|
||||
dbus.connection_unref(dbus.session_conn);
|
||||
}
|
||||
/* Don't do this - bug 3950
|
||||
dbus_shutdown() is a debug feature which closes all global resources in the dbus library. Calling this should be done by the app, not a library, because if there are multiple users of dbus in the process then SDL could shut it down even though another part is using it.
|
||||
*/
|
||||
#if 0
|
||||
if (dbus.shutdown) {
|
||||
dbus.shutdown();
|
||||
}
|
||||
#endif
|
||||
SDL_zero(dbus);
|
||||
UnloadDBUSLibrary();
|
||||
}
|
||||
|
||||
SDL_DBusContext *
|
||||
SDL_DBus_GetContext(void)
|
||||
{
|
||||
if (!dbus_handle || !dbus.session_conn) {
|
||||
SDL_DBus_Init();
|
||||
}
|
||||
|
||||
return (dbus_handle && dbus.session_conn) ? &dbus : NULL;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
if (conn) {
|
||||
DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
|
||||
if (msg) {
|
||||
int firstarg;
|
||||
va_list ap_reply;
|
||||
va_copy(ap_reply, ap); /* copy the arg list so we don't compete with D-Bus for it */
|
||||
firstarg = va_arg(ap, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
|
||||
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
/* skip any input args, get to output args. */
|
||||
while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) {
|
||||
/* we assume D-Bus already validated all this. */
|
||||
{ void *dumpptr = va_arg(ap_reply, void*); (void) dumpptr; }
|
||||
if (firstarg == DBUS_TYPE_ARRAY) {
|
||||
{ const int dumpint = va_arg(ap_reply, int); (void) dumpint; }
|
||||
}
|
||||
}
|
||||
firstarg = va_arg(ap_reply, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) {
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
dbus.message_unref(reply);
|
||||
}
|
||||
}
|
||||
va_end(ap_reply);
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
|
||||
{
|
||||
SDL_bool retval;
|
||||
va_list ap;
|
||||
va_start(ap, method);
|
||||
retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...)
|
||||
{
|
||||
SDL_bool retval;
|
||||
va_list ap;
|
||||
va_start(ap, method);
|
||||
retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
if (conn) {
|
||||
DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
|
||||
if (msg) {
|
||||
int firstarg = va_arg(ap, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
|
||||
if (dbus.connection_send(conn, msg, NULL)) {
|
||||
dbus.connection_flush(conn);
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
|
||||
{
|
||||
SDL_bool retval;
|
||||
va_list ap;
|
||||
va_start(ap, method);
|
||||
retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
|
||||
{
|
||||
SDL_bool retval;
|
||||
va_list ap;
|
||||
va_start(ap, method);
|
||||
retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
if (conn) {
|
||||
DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
|
||||
if (msg) {
|
||||
if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
|
||||
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
DBusMessageIter iter, sub;
|
||||
dbus.message_iter_init(reply, &iter);
|
||||
if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
|
||||
dbus.message_iter_recurse(&iter, &sub);
|
||||
if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
|
||||
dbus.message_iter_get_basic(&sub, result);
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
dbus.message_unref(reply);
|
||||
}
|
||||
}
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
|
||||
{
|
||||
return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SDL_DBus_ScreensaverTickle(void)
|
||||
{
|
||||
if (screensaver_cookie == 0) { /* no need to tickle if we're inhibiting. */
|
||||
/* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
|
||||
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
{
|
||||
if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
const char *node = "org.freedesktop.ScreenSaver";
|
||||
const char *path = "/org/freedesktop/ScreenSaver";
|
||||
const char *interface = "org.freedesktop.ScreenSaver";
|
||||
|
||||
if (inhibit) {
|
||||
const char *app = "My SDL application";
|
||||
const char *reason = "Playing a game";
|
||||
if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
|
||||
DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
|
||||
} else {
|
||||
if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
screensaver_cookie = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
96
externals/SDL/src/core/linux/SDL_dbus.h
vendored
Executable file
96
externals/SDL/src/core/linux/SDL_dbus.h
vendored
Executable file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_dbus_h_
|
||||
#define SDL_dbus_h_
|
||||
|
||||
#ifdef HAVE_DBUS_DBUS_H
|
||||
#define SDL_USE_LIBDBUS 1
|
||||
#include "SDL_stdinc.h"
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
|
||||
typedef struct SDL_DBusContext {
|
||||
DBusConnection *session_conn;
|
||||
DBusConnection *system_conn;
|
||||
|
||||
DBusConnection *(*bus_get_private)(DBusBusType, DBusError *);
|
||||
dbus_bool_t (*bus_register)(DBusConnection *, DBusError *);
|
||||
void (*bus_add_match)(DBusConnection *, const char *, DBusError *);
|
||||
DBusConnection * (*connection_open_private)(const char *, DBusError *);
|
||||
void (*connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t);
|
||||
dbus_bool_t (*connection_get_is_connected)(DBusConnection *);
|
||||
dbus_bool_t (*connection_add_filter)(DBusConnection *, DBusHandleMessageFunction, void *, DBusFreeFunction);
|
||||
dbus_bool_t (*connection_try_register_object_path)(DBusConnection *, const char *,
|
||||
const DBusObjectPathVTable *, void *, DBusError *);
|
||||
dbus_bool_t (*connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *);
|
||||
DBusMessage *(*connection_send_with_reply_and_block)(DBusConnection *, DBusMessage *, int, DBusError *);
|
||||
void (*connection_close)(DBusConnection *);
|
||||
void (*connection_unref)(DBusConnection *);
|
||||
void (*connection_flush)(DBusConnection *);
|
||||
dbus_bool_t (*connection_read_write)(DBusConnection *, int);
|
||||
DBusDispatchStatus (*connection_dispatch)(DBusConnection *);
|
||||
dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *);
|
||||
DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
|
||||
dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
|
||||
dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list);
|
||||
dbus_bool_t (*message_get_args)(DBusMessage *, DBusError *, int, ...);
|
||||
dbus_bool_t (*message_get_args_valist)(DBusMessage *, DBusError *, int, va_list);
|
||||
dbus_bool_t (*message_iter_init)(DBusMessage *, DBusMessageIter *);
|
||||
dbus_bool_t (*message_iter_next)(DBusMessageIter *);
|
||||
void (*message_iter_get_basic)(DBusMessageIter *, void *);
|
||||
int (*message_iter_get_arg_type)(DBusMessageIter *);
|
||||
void (*message_iter_recurse)(DBusMessageIter *, DBusMessageIter *);
|
||||
void (*message_unref)(DBusMessage *);
|
||||
void (*error_init)(DBusError *);
|
||||
dbus_bool_t (*error_is_set)(const DBusError *);
|
||||
void (*error_free)(DBusError *);
|
||||
char *(*get_local_machine_id)(void);
|
||||
void (*free)(void *);
|
||||
void (*free_string_array)(char **);
|
||||
void (*shutdown)(void);
|
||||
|
||||
} SDL_DBusContext;
|
||||
|
||||
extern void SDL_DBus_Init(void);
|
||||
extern void SDL_DBus_Quit(void);
|
||||
extern SDL_DBusContext * SDL_DBus_GetContext(void);
|
||||
|
||||
/* These use the built-in Session connection. */
|
||||
extern SDL_bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...);
|
||||
extern SDL_bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...);
|
||||
extern SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result);
|
||||
|
||||
/* These use whatever connection you like. */
|
||||
extern SDL_bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
||||
extern SDL_bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
||||
extern SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result);
|
||||
|
||||
extern void SDL_DBus_ScreensaverTickle(void);
|
||||
extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
|
||||
|
||||
#endif /* HAVE_DBUS_DBUS_H */
|
||||
|
||||
#endif /* SDL_dbus_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
797
externals/SDL/src/core/linux/SDL_evdev.c
vendored
Executable file
797
externals/SDL/src/core/linux/SDL_evdev.c
vendored
Executable file
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
|
||||
/* This is based on the linux joystick driver */
|
||||
/* References: https://www.kernel.org/doc/Documentation/input/input.txt
|
||||
* https://www.kernel.org/doc/Documentation/input/event-codes.txt
|
||||
* /usr/include/linux/input.h
|
||||
* The evtest application is also useful to debug the protocol
|
||||
*/
|
||||
|
||||
#include "SDL_evdev.h"
|
||||
#include "SDL_evdev_kbd.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_scancode.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
|
||||
/* These are not defined in older Linux kernel headers */
|
||||
#ifndef SYN_DROPPED
|
||||
#define SYN_DROPPED 3
|
||||
#endif
|
||||
#ifndef ABS_MT_SLOT
|
||||
#define ABS_MT_SLOT 0x2f
|
||||
#define ABS_MT_POSITION_X 0x35
|
||||
#define ABS_MT_POSITION_Y 0x36
|
||||
#define ABS_MT_TRACKING_ID 0x39
|
||||
#define ABS_MT_PRESSURE 0x3a
|
||||
#endif
|
||||
|
||||
typedef struct SDL_evdevlist_item
|
||||
{
|
||||
char *path;
|
||||
int fd;
|
||||
|
||||
/* TODO: use this for every device, not just touchscreen */
|
||||
int out_of_sync;
|
||||
|
||||
/* TODO: expand on this to have data for every possible class (mouse,
|
||||
keyboard, touchpad, etc.). Also there's probably some things in here we
|
||||
can pull out to the SDL_evdevlist_item i.e. name */
|
||||
int is_touchscreen;
|
||||
struct {
|
||||
char* name;
|
||||
|
||||
int min_x, max_x, range_x;
|
||||
int min_y, max_y, range_y;
|
||||
int min_pressure, max_pressure, range_pressure;
|
||||
|
||||
int max_slots;
|
||||
int current_slot;
|
||||
struct {
|
||||
enum {
|
||||
EVDEV_TOUCH_SLOTDELTA_NONE = 0,
|
||||
EVDEV_TOUCH_SLOTDELTA_DOWN,
|
||||
EVDEV_TOUCH_SLOTDELTA_UP,
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE
|
||||
} delta;
|
||||
int tracking_id;
|
||||
int x, y, pressure;
|
||||
} * slots;
|
||||
|
||||
} * touchscreen_data;
|
||||
|
||||
struct SDL_evdevlist_item *next;
|
||||
} SDL_evdevlist_item;
|
||||
|
||||
typedef struct SDL_EVDEV_PrivateData
|
||||
{
|
||||
int ref_count;
|
||||
int num_devices;
|
||||
SDL_evdevlist_item *first;
|
||||
SDL_evdevlist_item *last;
|
||||
SDL_EVDEV_keyboard_state *kbd;
|
||||
} SDL_EVDEV_PrivateData;
|
||||
|
||||
#undef _THIS
|
||||
#define _THIS SDL_EVDEV_PrivateData *_this
|
||||
static _THIS = NULL;
|
||||
|
||||
static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
|
||||
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
|
||||
static int SDL_EVDEV_device_removed(const char *dev_path);
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
|
||||
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
|
||||
const char *dev_path);
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
static Uint8 EVDEV_MouseButtons[] = {
|
||||
SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */
|
||||
SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */
|
||||
SDL_BUTTON_MIDDLE, /* BTN_MIDDLE 0x112 */
|
||||
SDL_BUTTON_X1, /* BTN_SIDE 0x113 */
|
||||
SDL_BUTTON_X2, /* BTN_EXTRA 0x114 */
|
||||
SDL_BUTTON_X2 + 1, /* BTN_FORWARD 0x115 */
|
||||
SDL_BUTTON_X2 + 2, /* BTN_BACK 0x116 */
|
||||
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
|
||||
};
|
||||
|
||||
static int
|
||||
SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
/* Mice already send relative events through this interface */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_EVDEV_Init(void)
|
||||
{
|
||||
if (_this == NULL) {
|
||||
_this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
|
||||
if (_this == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
SDL_free(_this);
|
||||
_this = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up the udev callback */
|
||||
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
SDL_free(_this);
|
||||
_this = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Force a scan to build the initial device list */
|
||||
SDL_UDEV_Scan();
|
||||
#else
|
||||
/* TODO: Scan the devices manually, like a caveman */
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
_this->kbd = SDL_EVDEV_kbd_init();
|
||||
}
|
||||
|
||||
SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
|
||||
|
||||
_this->ref_count += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_Quit(void)
|
||||
{
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_this->ref_count -= 1;
|
||||
|
||||
if (_this->ref_count < 1) {
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
|
||||
SDL_UDEV_Quit();
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
SDL_EVDEV_kbd_quit(_this->kbd);
|
||||
|
||||
/* Remove existing devices */
|
||||
while(_this->first != NULL) {
|
||||
SDL_EVDEV_device_removed(_this->first->path);
|
||||
}
|
||||
|
||||
SDL_assert(_this->first == NULL);
|
||||
SDL_assert(_this->last == NULL);
|
||||
SDL_assert(_this->num_devices == 0);
|
||||
|
||||
SDL_free(_this);
|
||||
_this = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
|
||||
const char* dev_path)
|
||||
{
|
||||
if (dev_path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(udev_event) {
|
||||
case SDL_UDEV_DEVICEADDED:
|
||||
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
|
||||
SDL_UDEV_DEVICE_TOUCHSCREEN)))
|
||||
return;
|
||||
|
||||
SDL_EVDEV_device_added(dev_path, udev_class);
|
||||
break;
|
||||
case SDL_UDEV_DEVICEREMOVED:
|
||||
SDL_EVDEV_device_removed(dev_path);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
void
|
||||
SDL_EVDEV_Poll(void)
|
||||
{
|
||||
struct input_event events[32];
|
||||
int i, j, len;
|
||||
SDL_evdevlist_item *item;
|
||||
SDL_Scancode scan_code;
|
||||
int mouse_button;
|
||||
SDL_Mouse *mouse;
|
||||
float norm_x, norm_y, norm_pressure;
|
||||
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_Poll();
|
||||
#endif
|
||||
|
||||
mouse = SDL_GetMouse();
|
||||
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
while ((len = read(item->fd, events, (sizeof events))) > 0) {
|
||||
len /= sizeof(events[0]);
|
||||
for (i = 0; i < len; ++i) {
|
||||
/* special handling for touchscreen, that should eventually be
|
||||
used for all devices */
|
||||
if (item->out_of_sync && item->is_touchscreen &&
|
||||
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (events[i].type) {
|
||||
case EV_KEY:
|
||||
if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
|
||||
mouse_button = events[i].code - BTN_MOUSE;
|
||||
if (events[i].value == 0) {
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
|
||||
} else if (events[i].value == 1) {
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* BTH_TOUCH event value 1 indicates there is contact with
|
||||
a touchscreen or trackpad (earlist finger's current
|
||||
position is sent in EV_ABS ABS_X/ABS_Y, switching to
|
||||
next finger after earlist is released) */
|
||||
if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
|
||||
if (item->touchscreen_data->max_slots == 1) {
|
||||
if (events[i].value)
|
||||
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
||||
else
|
||||
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Probably keyboard */
|
||||
scan_code = SDL_EVDEV_translate_keycode(events[i].code);
|
||||
if (scan_code != SDL_SCANCODE_UNKNOWN) {
|
||||
if (events[i].value == 0) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
|
||||
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
|
||||
}
|
||||
}
|
||||
SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
|
||||
break;
|
||||
case EV_ABS:
|
||||
switch(events[i].code) {
|
||||
case ABS_MT_SLOT:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
item->touchscreen_data->current_slot = events[i].value;
|
||||
break;
|
||||
case ABS_MT_TRACKING_ID:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
if (events[i].value >= 0) {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value;
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
||||
} else {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
||||
}
|
||||
break;
|
||||
case ABS_MT_POSITION_X:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
|
||||
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_MT_POSITION_Y:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
|
||||
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_MT_PRESSURE:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = events[i].value;
|
||||
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_X:
|
||||
if (item->is_touchscreen) {
|
||||
if (item->touchscreen_data->max_slots != 1)
|
||||
break;
|
||||
item->touchscreen_data->slots[0].x = events[i].value;
|
||||
} else
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
|
||||
break;
|
||||
case ABS_Y:
|
||||
if (item->is_touchscreen) {
|
||||
if (item->touchscreen_data->max_slots != 1)
|
||||
break;
|
||||
item->touchscreen_data->slots[0].y = events[i].value;
|
||||
} else
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EV_REL:
|
||||
switch(events[i].code) {
|
||||
case REL_X:
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
|
||||
break;
|
||||
case REL_Y:
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
|
||||
break;
|
||||
case REL_WHEEL:
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EV_SYN:
|
||||
switch (events[i].code) {
|
||||
case SYN_REPORT:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
|
||||
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
|
||||
norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) /
|
||||
(float)item->touchscreen_data->range_x;
|
||||
norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
|
||||
(float)item->touchscreen_data->range_y;
|
||||
|
||||
if (item->touchscreen_data->range_pressure > 0) {
|
||||
norm_pressure = (float)(item->touchscreen_data->slots[j].pressure - item->touchscreen_data->min_pressure) /
|
||||
(float)item->touchscreen_data->range_pressure;
|
||||
} else {
|
||||
/* This touchscreen does not support pressure */
|
||||
norm_pressure = 1.0f;
|
||||
}
|
||||
|
||||
/* FIXME: the touch's window shouldn't be null, but
|
||||
* the coordinate space of touch positions needs to
|
||||
* be window-relative in that case. */
|
||||
switch(item->touchscreen_data->slots[j].delta) {
|
||||
case EVDEV_TOUCH_SLOTDELTA_DOWN:
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
case EVDEV_TOUCH_SLOTDELTA_UP:
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].tracking_id = -1;
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
case EVDEV_TOUCH_SLOTDELTA_MOVE:
|
||||
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->out_of_sync)
|
||||
item->out_of_sync = 0;
|
||||
break;
|
||||
case SYN_DROPPED:
|
||||
if (item->is_touchscreen)
|
||||
item->out_of_sync = 1;
|
||||
SDL_EVDEV_sync_device(item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Scancode
|
||||
SDL_EVDEV_translate_keycode(int keycode)
|
||||
{
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
|
||||
if (keycode < SDL_arraysize(linux_scancode_table)) {
|
||||
scancode = linux_scancode_table[keycode];
|
||||
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
|
||||
you get an unexpected BTN_TOUCH from something SDL believes is not
|
||||
a touch device. In this case, we'd rather not get a misleading
|
||||
SDL_Log message about an unknown key. */
|
||||
if (keycode != BTN_TOUCH) {
|
||||
SDL_Log("The key you just pressed is not recognized by SDL. To help "
|
||||
"get this fixed, please report this to the SDL forums/mailing list "
|
||||
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scancode;
|
||||
}
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
static int
|
||||
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned long xreq, yreq;
|
||||
char name[64];
|
||||
struct input_absinfo abs_info;
|
||||
|
||||
if (!item->is_touchscreen)
|
||||
return 0;
|
||||
|
||||
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
|
||||
if (item->touchscreen_data == NULL)
|
||||
return SDL_OutOfMemory();
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen name");
|
||||
}
|
||||
|
||||
item->touchscreen_data->name = SDL_strdup(name);
|
||||
if (item->touchscreen_data->name == NULL) {
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
|
||||
if (abs_info.maximum == 0) {
|
||||
item->touchscreen_data->max_slots = 1;
|
||||
xreq = EVIOCGABS(ABS_X);
|
||||
yreq = EVIOCGABS(ABS_Y);
|
||||
} else {
|
||||
item->touchscreen_data->max_slots = abs_info.maximum + 1;
|
||||
xreq = EVIOCGABS(ABS_MT_POSITION_X);
|
||||
yreq = EVIOCGABS(ABS_MT_POSITION_Y);
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, xreq, &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
item->touchscreen_data->min_x = abs_info.minimum;
|
||||
item->touchscreen_data->max_x = abs_info.maximum;
|
||||
item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
ret = ioctl(item->fd, yreq, &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
item->touchscreen_data->min_y = abs_info.minimum;
|
||||
item->touchscreen_data->max_y = abs_info.maximum;
|
||||
item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_PRESSURE), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
item->touchscreen_data->min_pressure = abs_info.minimum;
|
||||
item->touchscreen_data->max_pressure = abs_info.maximum;
|
||||
item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
item->touchscreen_data->slots = SDL_calloc(
|
||||
item->touchscreen_data->max_slots,
|
||||
sizeof(*item->touchscreen_data->slots));
|
||||
if (item->touchscreen_data->slots == NULL) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
item->touchscreen_data->slots[i].tracking_id = -1;
|
||||
}
|
||||
|
||||
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
|
||||
SDL_TOUCH_DEVICE_DIRECT,
|
||||
item->touchscreen_data->name);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->slots);
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
static void
|
||||
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
|
||||
if (!item->is_touchscreen)
|
||||
return;
|
||||
|
||||
SDL_DelTouch(item->fd);
|
||||
SDL_free(item->touchscreen_data->slots);
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
||||
{
|
||||
#ifdef EVIOCGMTSLOTS
|
||||
int i, ret;
|
||||
struct input_absinfo abs_info;
|
||||
/*
|
||||
* struct input_mt_request_layout {
|
||||
* __u32 code;
|
||||
* __s32 values[num_slots];
|
||||
* };
|
||||
*
|
||||
* this is the structure we're trying to emulate
|
||||
*/
|
||||
Uint32* mt_req_code;
|
||||
Sint32* mt_req_values;
|
||||
size_t mt_req_size;
|
||||
|
||||
/* TODO: sync devices other than touchscreen */
|
||||
if (!item->is_touchscreen)
|
||||
return;
|
||||
|
||||
mt_req_size = sizeof(*mt_req_code) +
|
||||
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
|
||||
|
||||
mt_req_code = SDL_calloc(1, mt_req_size);
|
||||
if (mt_req_code == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mt_req_values = (Sint32*)mt_req_code + 1;
|
||||
|
||||
*mt_req_code = ABS_MT_TRACKING_ID;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
/*
|
||||
* This doesn't account for the very edge case of the user removing their
|
||||
* finger and replacing it on the screen during the time we're out of sync,
|
||||
* which'll mean that we're not going from down -> up or up -> down, we're
|
||||
* going from down -> down but with a different tracking id, meaning we'd
|
||||
* have to tell SDL of the two events, but since we wait till SYN_REPORT in
|
||||
* SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't
|
||||
* allow it. Lets just pray to God it doesn't happen.
|
||||
*/
|
||||
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
|
||||
mt_req_values[i] >= 0) {
|
||||
item->touchscreen_data->slots[i].tracking_id = mt_req_values[i];
|
||||
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
||||
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
||||
mt_req_values[i] < 0) {
|
||||
item->touchscreen_data->slots[i].tracking_id = -1;
|
||||
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
||||
}
|
||||
}
|
||||
|
||||
*mt_req_code = ABS_MT_POSITION_X;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
||||
item->touchscreen_data->slots[i].x != mt_req_values[i]) {
|
||||
item->touchscreen_data->slots[i].x = mt_req_values[i];
|
||||
if (item->touchscreen_data->slots[i].delta ==
|
||||
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[i].delta =
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*mt_req_code = ABS_MT_POSITION_Y;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
||||
item->touchscreen_data->slots[i].y != mt_req_values[i]) {
|
||||
item->touchscreen_data->slots[i].y = mt_req_values[i];
|
||||
if (item->touchscreen_data->slots[i].delta ==
|
||||
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[i].delta =
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*mt_req_code = ABS_MT_PRESSURE;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
||||
item->touchscreen_data->slots[i].pressure != mt_req_values[i]) {
|
||||
item->touchscreen_data->slots[i].pressure = mt_req_values[i];
|
||||
if (item->touchscreen_data->slots[i].delta ==
|
||||
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[i].delta =
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
item->touchscreen_data->current_slot = abs_info.value;
|
||||
|
||||
SDL_free(mt_req_code);
|
||||
|
||||
#endif /* EVIOCGMTSLOTS */
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
static int
|
||||
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
{
|
||||
int ret;
|
||||
SDL_evdevlist_item *item;
|
||||
|
||||
/* Check to make sure it's not already in list. */
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
if (SDL_strcmp(dev_path, item->path) == 0) {
|
||||
return -1; /* already have this one */
|
||||
}
|
||||
}
|
||||
|
||||
item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
|
||||
if (item == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
|
||||
if (item->fd < 0) {
|
||||
SDL_free(item);
|
||||
return SDL_SetError("Unable to open %s", dev_path);
|
||||
}
|
||||
|
||||
item->path = SDL_strdup(dev_path);
|
||||
if (item->path == NULL) {
|
||||
close(item->fd);
|
||||
SDL_free(item);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
|
||||
item->is_touchscreen = 1;
|
||||
|
||||
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
|
||||
close(item->fd);
|
||||
SDL_free(item);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->last == NULL) {
|
||||
_this->first = _this->last = item;
|
||||
} else {
|
||||
_this->last->next = item;
|
||||
_this->last = item;
|
||||
}
|
||||
|
||||
SDL_EVDEV_sync_device(item);
|
||||
|
||||
return _this->num_devices++;
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
static int
|
||||
SDL_EVDEV_device_removed(const char *dev_path)
|
||||
{
|
||||
SDL_evdevlist_item *item;
|
||||
SDL_evdevlist_item *prev = NULL;
|
||||
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
/* found it, remove it. */
|
||||
if (SDL_strcmp(dev_path, item->path) == 0) {
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(_this->first == item);
|
||||
_this->first = item->next;
|
||||
}
|
||||
if (item == _this->last) {
|
||||
_this->last = prev;
|
||||
}
|
||||
if (item->is_touchscreen) {
|
||||
SDL_EVDEV_destroy_touchscreen(item);
|
||||
}
|
||||
close(item->fd);
|
||||
SDL_free(item->path);
|
||||
SDL_free(item);
|
||||
_this->num_devices--;
|
||||
return 0;
|
||||
}
|
||||
prev = item;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_INPUT_LINUXEV */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
39
externals/SDL/src/core/linux/SDL_evdev.h
vendored
Executable file
39
externals/SDL/src/core/linux/SDL_evdev.h
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_evdev_h_
|
||||
#define SDL_evdev_h_
|
||||
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
|
||||
#include "SDL_events.h"
|
||||
|
||||
extern int SDL_EVDEV_Init(void);
|
||||
extern void SDL_EVDEV_Quit(void);
|
||||
extern void SDL_EVDEV_Poll(void);
|
||||
|
||||
#endif /* SDL_INPUT_LINUXEV */
|
||||
|
||||
#endif /* SDL_evdev_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
842
externals/SDL/src/core/linux/SDL_evdev_kbd.c
vendored
Executable file
842
externals/SDL/src/core/linux/SDL_evdev_kbd.c
vendored
Executable file
@@ -0,0 +1,842 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_evdev_kbd.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#ifdef SDL_INPUT_LINUXKD
|
||||
|
||||
/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/keyboard.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_evdev_kbd_default_accents.h"
|
||||
#include "SDL_evdev_kbd_default_keymap.h"
|
||||
|
||||
/* These are not defined in older Linux kernel headers */
|
||||
#ifndef K_UNICODE
|
||||
#define K_UNICODE 0x03
|
||||
#endif
|
||||
#ifndef K_OFF
|
||||
#define K_OFF 0x04
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handler Tables.
|
||||
*/
|
||||
|
||||
#define K_HANDLERS\
|
||||
k_self, k_fn, k_spec, k_pad,\
|
||||
k_dead, k_cons, k_cur, k_shift,\
|
||||
k_meta, k_ascii, k_lock, k_lowercase,\
|
||||
k_slock, k_dead2, k_brl, k_ignore
|
||||
|
||||
typedef void (k_handler_fn)(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag);
|
||||
static k_handler_fn K_HANDLERS;
|
||||
static k_handler_fn *k_handler[16] = { K_HANDLERS };
|
||||
|
||||
typedef void (fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
|
||||
static void fn_enter(SDL_EVDEV_keyboard_state *kbd);
|
||||
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd);
|
||||
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd);
|
||||
static void fn_num(SDL_EVDEV_keyboard_state *kbd);
|
||||
static void fn_compose(SDL_EVDEV_keyboard_state *kbd);
|
||||
|
||||
static fn_handler_fn *fn_handler[] =
|
||||
{
|
||||
NULL, fn_enter, NULL, NULL,
|
||||
NULL, NULL, NULL, fn_caps_toggle,
|
||||
fn_num, NULL, NULL, NULL,
|
||||
NULL, fn_caps_on, fn_compose, NULL,
|
||||
NULL, NULL, NULL, fn_num
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard State
|
||||
*/
|
||||
|
||||
struct SDL_EVDEV_keyboard_state
|
||||
{
|
||||
int console_fd;
|
||||
int old_kbd_mode;
|
||||
unsigned short **key_maps;
|
||||
unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
|
||||
SDL_bool dead_key_next;
|
||||
int npadch; /* -1 or number assembled on pad */
|
||||
struct kbdiacrs *accents;
|
||||
unsigned int diacr;
|
||||
SDL_bool rep; /* flag telling character repeat */
|
||||
unsigned char lockstate;
|
||||
unsigned char slockstate;
|
||||
unsigned char ledflagstate;
|
||||
char shift_state;
|
||||
char text[128];
|
||||
unsigned int text_len;
|
||||
};
|
||||
|
||||
#ifdef DUMP_ACCENTS
|
||||
static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("static struct kbdiacrs default_accents = {\n");
|
||||
printf(" %d,\n", kbd->accents->kb_cnt);
|
||||
printf(" {\n");
|
||||
for (i = 0; i < kbd->accents->kb_cnt; ++i) {
|
||||
struct kbdiacr *diacr = &kbd->accents->kbdiacr[i];
|
||||
printf(" { 0x%.2x, 0x%.2x, 0x%.2x },\n",
|
||||
diacr->diacr, diacr->base, diacr->result);
|
||||
}
|
||||
while (i < 256) {
|
||||
printf(" { 0x00, 0x00, 0x00 },\n");
|
||||
++i;
|
||||
}
|
||||
printf(" }\n");
|
||||
printf("};\n");
|
||||
}
|
||||
#endif /* DUMP_ACCENTS */
|
||||
|
||||
#ifdef DUMP_KEYMAP
|
||||
static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||
if (kbd->key_maps[i]) {
|
||||
printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
|
||||
for (j = 0; j < NR_KEYS; ++j) {
|
||||
if ((j%8) == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
printf("0x%.4x, ", kbd->key_maps[i][j]);
|
||||
}
|
||||
printf("\n};\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
|
||||
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||
if (kbd->key_maps[i]) {
|
||||
printf(" default_key_map_%d,\n", i);
|
||||
} else {
|
||||
printf(" NULL,\n");
|
||||
}
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
#endif /* DUMP_KEYMAP */
|
||||
|
||||
static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
kbd->key_maps = (unsigned short **)SDL_calloc(MAX_NR_KEYMAPS, sizeof(unsigned short *));
|
||||
if (!kbd->key_maps) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||
struct kbentry kbe;
|
||||
|
||||
kbe.kb_table = i;
|
||||
kbe.kb_index = 0;
|
||||
if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kbe.kb_value == K_NOSUCHMAP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kbd->key_maps[i] = (unsigned short *)SDL_malloc(NR_KEYS * sizeof(unsigned short));
|
||||
if (!kbd->key_maps[i]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = 0; j < NR_KEYS; ++j) {
|
||||
kbe.kb_table = i;
|
||||
kbe.kb_index = j;
|
||||
if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
|
||||
return -1;
|
||||
}
|
||||
kbd->key_maps[i][j] = (kbe.kb_value ^ 0xf000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_EVDEV_keyboard_state * kbd_cleanup_state = NULL;
|
||||
static int kbd_cleanup_sigactions_installed = 0;
|
||||
static int kbd_cleanup_atexit_installed = 0;
|
||||
|
||||
static struct sigaction old_sigaction[NSIG];
|
||||
|
||||
static int fatal_signals[] =
|
||||
{
|
||||
/* Handlers for SIGTERM and SIGINT are installed in SDL_QuitInit. */
|
||||
SIGHUP, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
|
||||
SIGSYS
|
||||
};
|
||||
|
||||
static void kbd_cleanup(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state* kbd = kbd_cleanup_state;
|
||||
if (kbd == NULL) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
|
||||
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_reraise_signal(int sig)
|
||||
{
|
||||
raise(sig);
|
||||
}
|
||||
|
||||
siginfo_t* SDL_EVDEV_kdb_cleanup_siginfo = NULL;
|
||||
void* SDL_EVDEV_kdb_cleanup_ucontext = NULL;
|
||||
|
||||
static void kbd_cleanup_signal_action(int signum, siginfo_t* info, void* ucontext)
|
||||
{
|
||||
struct sigaction* old_action_p = &(old_sigaction[signum]);
|
||||
sigset_t sigset;
|
||||
|
||||
/* Restore original signal handler before going any further. */
|
||||
sigaction(signum, old_action_p, NULL);
|
||||
|
||||
/* Unmask current signal. */
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, signum);
|
||||
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
||||
|
||||
/* Save original signal info and context for archeologists. */
|
||||
SDL_EVDEV_kdb_cleanup_siginfo = info;
|
||||
SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
|
||||
|
||||
/* Restore keyboard. */
|
||||
kbd_cleanup();
|
||||
|
||||
/* Reraise signal. */
|
||||
SDL_EVDEV_kbd_reraise_signal(signum);
|
||||
}
|
||||
|
||||
static void kbd_unregister_emerg_cleanup()
|
||||
{
|
||||
int tabidx, signum;
|
||||
|
||||
kbd_cleanup_state = NULL;
|
||||
|
||||
if (!kbd_cleanup_sigactions_installed) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_sigactions_installed = 0;
|
||||
|
||||
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
|
||||
struct sigaction* old_action_p;
|
||||
struct sigaction cur_action;
|
||||
signum = fatal_signals[tabidx];
|
||||
old_action_p = &(old_sigaction[signum]);
|
||||
|
||||
/* Examine current signal action */
|
||||
if (sigaction(signum, NULL, &cur_action))
|
||||
continue;
|
||||
|
||||
/* Check if action installed and not modifed */
|
||||
if (!(cur_action.sa_flags & SA_SIGINFO)
|
||||
|| cur_action.sa_sigaction != &kbd_cleanup_signal_action)
|
||||
continue;
|
||||
|
||||
/* Restore original action */
|
||||
sigaction(signum, old_action_p, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void kbd_cleanup_atexit(void)
|
||||
{
|
||||
/* Restore keyboard. */
|
||||
kbd_cleanup();
|
||||
|
||||
/* Try to restore signal handlers in case shared library is being unloaded */
|
||||
kbd_unregister_emerg_cleanup();
|
||||
}
|
||||
|
||||
static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state * kbd)
|
||||
{
|
||||
int tabidx, signum;
|
||||
|
||||
if (kbd_cleanup_state != NULL) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = kbd;
|
||||
|
||||
if (!kbd_cleanup_atexit_installed) {
|
||||
/* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish
|
||||
* functions that are called when the shared library is unloaded.
|
||||
* -- man atexit(3)
|
||||
*/
|
||||
atexit(kbd_cleanup_atexit);
|
||||
kbd_cleanup_atexit_installed = 1;
|
||||
}
|
||||
|
||||
if (kbd_cleanup_sigactions_installed) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_sigactions_installed = 1;
|
||||
|
||||
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
|
||||
struct sigaction* old_action_p;
|
||||
struct sigaction new_action;
|
||||
signum = fatal_signals[tabidx];
|
||||
old_action_p = &(old_sigaction[signum]);
|
||||
if (sigaction(signum, NULL, old_action_p))
|
||||
continue;
|
||||
|
||||
/* Skip SIGHUP and SIGPIPE if handler is already installed
|
||||
* - assume the handler will do the cleanup
|
||||
*/
|
||||
if ((signum == SIGHUP || signum == SIGPIPE)
|
||||
&& (old_action_p->sa_handler != SIG_DFL
|
||||
|| (void (*)(int))old_action_p->sa_sigaction != SIG_DFL))
|
||||
continue;
|
||||
|
||||
new_action = *old_action_p;
|
||||
new_action.sa_flags |= SA_SIGINFO;
|
||||
new_action.sa_sigaction = &kbd_cleanup_signal_action;
|
||||
sigaction(signum, &new_action, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_EVDEV_keyboard_state *
|
||||
SDL_EVDEV_kbd_init(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state *kbd;
|
||||
int i;
|
||||
char flag_state;
|
||||
char shift_state[ sizeof (long) ] = {TIOCL_GETSHIFTSTATE, 0};
|
||||
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
|
||||
if (!kbd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kbd->npadch = -1;
|
||||
|
||||
/* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
|
||||
kbd->console_fd = open("/dev/tty", O_RDONLY);
|
||||
|
||||
if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
|
||||
kbd->shift_state = *shift_state;
|
||||
}
|
||||
|
||||
if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
|
||||
kbd->ledflagstate = flag_state;
|
||||
}
|
||||
|
||||
kbd->accents = &default_accents;
|
||||
if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
|
||||
/* No worries, we'll use the default accent table */
|
||||
}
|
||||
|
||||
kbd->key_maps = default_key_maps;
|
||||
if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
|
||||
/* Set the keyboard in UNICODE mode and load the keymaps */
|
||||
ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
|
||||
|
||||
if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
|
||||
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||
if (kbd->key_maps[i]) {
|
||||
SDL_free(kbd->key_maps[i]);
|
||||
}
|
||||
}
|
||||
SDL_free(kbd->key_maps);
|
||||
|
||||
kbd->key_maps = default_key_maps;
|
||||
}
|
||||
|
||||
/* Allow inhibiting keyboard mute with env. variable for debugging etc. */
|
||||
if (getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
|
||||
/* Mute the keyboard so keystrokes only generate evdev events
|
||||
* and do not leak through to the console
|
||||
*/
|
||||
ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
|
||||
|
||||
/* Make sure to restore keyboard if application fails to call
|
||||
* SDL_Quit before exit or fatal signal is raised.
|
||||
*/
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
|
||||
kbd_register_emerg_cleanup(kbd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DUMP_ACCENTS
|
||||
SDL_EVDEV_dump_accents(kbd);
|
||||
#endif
|
||||
#ifdef DUMP_KEYMAP
|
||||
SDL_EVDEV_dump_keymap(kbd);
|
||||
#endif
|
||||
return kbd;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
|
||||
kbd_unregister_emerg_cleanup();
|
||||
|
||||
if (kbd->console_fd >= 0) {
|
||||
/* Restore the original keyboard mode */
|
||||
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
|
||||
close(kbd->console_fd);
|
||||
kbd->console_fd = -1;
|
||||
}
|
||||
|
||||
if (kbd->key_maps && kbd->key_maps != default_key_maps) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||
if (kbd->key_maps[i]) {
|
||||
SDL_free(kbd->key_maps[i]);
|
||||
}
|
||||
}
|
||||
SDL_free(kbd->key_maps);
|
||||
}
|
||||
|
||||
SDL_free(kbd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper Functions.
|
||||
*/
|
||||
static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c)
|
||||
{
|
||||
/* c is already part of a UTF-8 sequence and safe to add as a character */
|
||||
if (kbd->text_len < (sizeof(kbd->text)-1)) {
|
||||
kbd->text[kbd->text_len++] = (char)c;
|
||||
}
|
||||
}
|
||||
|
||||
static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c)
|
||||
{
|
||||
if (c < 0x80)
|
||||
/* 0******* */
|
||||
put_queue(kbd, c);
|
||||
else if (c < 0x800) {
|
||||
/* 110***** 10****** */
|
||||
put_queue(kbd, 0xc0 | (c >> 6));
|
||||
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||
} else if (c < 0x10000) {
|
||||
if (c >= 0xD800 && c < 0xE000)
|
||||
return;
|
||||
if (c == 0xFFFF)
|
||||
return;
|
||||
/* 1110**** 10****** 10****** */
|
||||
put_queue(kbd, 0xe0 | (c >> 12));
|
||||
put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
|
||||
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||
} else if (c < 0x110000) {
|
||||
/* 11110*** 10****** 10****** 10****** */
|
||||
put_queue(kbd, 0xf0 | (c >> 18));
|
||||
put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
|
||||
put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
|
||||
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a combining character DIACR here, followed by the character CH.
|
||||
* If the combination occurs in the table, return the corresponding value.
|
||||
* Otherwise, if CH is a space or equals DIACR, return DIACR.
|
||||
* Otherwise, conclude that DIACR was not combining after all,
|
||||
* queue it and return CH.
|
||||
*/
|
||||
static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
|
||||
{
|
||||
unsigned int d = kbd->diacr;
|
||||
unsigned int i;
|
||||
|
||||
kbd->diacr = 0;
|
||||
|
||||
for (i = 0; i < kbd->accents->kb_cnt; i++) {
|
||||
if (kbd->accents->kbdiacr[i].diacr == d &&
|
||||
kbd->accents->kbdiacr[i].base == ch) {
|
||||
return kbd->accents->kbdiacr[i].result;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == ' ' || ch == d)
|
||||
return d;
|
||||
|
||||
put_utf8(kbd, d);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
return (kbd->ledflagstate & flag) != 0;
|
||||
}
|
||||
|
||||
static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate |= flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate &= ~flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->lockstate ^= 1 << flag;
|
||||
}
|
||||
|
||||
static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->slockstate ^= 1 << flag;
|
||||
}
|
||||
|
||||
static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate ^= flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
/*
|
||||
* Special function handlers
|
||||
*/
|
||||
|
||||
static void fn_enter(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
if (kbd->diacr) {
|
||||
put_utf8(kbd, kbd->diacr);
|
||||
kbd->diacr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
if (kbd->rep)
|
||||
return;
|
||||
|
||||
chg_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||
}
|
||||
|
||||
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
if (kbd->rep)
|
||||
return;
|
||||
|
||||
set_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||
}
|
||||
|
||||
static void fn_num(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
if (!kbd->rep)
|
||||
chg_vc_kbd_led(kbd, K_NUMLOCK);
|
||||
}
|
||||
|
||||
static void fn_compose(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
kbd->dead_key_next = SDL_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special key handlers
|
||||
*/
|
||||
|
||||
static void k_ignore(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_spec(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
if (up_flag)
|
||||
return;
|
||||
if (value >= SDL_arraysize(fn_handler))
|
||||
return;
|
||||
if (fn_handler[value])
|
||||
fn_handler[value](kbd);
|
||||
}
|
||||
|
||||
static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
if (up_flag)
|
||||
return; /* no action, if this is a key release */
|
||||
|
||||
if (kbd->diacr)
|
||||
value = handle_diacr(kbd, value);
|
||||
|
||||
if (kbd->dead_key_next) {
|
||||
kbd->dead_key_next = SDL_FALSE;
|
||||
kbd->diacr = value;
|
||||
return;
|
||||
}
|
||||
put_utf8(kbd, value);
|
||||
}
|
||||
|
||||
static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag)
|
||||
{
|
||||
if (up_flag)
|
||||
return;
|
||||
|
||||
kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
|
||||
}
|
||||
|
||||
static void k_dead(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
|
||||
|
||||
k_deadunicode(kbd, ret_diacr[value], up_flag);
|
||||
}
|
||||
|
||||
static void k_dead2(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
k_deadunicode(kbd, value, up_flag);
|
||||
}
|
||||
|
||||
static void k_cons(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_fn(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_cur(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
static const char pad_chars[] = "0123456789+-*/\015,.?()#";
|
||||
|
||||
if (up_flag)
|
||||
return; /* no action, if this is a key release */
|
||||
|
||||
if (!vc_kbd_led(kbd, K_NUMLOCK)) {
|
||||
/* unprintable action */
|
||||
return;
|
||||
}
|
||||
|
||||
put_queue(kbd, pad_chars[value]);
|
||||
}
|
||||
|
||||
static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
int old_state = kbd->shift_state;
|
||||
|
||||
if (kbd->rep)
|
||||
return;
|
||||
/*
|
||||
* Mimic typewriter:
|
||||
* a CapsShift key acts like Shift but undoes CapsLock
|
||||
*/
|
||||
if (value == KVAL(K_CAPSSHIFT)) {
|
||||
value = KVAL(K_SHIFT);
|
||||
if (!up_flag)
|
||||
clr_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||
}
|
||||
|
||||
if (up_flag) {
|
||||
/*
|
||||
* handle the case that two shift or control
|
||||
* keys are depressed simultaneously
|
||||
*/
|
||||
if (kbd->shift_down[value])
|
||||
kbd->shift_down[value]--;
|
||||
} else
|
||||
kbd->shift_down[value]++;
|
||||
|
||||
if (kbd->shift_down[value])
|
||||
kbd->shift_state |= (1 << value);
|
||||
else
|
||||
kbd->shift_state &= ~(1 << value);
|
||||
|
||||
/* kludge */
|
||||
if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
|
||||
put_utf8(kbd, kbd->npadch);
|
||||
kbd->npadch = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void k_meta(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
int base;
|
||||
|
||||
if (up_flag)
|
||||
return;
|
||||
|
||||
if (value < 10) {
|
||||
/* decimal input of code, while Alt depressed */
|
||||
base = 10;
|
||||
} else {
|
||||
/* hexadecimal input of code, while AltGr depressed */
|
||||
value -= 10;
|
||||
base = 16;
|
||||
}
|
||||
|
||||
if (kbd->npadch == -1)
|
||||
kbd->npadch = value;
|
||||
else
|
||||
kbd->npadch = kbd->npadch * base + value;
|
||||
}
|
||||
|
||||
static void k_lock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
if (up_flag || kbd->rep)
|
||||
return;
|
||||
|
||||
chg_vc_kbd_lock(kbd, value);
|
||||
}
|
||||
|
||||
static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
k_shift(kbd, value, up_flag);
|
||||
if (up_flag || kbd->rep)
|
||||
return;
|
||||
|
||||
chg_vc_kbd_slock(kbd, value);
|
||||
/* try to make Alt, oops, AltGr and such work */
|
||||
if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
|
||||
kbd->slockstate = 0;
|
||||
chg_vc_kbd_slock(kbd, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void k_brl(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down)
|
||||
{
|
||||
unsigned char shift_final;
|
||||
unsigned char type;
|
||||
unsigned short *key_map;
|
||||
unsigned short keysym;
|
||||
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
|
||||
kbd->rep = (down == 2);
|
||||
|
||||
shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
|
||||
key_map = kbd->key_maps[shift_final];
|
||||
if (!key_map) {
|
||||
/* Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state */
|
||||
kbd->shift_state = 0;
|
||||
kbd->slockstate = 0;
|
||||
kbd->lockstate = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (keycode < NR_KEYS) {
|
||||
keysym = key_map[keycode];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
type = KTYP(keysym);
|
||||
|
||||
if (type < 0xf0) {
|
||||
if (down) {
|
||||
put_utf8(kbd, keysym);
|
||||
}
|
||||
} else {
|
||||
type -= 0xf0;
|
||||
|
||||
/* if type is KT_LETTER then it can be affected by Caps Lock */
|
||||
if (type == KT_LETTER) {
|
||||
type = KT_LATIN;
|
||||
|
||||
if (vc_kbd_led(kbd, K_CAPSLOCK)) {
|
||||
key_map = kbd->key_maps[shift_final ^ (1 << KG_SHIFT)];
|
||||
if (key_map) {
|
||||
keysym = key_map[keycode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*k_handler[type])(kbd, keysym & 0xff, !down);
|
||||
|
||||
if (type != KT_SLOCK) {
|
||||
kbd->slockstate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (kbd->text_len > 0) {
|
||||
kbd->text[kbd->text_len] = '\0';
|
||||
SDL_SendKeyboardText(kbd->text);
|
||||
kbd->text_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !SDL_INPUT_LINUXKD */
|
||||
|
||||
SDL_EVDEV_keyboard_state *
|
||||
SDL_EVDEV_kbd_init(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_INPUT_LINUXKD */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
34
externals/SDL/src/core/linux/SDL_evdev_kbd.h
vendored
Executable file
34
externals/SDL/src/core/linux/SDL_evdev_kbd.h
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_evdev_kbd_h_
|
||||
#define SDL_evdev_kbd_h_
|
||||
|
||||
struct SDL_EVDEV_keyboard_state;
|
||||
typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state;
|
||||
|
||||
extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void);
|
||||
extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down);
|
||||
extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state);
|
||||
|
||||
#endif /* SDL_evdev_kbd_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
284
externals/SDL/src/core/linux/SDL_evdev_kbd_default_accents.h
vendored
Executable file
284
externals/SDL/src/core/linux/SDL_evdev_kbd_default_accents.h
vendored
Executable file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
static struct kbdiacrs default_accents = {
|
||||
68,
|
||||
{
|
||||
{ 0x60, 0x41, 0xc0 },
|
||||
{ 0x60, 0x61, 0xe0 },
|
||||
{ 0x27, 0x41, 0xc1 },
|
||||
{ 0x27, 0x61, 0xe1 },
|
||||
{ 0x5e, 0x41, 0xc2 },
|
||||
{ 0x5e, 0x61, 0xe2 },
|
||||
{ 0x7e, 0x41, 0xc3 },
|
||||
{ 0x7e, 0x61, 0xe3 },
|
||||
{ 0x22, 0x41, 0xc4 },
|
||||
{ 0x22, 0x61, 0xe4 },
|
||||
{ 0x4f, 0x41, 0xc5 },
|
||||
{ 0x6f, 0x61, 0xe5 },
|
||||
{ 0x30, 0x41, 0xc5 },
|
||||
{ 0x30, 0x61, 0xe5 },
|
||||
{ 0x41, 0x41, 0xc5 },
|
||||
{ 0x61, 0x61, 0xe5 },
|
||||
{ 0x41, 0x45, 0xc6 },
|
||||
{ 0x61, 0x65, 0xe6 },
|
||||
{ 0x2c, 0x43, 0xc7 },
|
||||
{ 0x2c, 0x63, 0xe7 },
|
||||
{ 0x60, 0x45, 0xc8 },
|
||||
{ 0x60, 0x65, 0xe8 },
|
||||
{ 0x27, 0x45, 0xc9 },
|
||||
{ 0x27, 0x65, 0xe9 },
|
||||
{ 0x5e, 0x45, 0xca },
|
||||
{ 0x5e, 0x65, 0xea },
|
||||
{ 0x22, 0x45, 0xcb },
|
||||
{ 0x22, 0x65, 0xeb },
|
||||
{ 0x60, 0x49, 0xcc },
|
||||
{ 0x60, 0x69, 0xec },
|
||||
{ 0x27, 0x49, 0xcd },
|
||||
{ 0x27, 0x69, 0xed },
|
||||
{ 0x5e, 0x49, 0xce },
|
||||
{ 0x5e, 0x69, 0xee },
|
||||
{ 0x22, 0x49, 0xcf },
|
||||
{ 0x22, 0x69, 0xef },
|
||||
{ 0x2d, 0x44, 0xd0 },
|
||||
{ 0x2d, 0x64, 0xf0 },
|
||||
{ 0x7e, 0x4e, 0xd1 },
|
||||
{ 0x7e, 0x6e, 0xf1 },
|
||||
{ 0x60, 0x4f, 0xd2 },
|
||||
{ 0x60, 0x6f, 0xf2 },
|
||||
{ 0x27, 0x4f, 0xd3 },
|
||||
{ 0x27, 0x6f, 0xf3 },
|
||||
{ 0x5e, 0x4f, 0xd4 },
|
||||
{ 0x5e, 0x6f, 0xf4 },
|
||||
{ 0x7e, 0x4f, 0xd5 },
|
||||
{ 0x7e, 0x6f, 0xf5 },
|
||||
{ 0x22, 0x4f, 0xd6 },
|
||||
{ 0x22, 0x6f, 0xf6 },
|
||||
{ 0x2f, 0x4f, 0xd8 },
|
||||
{ 0x2f, 0x6f, 0xf8 },
|
||||
{ 0x60, 0x55, 0xd9 },
|
||||
{ 0x60, 0x75, 0xf9 },
|
||||
{ 0x27, 0x55, 0xda },
|
||||
{ 0x27, 0x75, 0xfa },
|
||||
{ 0x5e, 0x55, 0xdb },
|
||||
{ 0x5e, 0x75, 0xfb },
|
||||
{ 0x22, 0x55, 0xdc },
|
||||
{ 0x22, 0x75, 0xfc },
|
||||
{ 0x27, 0x59, 0xdd },
|
||||
{ 0x27, 0x79, 0xfd },
|
||||
{ 0x54, 0x48, 0xde },
|
||||
{ 0x74, 0x68, 0xfe },
|
||||
{ 0x73, 0x73, 0xdf },
|
||||
{ 0x22, 0x79, 0xff },
|
||||
{ 0x73, 0x7a, 0xdf },
|
||||
{ 0x69, 0x6a, 0xff },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00 },
|
||||
}
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
4763
externals/SDL/src/core/linux/SDL_evdev_kbd_default_keymap.h
vendored
Executable file
4763
externals/SDL/src/core/linux/SDL_evdev_kbd_default_keymap.h
vendored
Executable file
File diff suppressed because it is too large
Load Diff
373
externals/SDL/src/core/linux/SDL_fcitx.c
vendored
Executable file
373
externals/SDL/src/core/linux/SDL_fcitx.c
vendored
Executable file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
|
||||
#include <fcitx/frontend.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "SDL_fcitx.h"
|
||||
#include "SDL_keycode.h"
|
||||
#include "SDL_keyboard.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "SDL_syswm.h"
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
# include "../../video/x11/SDL_x11video.h"
|
||||
#endif
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
|
||||
|
||||
#define FCITX_IM_DBUS_PATH "/inputmethod"
|
||||
#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
|
||||
|
||||
#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
|
||||
#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
|
||||
|
||||
#define IC_NAME_MAX 64
|
||||
#define DBUS_TIMEOUT 500
|
||||
|
||||
typedef struct _FcitxClient
|
||||
{
|
||||
SDL_DBusContext *dbus;
|
||||
|
||||
char servicename[IC_NAME_MAX];
|
||||
char icname[IC_NAME_MAX];
|
||||
|
||||
int id;
|
||||
|
||||
SDL_Rect cursor_rect;
|
||||
} FcitxClient;
|
||||
|
||||
static FcitxClient fcitx_client;
|
||||
|
||||
static int
|
||||
GetDisplayNumber()
|
||||
{
|
||||
const char *display = SDL_getenv("DISPLAY");
|
||||
const char *p = NULL;
|
||||
int number = 0;
|
||||
|
||||
if (display == NULL)
|
||||
return 0;
|
||||
|
||||
display = SDL_strchr(display, ':');
|
||||
if (display == NULL)
|
||||
return 0;
|
||||
|
||||
display++;
|
||||
p = SDL_strchr(display, '.');
|
||||
if (p == NULL && display != NULL) {
|
||||
number = SDL_strtod(display, NULL);
|
||||
} else {
|
||||
char *buffer = SDL_strdup(display);
|
||||
buffer[p - display] = '\0';
|
||||
number = SDL_strtod(buffer, NULL);
|
||||
SDL_free(buffer);
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
static char*
|
||||
GetAppName()
|
||||
{
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__)
|
||||
char *spot;
|
||||
char procfile[1024];
|
||||
char linkfile[1024];
|
||||
int linksize;
|
||||
|
||||
#if defined(__LINUX__)
|
||||
SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid());
|
||||
#elif defined(__FREEBSD__)
|
||||
SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid());
|
||||
#endif
|
||||
linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
spot = SDL_strrchr(linkfile, '/');
|
||||
if (spot) {
|
||||
return SDL_strdup(spot + 1);
|
||||
} else {
|
||||
return SDL_strdup(linkfile);
|
||||
}
|
||||
}
|
||||
#endif /* __LINUX__ || __FREEBSD__ */
|
||||
|
||||
return SDL_strdup("SDL_App");
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||
{
|
||||
SDL_DBusContext *dbus = (SDL_DBusContext *)data;
|
||||
|
||||
if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "CommitString")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text = NULL;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
dbus->message_iter_get_basic(&iter, &text);
|
||||
|
||||
if (text)
|
||||
SDL_SendKeyboardText(text);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
dbus->message_iter_get_basic(&iter, &text);
|
||||
|
||||
if (text && *text) {
|
||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
size_t cursor = 0;
|
||||
|
||||
while (i < text_bytes) {
|
||||
const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
|
||||
const size_t chars = SDL_utf8strlen(buf);
|
||||
|
||||
SDL_SendEditingText(buf, cursor, chars);
|
||||
|
||||
i += sz;
|
||||
cursor += chars;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Fcitx_UpdateTextRect(NULL);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static void
|
||||
FcitxClientICCallMethod(FcitxClient *client, const char *method)
|
||||
{
|
||||
SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
Fcitx_SetCapabilities(void *data,
|
||||
const char *name,
|
||||
const char *old_val,
|
||||
const char *internal_editing)
|
||||
{
|
||||
FcitxClient *client = (FcitxClient *)data;
|
||||
Uint32 caps = CAPACITY_NONE;
|
||||
|
||||
if (!(internal_editing && *internal_editing == '1')) {
|
||||
caps |= CAPACITY_PREEDIT;
|
||||
}
|
||||
|
||||
SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
FcitxClientCreateIC(FcitxClient *client)
|
||||
{
|
||||
char *appname = GetAppName();
|
||||
pid_t pid = getpid();
|
||||
int id = -1;
|
||||
Uint32 enable, arg1, arg2, arg3, arg4;
|
||||
|
||||
if (!SDL_DBus_CallMethod(client->servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateICv3",
|
||||
DBUS_TYPE_STRING, &appname, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_INT32, &id, DBUS_TYPE_BOOLEAN, &enable, DBUS_TYPE_UINT32, &arg1, DBUS_TYPE_UINT32, &arg2, DBUS_TYPE_UINT32, &arg3, DBUS_TYPE_UINT32, &arg4, DBUS_TYPE_INVALID)) {
|
||||
id = -1; /* just in case. */
|
||||
}
|
||||
|
||||
SDL_free(appname);
|
||||
|
||||
if (id >= 0) {
|
||||
SDL_DBusContext *dbus = client->dbus;
|
||||
|
||||
client->id = id;
|
||||
|
||||
SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
|
||||
|
||||
dbus->bus_add_match(dbus->session_conn,
|
||||
"type='signal', interface='org.fcitx.Fcitx.InputContext'",
|
||||
NULL);
|
||||
dbus->connection_add_filter(dbus->session_conn,
|
||||
&DBus_MessageFilter, dbus,
|
||||
NULL);
|
||||
dbus->connection_flush(dbus->session_conn);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, Fcitx_SetCapabilities, client);
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static Uint32
|
||||
Fcitx_ModState(void)
|
||||
{
|
||||
Uint32 fcitx_mods = 0;
|
||||
SDL_Keymod sdl_mods = SDL_GetModState();
|
||||
|
||||
if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
|
||||
if (sdl_mods & KMOD_CAPS) fcitx_mods |= FcitxKeyState_CapsLock;
|
||||
if (sdl_mods & KMOD_CTRL) fcitx_mods |= FcitxKeyState_Ctrl;
|
||||
if (sdl_mods & KMOD_ALT) fcitx_mods |= FcitxKeyState_Alt;
|
||||
if (sdl_mods & KMOD_NUM) fcitx_mods |= FcitxKeyState_NumLock;
|
||||
if (sdl_mods & KMOD_LGUI) fcitx_mods |= FcitxKeyState_Super;
|
||||
if (sdl_mods & KMOD_RGUI) fcitx_mods |= FcitxKeyState_Meta;
|
||||
|
||||
return fcitx_mods;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_Fcitx_Init()
|
||||
{
|
||||
fcitx_client.dbus = SDL_DBus_GetContext();
|
||||
|
||||
fcitx_client.cursor_rect.x = -1;
|
||||
fcitx_client.cursor_rect.y = -1;
|
||||
fcitx_client.cursor_rect.w = 0;
|
||||
fcitx_client.cursor_rect.h = 0;
|
||||
|
||||
SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
|
||||
"%s-%d",
|
||||
FCITX_DBUS_SERVICE, GetDisplayNumber());
|
||||
|
||||
return FcitxClientCreateIC(&fcitx_client);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Fcitx_Quit()
|
||||
{
|
||||
FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Fcitx_SetFocus(SDL_bool focused)
|
||||
{
|
||||
if (focused) {
|
||||
FcitxClientICCallMethod(&fcitx_client, "FocusIn");
|
||||
} else {
|
||||
FcitxClientICCallMethod(&fcitx_client, "FocusOut");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Fcitx_Reset(void)
|
||||
{
|
||||
FcitxClientICCallMethod(&fcitx_client, "Reset");
|
||||
FcitxClientICCallMethod(&fcitx_client, "CloseIC");
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
{
|
||||
Uint32 state = Fcitx_ModState();
|
||||
Uint32 handled = SDL_FALSE;
|
||||
int type = FCITX_PRESS_KEY;
|
||||
Uint32 event_time = 0;
|
||||
|
||||
if (SDL_DBus_CallMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
|
||||
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INT32, &type, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_INT32, &handled, DBUS_TYPE_INVALID)) {
|
||||
if (handled) {
|
||||
SDL_Fcitx_UpdateTextRect(NULL);
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
|
||||
{
|
||||
SDL_Window *focused_win = NULL;
|
||||
SDL_SysWMinfo info;
|
||||
int x = 0, y = 0;
|
||||
SDL_Rect *cursor = &fcitx_client.cursor_rect;
|
||||
|
||||
if (rect) {
|
||||
SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
|
||||
}
|
||||
|
||||
focused_win = SDL_GetKeyboardFocus();
|
||||
if (!focused_win) {
|
||||
return ;
|
||||
}
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
if (!SDL_GetWindowWMInfo(focused_win, &info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GetWindowPosition(focused_win, &x, &y);
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
|
||||
|
||||
Display *x_disp = info.info.x11.display;
|
||||
Window x_win = info.info.x11.window;
|
||||
int x_screen = displaydata->screen;
|
||||
Window unused;
|
||||
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) {
|
||||
/* move to bottom left */
|
||||
int w = 0, h = 0;
|
||||
SDL_GetWindowSize(focused_win, &w, &h);
|
||||
cursor->x = 0;
|
||||
cursor->y = h;
|
||||
}
|
||||
|
||||
x += cursor->x;
|
||||
y += cursor->y;
|
||||
|
||||
SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
|
||||
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &cursor->w, DBUS_TYPE_INT32, &cursor->h, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Fcitx_PumpEvents(void)
|
||||
{
|
||||
SDL_DBusContext *dbus = fcitx_client.dbus;
|
||||
DBusConnection *conn = dbus->session_conn;
|
||||
|
||||
dbus->connection_read_write(conn, 0);
|
||||
|
||||
while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||
/* Do nothing, actual work happens in DBus_MessageFilter */
|
||||
usleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_FCITX_FRONTEND_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
40
externals/SDL/src/core/linux/SDL_fcitx.h
vendored
Executable file
40
externals/SDL/src/core/linux/SDL_fcitx.h
vendored
Executable file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_fcitx_h_
|
||||
#define SDL_fcitx_h_
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_rect.h"
|
||||
|
||||
extern SDL_bool SDL_Fcitx_Init(void);
|
||||
extern void SDL_Fcitx_Quit(void);
|
||||
extern void SDL_Fcitx_SetFocus(SDL_bool focused);
|
||||
extern void SDL_Fcitx_Reset(void);
|
||||
extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
|
||||
extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
|
||||
extern void SDL_Fcitx_PumpEvents(void);
|
||||
|
||||
#endif /* SDL_fcitx_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
584
externals/SDL/src/core/linux/SDL_ibus.c
vendored
Executable file
584
externals/SDL/src/core/linux/SDL_ibus.c
vendored
Executable file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_ibus.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "../../video/SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
#include "../../video/x11/SDL_x11video.h"
|
||||
#endif
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static const char IBUS_SERVICE[] = "org.freedesktop.IBus";
|
||||
static const char IBUS_PATH[] = "/org/freedesktop/IBus";
|
||||
static const char IBUS_INTERFACE[] = "org.freedesktop.IBus";
|
||||
static const char IBUS_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
|
||||
|
||||
static char *input_ctx_path = NULL;
|
||||
static SDL_Rect ibus_cursor_rect = { 0, 0, 0, 0 };
|
||||
static DBusConnection *ibus_conn = NULL;
|
||||
static char *ibus_addr_file = NULL;
|
||||
static int inotify_fd = -1, inotify_wd = -1;
|
||||
|
||||
static Uint32
|
||||
IBus_ModState(void)
|
||||
{
|
||||
Uint32 ibus_mods = 0;
|
||||
SDL_Keymod sdl_mods = SDL_GetModState();
|
||||
|
||||
/* Not sure about MOD3, MOD4 and HYPER mappings */
|
||||
if (sdl_mods & KMOD_LSHIFT) ibus_mods |= IBUS_SHIFT_MASK;
|
||||
if (sdl_mods & KMOD_CAPS) ibus_mods |= IBUS_LOCK_MASK;
|
||||
if (sdl_mods & KMOD_LCTRL) ibus_mods |= IBUS_CONTROL_MASK;
|
||||
if (sdl_mods & KMOD_LALT) ibus_mods |= IBUS_MOD1_MASK;
|
||||
if (sdl_mods & KMOD_NUM) ibus_mods |= IBUS_MOD2_MASK;
|
||||
if (sdl_mods & KMOD_MODE) ibus_mods |= IBUS_MOD5_MASK;
|
||||
if (sdl_mods & KMOD_LGUI) ibus_mods |= IBUS_SUPER_MASK;
|
||||
if (sdl_mods & KMOD_RGUI) ibus_mods |= IBUS_META_MASK;
|
||||
|
||||
return ibus_mods;
|
||||
}
|
||||
|
||||
static const char *
|
||||
IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus)
|
||||
{
|
||||
/* The text we need is nested weirdly, use dbus-monitor to see the structure better */
|
||||
const char *text = NULL;
|
||||
const char *struct_id = NULL;
|
||||
DBusMessageIter sub1, sub2;
|
||||
|
||||
if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_recurse(iter, &sub1);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub1) != DBUS_TYPE_STRUCT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_recurse(&sub1, &sub2);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_get_basic(&sub2, &struct_id);
|
||||
if (!struct_id || SDL_strncmp(struct_id, "IBusText", sizeof("IBusText")) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_next(&sub2);
|
||||
dbus->message_iter_next(&sub2);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_get_basic(&sub2, &text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg, void *user_data)
|
||||
{
|
||||
SDL_DBusContext *dbus = (SDL_DBusContext *)user_data;
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "CommitText")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
|
||||
text = IBus_GetVariantText(conn, &iter, dbus);
|
||||
if (text && *text) {
|
||||
char buf[SDL_TEXTINPUTEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
|
||||
while (i < text_bytes) {
|
||||
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
|
||||
SDL_SendKeyboardText(buf);
|
||||
|
||||
i += sz;
|
||||
}
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "UpdatePreeditText")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
text = IBus_GetVariantText(conn, &iter, dbus);
|
||||
|
||||
if (text) {
|
||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
size_t cursor = 0;
|
||||
|
||||
do {
|
||||
const size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
|
||||
const size_t chars = SDL_utf8strlen(buf);
|
||||
|
||||
SDL_SendEditingText(buf, cursor, chars);
|
||||
|
||||
i += sz;
|
||||
cursor += chars;
|
||||
} while (i < text_bytes);
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "HidePreeditText")) {
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static char *
|
||||
IBus_ReadAddressFromFile(const char *file_path)
|
||||
{
|
||||
char addr_buf[1024];
|
||||
SDL_bool success = SDL_FALSE;
|
||||
FILE *addr_file;
|
||||
|
||||
addr_file = fopen(file_path, "r");
|
||||
if (!addr_file) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (fgets(addr_buf, sizeof(addr_buf), addr_file)) {
|
||||
if (SDL_strncmp(addr_buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
|
||||
size_t sz = SDL_strlen(addr_buf);
|
||||
if (addr_buf[sz-1] == '\n') addr_buf[sz-1] = 0;
|
||||
if (addr_buf[sz-2] == '\r') addr_buf[sz-2] = 0;
|
||||
success = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(addr_file);
|
||||
|
||||
if (success) {
|
||||
return SDL_strdup(addr_buf + (sizeof("IBUS_ADDRESS=") - 1));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
IBus_GetDBusAddressFilename(void)
|
||||
{
|
||||
SDL_DBusContext *dbus;
|
||||
const char *disp_env;
|
||||
char config_dir[PATH_MAX];
|
||||
char *display = NULL;
|
||||
const char *addr;
|
||||
const char *conf_env;
|
||||
char *key;
|
||||
char file_path[PATH_MAX];
|
||||
const char *host;
|
||||
char *disp_num, *screen_num;
|
||||
|
||||
if (ibus_addr_file) {
|
||||
return SDL_strdup(ibus_addr_file);
|
||||
}
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
if (!dbus) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Use this environment variable if it exists. */
|
||||
addr = SDL_getenv("IBUS_ADDRESS");
|
||||
if (addr && *addr) {
|
||||
return SDL_strdup(addr);
|
||||
}
|
||||
|
||||
/* Otherwise, we have to get the hostname, display, machine id, config dir
|
||||
and look up the address from a filepath using all those bits, eek. */
|
||||
disp_env = SDL_getenv("DISPLAY");
|
||||
|
||||
if (!disp_env || !*disp_env) {
|
||||
display = SDL_strdup(":0.0");
|
||||
} else {
|
||||
display = SDL_strdup(disp_env);
|
||||
}
|
||||
|
||||
host = display;
|
||||
disp_num = SDL_strrchr(display, ':');
|
||||
screen_num = SDL_strrchr(display, '.');
|
||||
|
||||
if (!disp_num) {
|
||||
SDL_free(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*disp_num = 0;
|
||||
disp_num++;
|
||||
|
||||
if (screen_num) {
|
||||
*screen_num = 0;
|
||||
}
|
||||
|
||||
if (!*host) {
|
||||
host = "unix";
|
||||
}
|
||||
|
||||
SDL_memset(config_dir, 0, sizeof(config_dir));
|
||||
|
||||
conf_env = SDL_getenv("XDG_CONFIG_HOME");
|
||||
if (conf_env && *conf_env) {
|
||||
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
|
||||
} else {
|
||||
const char *home_env = SDL_getenv("HOME");
|
||||
if (!home_env || !*home_env) {
|
||||
SDL_free(display);
|
||||
return NULL;
|
||||
}
|
||||
SDL_snprintf(config_dir, sizeof(config_dir), "%s/.config", home_env);
|
||||
}
|
||||
|
||||
key = dbus->get_local_machine_id();
|
||||
|
||||
SDL_memset(file_path, 0, sizeof(file_path));
|
||||
SDL_snprintf(file_path, sizeof(file_path), "%s/ibus/bus/%s-%s-%s",
|
||||
config_dir, key, host, disp_num);
|
||||
dbus->free(key);
|
||||
SDL_free(display);
|
||||
|
||||
return SDL_strdup(file_path);
|
||||
}
|
||||
|
||||
static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
|
||||
|
||||
static void SDLCALL
|
||||
IBus_SetCapabilities(void *data, const char *name, const char *old_val,
|
||||
const char *internal_editing)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
Uint32 caps = IBUS_CAP_FOCUS;
|
||||
if (!(internal_editing && *internal_editing == '1')) {
|
||||
caps |= IBUS_CAP_PREEDIT_TEXT;
|
||||
}
|
||||
|
||||
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities",
|
||||
DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SDL_bool
|
||||
IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
|
||||
{
|
||||
const char *client_name = "SDL2_Application";
|
||||
const char *path = NULL;
|
||||
SDL_bool result = SDL_FALSE;
|
||||
DBusObjectPathVTable ibus_vtable;
|
||||
|
||||
SDL_zero(ibus_vtable);
|
||||
ibus_vtable.message_function = &IBus_MessageHandler;
|
||||
|
||||
ibus_conn = dbus->connection_open_private(addr, NULL);
|
||||
|
||||
if (!ibus_conn) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
dbus->connection_flush(ibus_conn);
|
||||
|
||||
if (!dbus->bus_register(ibus_conn, NULL)) {
|
||||
ibus_conn = NULL;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
dbus->connection_flush(ibus_conn);
|
||||
|
||||
if (SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext",
|
||||
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
|
||||
SDL_free(input_ctx_path);
|
||||
input_ctx_path = SDL_strdup(path);
|
||||
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
|
||||
|
||||
dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
|
||||
dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus, NULL);
|
||||
dbus->connection_flush(ibus_conn);
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
IBus_CheckConnection(SDL_DBusContext *dbus)
|
||||
{
|
||||
if (!dbus) return SDL_FALSE;
|
||||
|
||||
if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
if (inotify_fd > 0 && inotify_wd > 0) {
|
||||
char buf[1024];
|
||||
ssize_t readsize = read(inotify_fd, buf, sizeof(buf));
|
||||
if (readsize > 0) {
|
||||
|
||||
char *p;
|
||||
SDL_bool file_updated = SDL_FALSE;
|
||||
|
||||
for (p = buf; p < buf + readsize; /**/) {
|
||||
struct inotify_event *event = (struct inotify_event*) p;
|
||||
if (event->len > 0) {
|
||||
char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/');
|
||||
if (!addr_file_no_path) return SDL_FALSE;
|
||||
|
||||
if (SDL_strcmp(addr_file_no_path + 1, event->name) == 0) {
|
||||
file_updated = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p += sizeof(struct inotify_event) + event->len;
|
||||
}
|
||||
|
||||
if (file_updated) {
|
||||
char *addr = IBus_ReadAddressFromFile(ibus_addr_file);
|
||||
if (addr) {
|
||||
SDL_bool result = IBus_SetupConnection(dbus, addr);
|
||||
SDL_free(addr);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IBus_Init(void)
|
||||
{
|
||||
SDL_bool result = SDL_FALSE;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (dbus) {
|
||||
char *addr_file = IBus_GetDBusAddressFilename();
|
||||
char *addr;
|
||||
char *addr_file_dir;
|
||||
|
||||
if (!addr_file) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* !!! FIXME: if ibus_addr_file != NULL, this will overwrite it and leak (twice!) */
|
||||
ibus_addr_file = SDL_strdup(addr_file);
|
||||
|
||||
addr = IBus_ReadAddressFromFile(addr_file);
|
||||
if (!addr) {
|
||||
SDL_free(addr_file);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (inotify_fd < 0) {
|
||||
inotify_fd = inotify_init();
|
||||
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
addr_file_dir = SDL_strrchr(addr_file, '/');
|
||||
if (addr_file_dir) {
|
||||
*addr_file_dir = 0;
|
||||
}
|
||||
|
||||
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
|
||||
SDL_free(addr_file);
|
||||
|
||||
if (addr) {
|
||||
result = IBus_SetupConnection(dbus, addr);
|
||||
SDL_free(addr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_Quit(void)
|
||||
{
|
||||
SDL_DBusContext *dbus;
|
||||
|
||||
if (input_ctx_path) {
|
||||
SDL_free(input_ctx_path);
|
||||
input_ctx_path = NULL;
|
||||
}
|
||||
|
||||
if (ibus_addr_file) {
|
||||
SDL_free(ibus_addr_file);
|
||||
ibus_addr_file = NULL;
|
||||
}
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (dbus && ibus_conn) {
|
||||
dbus->connection_close(ibus_conn);
|
||||
dbus->connection_unref(ibus_conn);
|
||||
}
|
||||
|
||||
if (inotify_fd > 0 && inotify_wd > 0) {
|
||||
inotify_rm_watch(inotify_fd, inotify_wd);
|
||||
inotify_wd = -1;
|
||||
}
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
|
||||
|
||||
SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
static void
|
||||
IBus_SimpleMessage(const char *method)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_SetFocus(SDL_bool focused)
|
||||
{
|
||||
const char *method = focused ? "FocusIn" : "FocusOut";
|
||||
IBus_SimpleMessage(method);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_Reset(void)
|
||||
{
|
||||
IBus_SimpleMessage("Reset");
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
{
|
||||
Uint32 result = 0;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
Uint32 mods = IBus_ModState();
|
||||
if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
|
||||
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_UpdateTextRect(SDL_Rect *rect)
|
||||
{
|
||||
SDL_Window *focused_win;
|
||||
SDL_SysWMinfo info;
|
||||
int x = 0, y = 0;
|
||||
SDL_DBusContext *dbus;
|
||||
|
||||
if (rect) {
|
||||
SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
focused_win = SDL_GetKeyboardFocus();
|
||||
if (!focused_win) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
if (!SDL_GetWindowWMInfo(focused_win, &info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GetWindowPosition(focused_win, &x, &y);
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
|
||||
|
||||
Display *x_disp = info.info.x11.display;
|
||||
Window x_win = info.info.x11.window;
|
||||
int x_screen = displaydata->screen;
|
||||
Window unused;
|
||||
|
||||
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
|
||||
}
|
||||
#endif
|
||||
|
||||
x += ibus_cursor_rect.x;
|
||||
y += ibus_cursor_rect.y;
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
|
||||
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &ibus_cursor_rect.w, DBUS_TYPE_INT32, &ibus_cursor_rect.h, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_PumpEvents(void)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
dbus->connection_read_write(ibus_conn, 0);
|
||||
|
||||
while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||
/* Do nothing, actual work happens in IBus_MessageHandler */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
58
externals/SDL/src/core/linux/SDL_ibus.h
vendored
Executable file
58
externals/SDL/src/core/linux/SDL_ibus.h
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_ibus_h_
|
||||
#define SDL_ibus_h_
|
||||
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
#define SDL_USE_IBUS 1
|
||||
#include "SDL_stdinc.h"
|
||||
#include <ibus-1.0/ibus.h>
|
||||
|
||||
extern SDL_bool SDL_IBus_Init(void);
|
||||
extern void SDL_IBus_Quit(void);
|
||||
|
||||
/* Lets the IBus server know about changes in window focus */
|
||||
extern void SDL_IBus_SetFocus(SDL_bool focused);
|
||||
|
||||
/* Closes the candidate list and resets any text currently being edited */
|
||||
extern void SDL_IBus_Reset(void);
|
||||
|
||||
/* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
|
||||
update its candidate list or change input methods. PumpEvents should be
|
||||
called some time after this, to recieve the TextInput / TextEditing event back. */
|
||||
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
|
||||
|
||||
/* Update the position of IBus' candidate list. If rect is NULL then this will
|
||||
just reposition it relative to the focused window's new position. */
|
||||
extern void SDL_IBus_UpdateTextRect(SDL_Rect *window_relative_rect);
|
||||
|
||||
/* Checks DBus for new IBus events, and calls SDL_SendKeyboardText /
|
||||
SDL_SendEditingText for each event it finds */
|
||||
extern void SDL_IBus_PumpEvents(void);
|
||||
|
||||
#endif /* HAVE_IBUS_IBUS_H */
|
||||
|
||||
#endif /* SDL_ibus_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
152
externals/SDL/src/core/linux/SDL_ime.c
vendored
Executable file
152
externals/SDL/src/core/linux/SDL_ime.c
vendored
Executable file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_ime.h"
|
||||
#include "SDL_ibus.h"
|
||||
#include "SDL_fcitx.h"
|
||||
|
||||
typedef SDL_bool (*_SDL_IME_Init)();
|
||||
typedef void (*_SDL_IME_Quit)();
|
||||
typedef void (*_SDL_IME_SetFocus)(SDL_bool);
|
||||
typedef void (*_SDL_IME_Reset)();
|
||||
typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
|
||||
typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
|
||||
typedef void (*_SDL_IME_PumpEvents)();
|
||||
|
||||
static _SDL_IME_Init SDL_IME_Init_Real = NULL;
|
||||
static _SDL_IME_Quit SDL_IME_Quit_Real = NULL;
|
||||
static _SDL_IME_SetFocus SDL_IME_SetFocus_Real = NULL;
|
||||
static _SDL_IME_Reset SDL_IME_Reset_Real = NULL;
|
||||
static _SDL_IME_ProcessKeyEvent SDL_IME_ProcessKeyEvent_Real = NULL;
|
||||
static _SDL_IME_UpdateTextRect SDL_IME_UpdateTextRect_Real = NULL;
|
||||
static _SDL_IME_PumpEvents SDL_IME_PumpEvents_Real = NULL;
|
||||
|
||||
static void
|
||||
InitIME()
|
||||
{
|
||||
static SDL_bool inited = SDL_FALSE;
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
const char *im_module = SDL_getenv("SDL_IM_MODULE");
|
||||
const char *xmodifiers = SDL_getenv("XMODIFIERS");
|
||||
#endif
|
||||
|
||||
if (inited == SDL_TRUE)
|
||||
return;
|
||||
|
||||
inited = SDL_TRUE;
|
||||
|
||||
/* See if fcitx IME support is being requested */
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
if (!SDL_IME_Init_Real &&
|
||||
((im_module && SDL_strcmp(im_module, "fcitx") == 0) ||
|
||||
(!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) {
|
||||
SDL_IME_Init_Real = SDL_Fcitx_Init;
|
||||
SDL_IME_Quit_Real = SDL_Fcitx_Quit;
|
||||
SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus;
|
||||
SDL_IME_Reset_Real = SDL_Fcitx_Reset;
|
||||
SDL_IME_ProcessKeyEvent_Real = SDL_Fcitx_ProcessKeyEvent;
|
||||
SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect;
|
||||
SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents;
|
||||
}
|
||||
#endif /* HAVE_FCITX_FRONTEND_H */
|
||||
|
||||
/* default to IBus */
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
if (!SDL_IME_Init_Real) {
|
||||
SDL_IME_Init_Real = SDL_IBus_Init;
|
||||
SDL_IME_Quit_Real = SDL_IBus_Quit;
|
||||
SDL_IME_SetFocus_Real = SDL_IBus_SetFocus;
|
||||
SDL_IME_Reset_Real = SDL_IBus_Reset;
|
||||
SDL_IME_ProcessKeyEvent_Real = SDL_IBus_ProcessKeyEvent;
|
||||
SDL_IME_UpdateTextRect_Real = SDL_IBus_UpdateTextRect;
|
||||
SDL_IME_PumpEvents_Real = SDL_IBus_PumpEvents;
|
||||
}
|
||||
#endif /* HAVE_IBUS_IBUS_H */
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IME_Init(void)
|
||||
{
|
||||
InitIME();
|
||||
|
||||
if (SDL_IME_Init_Real) {
|
||||
if (SDL_IME_Init_Real()) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* uhoh, the IME implementation's init failed! Disable IME support. */
|
||||
SDL_IME_Init_Real = NULL;
|
||||
SDL_IME_Quit_Real = NULL;
|
||||
SDL_IME_SetFocus_Real = NULL;
|
||||
SDL_IME_Reset_Real = NULL;
|
||||
SDL_IME_ProcessKeyEvent_Real = NULL;
|
||||
SDL_IME_UpdateTextRect_Real = NULL;
|
||||
SDL_IME_PumpEvents_Real = NULL;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IME_Quit(void)
|
||||
{
|
||||
if (SDL_IME_Quit_Real)
|
||||
SDL_IME_Quit_Real();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IME_SetFocus(SDL_bool focused)
|
||||
{
|
||||
if (SDL_IME_SetFocus_Real)
|
||||
SDL_IME_SetFocus_Real(focused);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IME_Reset(void)
|
||||
{
|
||||
if (SDL_IME_Reset_Real)
|
||||
SDL_IME_Reset_Real();
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
{
|
||||
if (SDL_IME_ProcessKeyEvent_Real)
|
||||
return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IME_UpdateTextRect(SDL_Rect *rect)
|
||||
{
|
||||
if (SDL_IME_UpdateTextRect_Real)
|
||||
SDL_IME_UpdateTextRect_Real(rect);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IME_PumpEvents()
|
||||
{
|
||||
if (SDL_IME_PumpEvents_Real)
|
||||
SDL_IME_PumpEvents_Real();
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
40
externals/SDL/src/core/linux/SDL_ime.h
vendored
Executable file
40
externals/SDL/src/core/linux/SDL_ime.h
vendored
Executable file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_ime_h_
|
||||
#define SDL_ime_h_
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_rect.h"
|
||||
|
||||
extern SDL_bool SDL_IME_Init(void);
|
||||
extern void SDL_IME_Quit(void);
|
||||
extern void SDL_IME_SetFocus(SDL_bool focused);
|
||||
extern void SDL_IME_Reset(void);
|
||||
extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
|
||||
extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
|
||||
extern void SDL_IME_PumpEvents(void);
|
||||
|
||||
#endif /* SDL_ime_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
116
externals/SDL/src/core/linux/SDL_threadprio.c
vendored
Executable file
116
externals/SDL/src/core/linux/SDL_threadprio.c
vendored
Executable file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef __LINUX__
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#if !SDL_THREADS_DISABLED
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <pthread.h>
|
||||
#include "SDL_system.h"
|
||||
|
||||
#include "SDL_dbus.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* d-bus queries to org.freedesktop.RealtimeKit1. */
|
||||
#define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1"
|
||||
#define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1"
|
||||
#define RTKIT_DBUS_INTERFACE "org.freedesktop.RealtimeKit1"
|
||||
|
||||
static pthread_once_t rtkit_initialize_once = PTHREAD_ONCE_INIT;
|
||||
static Sint32 rtkit_min_nice_level = -20;
|
||||
|
||||
static void
|
||||
rtkit_initialize()
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
/* Try getting minimum nice level: this is often greater than PRIO_MIN (-20). */
|
||||
if (!dbus || !SDL_DBus_QueryPropertyOnConnection(dbus->system_conn, RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MinNiceLevel",
|
||||
DBUS_TYPE_INT32, &rtkit_min_nice_level)) {
|
||||
rtkit_min_nice_level = -20;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
rtkit_setpriority(pid_t thread, int nice_level)
|
||||
{
|
||||
Uint64 ui64 = (Uint64)thread;
|
||||
Sint32 si32 = (Sint32)nice_level;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
pthread_once(&rtkit_initialize_once, rtkit_initialize);
|
||||
|
||||
if (si32 < rtkit_min_nice_level)
|
||||
si32 = rtkit_min_nice_level;
|
||||
|
||||
if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn,
|
||||
RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MakeThreadHighPriority",
|
||||
DBUS_TYPE_UINT64, &ui64, DBUS_TYPE_INT32, &si32, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif /* dbus */
|
||||
#endif /* threads */
|
||||
|
||||
|
||||
/* this is a public symbol, so it has to exist even if threads are disabled. */
|
||||
int
|
||||
SDL_LinuxSetThreadPriority(Sint64 threadID, int priority)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return SDL_Unsupported();
|
||||
#else
|
||||
if (setpriority(PRIO_PROCESS, (id_t)threadID, priority) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* Note that this fails you most likely:
|
||||
* Have your process's scheduler incorrectly configured.
|
||||
See the requirements at:
|
||||
http://git.0pointer.net/rtkit.git/tree/README#n16
|
||||
* Encountered dbus/polkit security restrictions. Note
|
||||
that the RealtimeKit1 dbus endpoint is inaccessible
|
||||
over ssh connections for most common distro configs.
|
||||
You might want to check your local config for details:
|
||||
/usr/share/polkit-1/actions/org.freedesktop.RealtimeKit1.policy
|
||||
|
||||
README and sample code at: http://git.0pointer.net/rtkit.git
|
||||
*/
|
||||
if (rtkit_setpriority((pid_t)threadID, priority)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_SetError("setpriority() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __LINUX__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
576
externals/SDL/src/core/linux/SDL_udev.c
vendored
Executable file
576
externals/SDL/src/core/linux/SDL_udev.c
vendored
Executable file
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To list the properties of a device, try something like:
|
||||
* udevadm info -a -n snd/hwC0D0 (for a sound card)
|
||||
* udevadm info --query=all -n input/event3 (for a keyboard, mouse, etc)
|
||||
* udevadm info --query=property -n input/event2
|
||||
*/
|
||||
#include "SDL_udev.h"
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "../unix/SDL_poll.h"
|
||||
|
||||
static const char *SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
|
||||
|
||||
#define _THIS SDL_UDEV_PrivateData *_this
|
||||
static _THIS = NULL;
|
||||
|
||||
static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr);
|
||||
static int SDL_UDEV_load_syms(void);
|
||||
static SDL_bool SDL_UDEV_hotplug_update_available(void);
|
||||
static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev);
|
||||
|
||||
static SDL_bool
|
||||
SDL_UDEV_load_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(_this->udev_handle, fn);
|
||||
if (*addr == NULL) {
|
||||
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_UDEV_load_syms(void)
|
||||
{
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
#define SDL_UDEV_SYM(x) \
|
||||
if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->syms.x)) return -1
|
||||
|
||||
SDL_UDEV_SYM(udev_device_get_action);
|
||||
SDL_UDEV_SYM(udev_device_get_devnode);
|
||||
SDL_UDEV_SYM(udev_device_get_subsystem);
|
||||
SDL_UDEV_SYM(udev_device_get_parent_with_subsystem_devtype);
|
||||
SDL_UDEV_SYM(udev_device_get_property_value);
|
||||
SDL_UDEV_SYM(udev_device_get_sysattr_value);
|
||||
SDL_UDEV_SYM(udev_device_new_from_syspath);
|
||||
SDL_UDEV_SYM(udev_device_unref);
|
||||
SDL_UDEV_SYM(udev_enumerate_add_match_property);
|
||||
SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
|
||||
SDL_UDEV_SYM(udev_enumerate_get_list_entry);
|
||||
SDL_UDEV_SYM(udev_enumerate_new);
|
||||
SDL_UDEV_SYM(udev_enumerate_scan_devices);
|
||||
SDL_UDEV_SYM(udev_enumerate_unref);
|
||||
SDL_UDEV_SYM(udev_list_entry_get_name);
|
||||
SDL_UDEV_SYM(udev_list_entry_get_next);
|
||||
SDL_UDEV_SYM(udev_monitor_enable_receiving);
|
||||
SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
|
||||
SDL_UDEV_SYM(udev_monitor_get_fd);
|
||||
SDL_UDEV_SYM(udev_monitor_new_from_netlink);
|
||||
SDL_UDEV_SYM(udev_monitor_receive_device);
|
||||
SDL_UDEV_SYM(udev_monitor_unref);
|
||||
SDL_UDEV_SYM(udev_new);
|
||||
SDL_UDEV_SYM(udev_unref);
|
||||
SDL_UDEV_SYM(udev_device_new_from_devnum);
|
||||
SDL_UDEV_SYM(udev_device_get_devnum);
|
||||
#undef SDL_UDEV_SYM
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
SDL_UDEV_hotplug_update_available(void)
|
||||
{
|
||||
if (_this->udev_mon != NULL) {
|
||||
const int fd = _this->syms.udev_monitor_get_fd(_this->udev_mon);
|
||||
if (SDL_IOReady(fd, SDL_FALSE, 0)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_UDEV_Init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (_this == NULL) {
|
||||
_this = (SDL_UDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
|
||||
if(_this == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
retval = SDL_UDEV_LoadLibrary();
|
||||
if (retval < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Set up udev monitoring
|
||||
* Listen for input devices (mouse, keyboard, joystick, etc) and sound devices
|
||||
*/
|
||||
|
||||
_this->udev = _this->syms.udev_new();
|
||||
if (_this->udev == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("udev_new() failed");
|
||||
}
|
||||
|
||||
_this->udev_mon = _this->syms.udev_monitor_new_from_netlink(_this->udev, "udev");
|
||||
if (_this->udev_mon == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("udev_monitor_new_from_netlink() failed");
|
||||
}
|
||||
|
||||
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
|
||||
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
|
||||
_this->syms.udev_monitor_enable_receiving(_this->udev_mon);
|
||||
|
||||
/* Do an initial scan of existing devices */
|
||||
SDL_UDEV_Scan();
|
||||
|
||||
}
|
||||
|
||||
_this->ref_count += 1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_Quit(void)
|
||||
{
|
||||
SDL_UDEV_CallbackList *item;
|
||||
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_this->ref_count -= 1;
|
||||
|
||||
if (_this->ref_count < 1) {
|
||||
|
||||
if (_this->udev_mon != NULL) {
|
||||
_this->syms.udev_monitor_unref(_this->udev_mon);
|
||||
_this->udev_mon = NULL;
|
||||
}
|
||||
if (_this->udev != NULL) {
|
||||
_this->syms.udev_unref(_this->udev);
|
||||
_this->udev = NULL;
|
||||
}
|
||||
|
||||
/* Remove existing devices */
|
||||
while (_this->first != NULL) {
|
||||
item = _this->first;
|
||||
_this->first = _this->first->next;
|
||||
SDL_free(item);
|
||||
}
|
||||
|
||||
SDL_UDEV_UnloadLibrary();
|
||||
SDL_free(_this);
|
||||
_this = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_Scan(void)
|
||||
{
|
||||
struct udev_enumerate *enumerate = NULL;
|
||||
struct udev_list_entry *devs = NULL;
|
||||
struct udev_list_entry *item = NULL;
|
||||
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
enumerate = _this->syms.udev_enumerate_new(_this->udev);
|
||||
if (enumerate == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
SDL_SetError("udev_enumerate_new() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "sound");
|
||||
|
||||
_this->syms.udev_enumerate_scan_devices(enumerate);
|
||||
devs = _this->syms.udev_enumerate_get_list_entry(enumerate);
|
||||
for (item = devs; item; item = _this->syms.udev_list_entry_get_next(item)) {
|
||||
const char *path = _this->syms.udev_list_entry_get_name(item);
|
||||
struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path);
|
||||
if (dev != NULL) {
|
||||
device_event(SDL_UDEV_DEVICEADDED, dev);
|
||||
_this->syms.udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
_this->syms.udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SDL_UDEV_UnloadLibrary(void)
|
||||
{
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this->udev_handle != NULL) {
|
||||
SDL_UnloadObject(_this->udev_handle);
|
||||
_this->udev_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_UDEV_LoadLibrary(void)
|
||||
{
|
||||
int retval = 0, i;
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_SetError("UDEV not initialized");
|
||||
}
|
||||
|
||||
/* See if there is a udev library already loaded */
|
||||
if (SDL_UDEV_load_syms() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_UDEV_DYNAMIC
|
||||
/* Check for the build environment's libudev first */
|
||||
if (_this->udev_handle == NULL) {
|
||||
_this->udev_handle = SDL_LoadObject(SDL_UDEV_DYNAMIC);
|
||||
if (_this->udev_handle != NULL) {
|
||||
retval = SDL_UDEV_load_syms();
|
||||
if (retval < 0) {
|
||||
SDL_UDEV_UnloadLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_this->udev_handle == NULL) {
|
||||
for( i = 0 ; i < SDL_arraysize(SDL_UDEV_LIBS); i++) {
|
||||
_this->udev_handle = SDL_LoadObject(SDL_UDEV_LIBS[i]);
|
||||
if (_this->udev_handle != NULL) {
|
||||
retval = SDL_UDEV_load_syms();
|
||||
if (retval < 0) {
|
||||
SDL_UDEV_UnloadLibrary();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->udev_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
|
||||
#define OFF(x) ((x)%BITS_PER_LONG)
|
||||
#define LONG(x) ((x)/BITS_PER_LONG)
|
||||
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
|
||||
|
||||
static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len)
|
||||
{
|
||||
const char *value;
|
||||
char text[4096];
|
||||
char *word;
|
||||
int i;
|
||||
unsigned long v;
|
||||
|
||||
SDL_memset(bitmask, 0, bitmask_len*sizeof(*bitmask));
|
||||
value = _this->syms.udev_device_get_sysattr_value(pdev, attr);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_strlcpy(text, value, sizeof(text));
|
||||
i = 0;
|
||||
while ((word = SDL_strrchr(text, ' ')) != NULL) {
|
||||
v = SDL_strtoul(word+1, NULL, 16);
|
||||
if (i < bitmask_len) {
|
||||
bitmask[i] = v;
|
||||
}
|
||||
++i;
|
||||
*word = '\0';
|
||||
}
|
||||
v = SDL_strtoul(text, NULL, 16);
|
||||
if (i < bitmask_len) {
|
||||
bitmask[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
guess_device_class(struct udev_device *dev)
|
||||
{
|
||||
int devclass = 0;
|
||||
struct udev_device *pdev;
|
||||
unsigned long bitmask_ev[NBITS(EV_MAX)];
|
||||
unsigned long bitmask_abs[NBITS(ABS_MAX)];
|
||||
unsigned long bitmask_key[NBITS(KEY_MAX)];
|
||||
unsigned long bitmask_rel[NBITS(REL_MAX)];
|
||||
unsigned long keyboard_mask;
|
||||
|
||||
/* walk up the parental chain until we find the real input device; the
|
||||
* argument is very likely a subdevice of this, like eventN */
|
||||
pdev = dev;
|
||||
while (pdev && !_this->syms.udev_device_get_sysattr_value(pdev, "capabilities/ev")) {
|
||||
pdev = _this->syms.udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL);
|
||||
}
|
||||
if (!pdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_caps(dev, pdev, "capabilities/ev", bitmask_ev, SDL_arraysize(bitmask_ev));
|
||||
get_caps(dev, pdev, "capabilities/abs", bitmask_abs, SDL_arraysize(bitmask_abs));
|
||||
get_caps(dev, pdev, "capabilities/rel", bitmask_rel, SDL_arraysize(bitmask_rel));
|
||||
get_caps(dev, pdev, "capabilities/key", bitmask_key, SDL_arraysize(bitmask_key));
|
||||
|
||||
if (test_bit(EV_ABS, bitmask_ev) &&
|
||||
test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) {
|
||||
if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) {
|
||||
; /* ID_INPUT_TABLET */
|
||||
} else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) {
|
||||
; /* ID_INPUT_TOUCHPAD */
|
||||
} else if (test_bit(BTN_MOUSE, bitmask_key)) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
|
||||
} else if (test_bit(BTN_TOUCH, bitmask_key)) {
|
||||
/* TODO: better determining between touchscreen and multitouch touchpad,
|
||||
see https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-input_id.c */
|
||||
devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; /* ID_INPUT_TOUCHSCREEN */
|
||||
}
|
||||
|
||||
if (test_bit(BTN_TRIGGER, bitmask_key) ||
|
||||
test_bit(BTN_A, bitmask_key) ||
|
||||
test_bit(BTN_1, bitmask_key) ||
|
||||
test_bit(ABS_RX, bitmask_abs) ||
|
||||
test_bit(ABS_RY, bitmask_abs) ||
|
||||
test_bit(ABS_RZ, bitmask_abs) ||
|
||||
test_bit(ABS_THROTTLE, bitmask_abs) ||
|
||||
test_bit(ABS_RUDDER, bitmask_abs) ||
|
||||
test_bit(ABS_WHEEL, bitmask_abs) ||
|
||||
test_bit(ABS_GAS, bitmask_abs) ||
|
||||
test_bit(ABS_BRAKE, bitmask_abs)) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(EV_REL, bitmask_ev) &&
|
||||
test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) &&
|
||||
test_bit(BTN_MOUSE, bitmask_key)) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
|
||||
}
|
||||
|
||||
/* the first 32 bits are ESC, numbers, and Q to D; if we have any of
|
||||
* those, consider it a keyboard device; do not test KEY_RESERVED, though */
|
||||
keyboard_mask = 0xFFFFFFFE;
|
||||
if ((bitmask_key[0] & keyboard_mask) != 0)
|
||||
devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */
|
||||
|
||||
return devclass;
|
||||
}
|
||||
|
||||
static void
|
||||
device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
{
|
||||
const char *subsystem;
|
||||
const char *val = NULL;
|
||||
int devclass = 0;
|
||||
const char *path;
|
||||
SDL_UDEV_CallbackList *item;
|
||||
|
||||
path = _this->syms.udev_device_get_devnode(dev);
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
subsystem = _this->syms.udev_device_get_subsystem(dev);
|
||||
if (SDL_strcmp(subsystem, "sound") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_SOUND;
|
||||
} else if (SDL_strcmp(subsystem, "input") == 0) {
|
||||
/* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER");
|
||||
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) &&
|
||||
val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE;
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
|
||||
}
|
||||
|
||||
/* The undocumented rule is:
|
||||
- All devices with keys get ID_INPUT_KEY
|
||||
- From this subset, if they have ESC, numbers, and Q to D, it also gets ID_INPUT_KEYBOARD
|
||||
|
||||
Ref: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c#n183
|
||||
*/
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEY");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_KEYBOARD;
|
||||
}
|
||||
|
||||
if (devclass == 0) {
|
||||
/* Fall back to old style input classes */
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_CLASS");
|
||||
if (val != NULL) {
|
||||
if (SDL_strcmp(val, "joystick") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_JOYSTICK;
|
||||
} else if (SDL_strcmp(val, "mouse") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_MOUSE;
|
||||
} else if (SDL_strcmp(val, "kbd") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_KEYBOARD;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* We could be linked with libudev on a system that doesn't have udev running */
|
||||
devclass = guess_device_class(dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process callbacks */
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
item->callback(type, devclass, path);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_Poll(void)
|
||||
{
|
||||
struct udev_device *dev = NULL;
|
||||
const char *action = NULL;
|
||||
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (SDL_UDEV_hotplug_update_available()) {
|
||||
dev = _this->syms.udev_monitor_receive_device(_this->udev_mon);
|
||||
if (dev == NULL) {
|
||||
break;
|
||||
}
|
||||
action = _this->syms.udev_device_get_action(dev);
|
||||
|
||||
if (SDL_strcmp(action, "add") == 0) {
|
||||
/* Wait for the device to finish initialization */
|
||||
SDL_Delay(100);
|
||||
|
||||
device_event(SDL_UDEV_DEVICEADDED, dev);
|
||||
} else if (SDL_strcmp(action, "remove") == 0) {
|
||||
device_event(SDL_UDEV_DEVICEREMOVED, dev);
|
||||
}
|
||||
|
||||
_this->syms.udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
||||
{
|
||||
SDL_UDEV_CallbackList *item;
|
||||
item = (SDL_UDEV_CallbackList *) SDL_calloc(1, sizeof (SDL_UDEV_CallbackList));
|
||||
if (item == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->callback = cb;
|
||||
|
||||
if (_this->last == NULL) {
|
||||
_this->first = _this->last = item;
|
||||
} else {
|
||||
_this->last->next = item;
|
||||
_this->last = item;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
||||
{
|
||||
SDL_UDEV_CallbackList *item;
|
||||
SDL_UDEV_CallbackList *prev = NULL;
|
||||
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
/* found it, remove it. */
|
||||
if (item->callback == cb) {
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(_this->first == item);
|
||||
_this->first = item->next;
|
||||
}
|
||||
if (item == _this->last) {
|
||||
_this->last = prev;
|
||||
}
|
||||
SDL_free(item);
|
||||
return;
|
||||
}
|
||||
prev = item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const SDL_UDEV_Symbols *
|
||||
SDL_UDEV_GetUdevSyms(void)
|
||||
{
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
SDL_SetError("Could not initialize UDEV");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &_this->syms;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_ReleaseUdevSyms(void)
|
||||
{
|
||||
SDL_UDEV_Quit();
|
||||
}
|
||||
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
125
externals/SDL/src/core/linux/SDL_udev.h
vendored
Executable file
125
externals/SDL/src/core/linux/SDL_udev.h
vendored
Executable file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_udev_h_
|
||||
#define SDL_udev_h_
|
||||
|
||||
#if HAVE_LIBUDEV_H
|
||||
|
||||
#ifndef SDL_USE_LIBUDEV
|
||||
#define SDL_USE_LIBUDEV 1
|
||||
#endif
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_events.h"
|
||||
#include <libudev.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* \brief Device type
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_UDEV_DEVICEADDED = 1,
|
||||
SDL_UDEV_DEVICEREMOVED
|
||||
} SDL_UDEV_deviceevent;
|
||||
|
||||
/* A device can be any combination of these classes */
|
||||
typedef enum
|
||||
{
|
||||
SDL_UDEV_DEVICE_UNKNOWN = 0x0000,
|
||||
SDL_UDEV_DEVICE_MOUSE = 0x0001,
|
||||
SDL_UDEV_DEVICE_KEYBOARD = 0x0002,
|
||||
SDL_UDEV_DEVICE_JOYSTICK = 0x0004,
|
||||
SDL_UDEV_DEVICE_SOUND = 0x0008,
|
||||
SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0010
|
||||
} SDL_UDEV_deviceclass;
|
||||
|
||||
typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
|
||||
|
||||
typedef struct SDL_UDEV_CallbackList {
|
||||
SDL_UDEV_Callback callback;
|
||||
struct SDL_UDEV_CallbackList *next;
|
||||
} SDL_UDEV_CallbackList;
|
||||
|
||||
typedef struct SDL_UDEV_Symbols {
|
||||
const char *(*udev_device_get_action)(struct udev_device *);
|
||||
const char *(*udev_device_get_devnode)(struct udev_device *);
|
||||
const char *(*udev_device_get_subsystem)(struct udev_device *);
|
||||
struct udev_device *(*udev_device_get_parent_with_subsystem_devtype)(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||
const char *(*udev_device_get_property_value)(struct udev_device *, const char *);
|
||||
const char *(*udev_device_get_sysattr_value)(struct udev_device *udev_device, const char *sysattr);
|
||||
struct udev_device *(*udev_device_new_from_syspath)(struct udev *, const char *);
|
||||
void (*udev_device_unref)(struct udev_device *);
|
||||
int (*udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *);
|
||||
int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *);
|
||||
struct udev_list_entry *(*udev_enumerate_get_list_entry)(struct udev_enumerate *);
|
||||
struct udev_enumerate *(*udev_enumerate_new)(struct udev *);
|
||||
int (*udev_enumerate_scan_devices)(struct udev_enumerate *);
|
||||
void (*udev_enumerate_unref)(struct udev_enumerate *);
|
||||
const char *(*udev_list_entry_get_name)(struct udev_list_entry *);
|
||||
struct udev_list_entry *(*udev_list_entry_get_next)(struct udev_list_entry *);
|
||||
int (*udev_monitor_enable_receiving)(struct udev_monitor *);
|
||||
int (*udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor *, const char *, const char *);
|
||||
int (*udev_monitor_get_fd)(struct udev_monitor *);
|
||||
struct udev_monitor *(*udev_monitor_new_from_netlink)(struct udev *, const char *);
|
||||
struct udev_device *(*udev_monitor_receive_device)(struct udev_monitor *);
|
||||
void (*udev_monitor_unref)(struct udev_monitor *);
|
||||
struct udev *(*udev_new)(void);
|
||||
void (*udev_unref)(struct udev *);
|
||||
struct udev_device * (*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum);
|
||||
dev_t (*udev_device_get_devnum) (struct udev_device *udev_device);
|
||||
} SDL_UDEV_Symbols;
|
||||
|
||||
typedef struct SDL_UDEV_PrivateData
|
||||
{
|
||||
const char *udev_library;
|
||||
void *udev_handle;
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_mon;
|
||||
int ref_count;
|
||||
SDL_UDEV_CallbackList *first, *last;
|
||||
|
||||
/* Function pointers */
|
||||
SDL_UDEV_Symbols syms;
|
||||
} SDL_UDEV_PrivateData;
|
||||
|
||||
extern int SDL_UDEV_Init(void);
|
||||
extern void SDL_UDEV_Quit(void);
|
||||
extern void SDL_UDEV_UnloadLibrary(void);
|
||||
extern int SDL_UDEV_LoadLibrary(void);
|
||||
extern void SDL_UDEV_Poll(void);
|
||||
extern void SDL_UDEV_Scan(void);
|
||||
extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
|
||||
extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
|
||||
extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void);
|
||||
extern void SDL_UDEV_ReleaseUdevSyms(void);
|
||||
|
||||
|
||||
#endif /* HAVE_LIBUDEV_H */
|
||||
|
||||
#endif /* SDL_udev_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
87
externals/SDL/src/core/unix/SDL_poll.c
vendored
Executable file
87
externals/SDL/src/core/unix/SDL_poll.c
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_poll.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
#include <poll.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
int
|
||||
SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Note: We don't bother to account for elapsed time if we get EINTR */
|
||||
do
|
||||
{
|
||||
#ifdef HAVE_POLL
|
||||
struct pollfd info;
|
||||
|
||||
info.fd = fd;
|
||||
if (forWrite) {
|
||||
info.events = POLLOUT;
|
||||
} else {
|
||||
info.events = POLLIN | POLLPRI;
|
||||
}
|
||||
result = poll(&info, 1, timeoutMS);
|
||||
#else
|
||||
fd_set rfdset, *rfdp = NULL;
|
||||
fd_set wfdset, *wfdp = NULL;
|
||||
struct timeval tv, *tvp = NULL;
|
||||
|
||||
/* If this assert triggers we'll corrupt memory here */
|
||||
SDL_assert(fd >= 0 && fd < FD_SETSIZE);
|
||||
|
||||
if (forWrite) {
|
||||
FD_ZERO(&wfdset);
|
||||
FD_SET(fd, &wfdset);
|
||||
wfdp = &wfdset;
|
||||
} else {
|
||||
FD_ZERO(&rfdset);
|
||||
FD_SET(fd, &rfdset);
|
||||
rfdp = &rfdset;
|
||||
}
|
||||
|
||||
if (timeoutMS >= 0) {
|
||||
tv.tv_sec = timeoutMS / 1000;
|
||||
tv.tv_usec = (timeoutMS % 1000) * 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
result = select(fd + 1, rfdp, wfdp, NULL, tvp);
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
} while ( result < 0 && errno == EINTR );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
34
externals/SDL/src/core/unix/SDL_poll.h
vendored
Executable file
34
externals/SDL/src/core/unix/SDL_poll.h
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_poll_h_
|
||||
#define SDL_poll_h_
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
|
||||
extern int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS);
|
||||
|
||||
#endif /* SDL_poll_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
111
externals/SDL/src/core/windows/SDL_directx.h
vendored
Executable file
111
externals/SDL/src/core/windows/SDL_directx.h
vendored
Executable file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_directx_h_
|
||||
#define SDL_directx_h_
|
||||
|
||||
/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
|
||||
|
||||
#include "SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
#endif
|
||||
#undef WINNT
|
||||
|
||||
/* Far pointers don't exist in 32-bit code */
|
||||
#ifndef FAR
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
/* Error codes not yet included in Win32 API header files */
|
||||
#ifndef MAKE_HRESULT
|
||||
#define MAKE_HRESULT(sev,fac,code) \
|
||||
((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))))
|
||||
#endif
|
||||
|
||||
#ifndef S_OK
|
||||
#define S_OK (HRESULT)0x00000000L
|
||||
#endif
|
||||
|
||||
#ifndef SUCCEEDED
|
||||
#define SUCCEEDED(x) ((HRESULT)(x) >= 0)
|
||||
#endif
|
||||
#ifndef FAILED
|
||||
#define FAILED(x) ((HRESULT)(x)<0)
|
||||
#endif
|
||||
|
||||
#ifndef E_FAIL
|
||||
#define E_FAIL (HRESULT)0x80000008L
|
||||
#endif
|
||||
#ifndef E_NOINTERFACE
|
||||
#define E_NOINTERFACE (HRESULT)0x80004002L
|
||||
#endif
|
||||
#ifndef E_OUTOFMEMORY
|
||||
#define E_OUTOFMEMORY (HRESULT)0x8007000EL
|
||||
#endif
|
||||
#ifndef E_INVALIDARG
|
||||
#define E_INVALIDARG (HRESULT)0x80070057L
|
||||
#endif
|
||||
#ifndef E_NOTIMPL
|
||||
#define E_NOTIMPL (HRESULT)0x80004001L
|
||||
#endif
|
||||
#ifndef REGDB_E_CLASSNOTREG
|
||||
#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L
|
||||
#endif
|
||||
|
||||
/* Severity codes */
|
||||
#ifndef SEVERITY_ERROR
|
||||
#define SEVERITY_ERROR 1
|
||||
#endif
|
||||
|
||||
/* Error facility codes */
|
||||
#ifndef FACILITY_WIN32
|
||||
#define FACILITY_WIN32 7
|
||||
#endif
|
||||
|
||||
#ifndef FIELD_OFFSET
|
||||
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
|
||||
#endif
|
||||
|
||||
/* DirectX headers (if it isn't included, I haven't tested it yet)
|
||||
*/
|
||||
/* We need these defines to mark what version of DirectX API we use */
|
||||
#define DIRECTDRAW_VERSION 0x0700
|
||||
#define DIRECTSOUND_VERSION 0x0800
|
||||
#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
|
||||
|
||||
#ifdef HAVE_DDRAW_H
|
||||
#include <ddraw.h>
|
||||
#endif
|
||||
#ifdef HAVE_DSOUND_H
|
||||
#include <dsound.h>
|
||||
#endif
|
||||
#ifdef HAVE_DINPUT_H
|
||||
#include <dinput.h>
|
||||
#else
|
||||
typedef struct { int unused; } DIDEVICEINSTANCE;
|
||||
#endif
|
||||
|
||||
#endif /* SDL_directx_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
233
externals/SDL/src/core/windows/SDL_windows.c
vendored
Executable file
233
externals/SDL/src/core/windows/SDL_windows.c
vendored
Executable file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
|
||||
#include "SDL_windows.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
|
||||
|
||||
#ifndef _WIN32_WINNT_VISTA
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WIN7
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#endif
|
||||
|
||||
|
||||
/* Sets an error message based on an HRESULT */
|
||||
int
|
||||
WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
|
||||
{
|
||||
TCHAR buffer[1024];
|
||||
char *message;
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,
|
||||
buffer, SDL_arraysize(buffer), NULL);
|
||||
message = WIN_StringToUTF8(buffer);
|
||||
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
|
||||
SDL_free(message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
int
|
||||
WIN_SetError(const char *prefix)
|
||||
{
|
||||
return WIN_SetErrorFromHRESULT(prefix, GetLastError());
|
||||
}
|
||||
|
||||
HRESULT
|
||||
WIN_CoInitialize(void)
|
||||
{
|
||||
/* SDL handles any threading model, so initialize with the default, which
|
||||
is compatible with OLE and if that doesn't work, try multi-threaded mode.
|
||||
|
||||
If you need multi-threaded mode, call CoInitializeEx() before SDL_Init()
|
||||
*/
|
||||
#ifdef __WINRT__
|
||||
/* DLudwig: On WinRT, it is assumed that COM was initialized in main().
|
||||
CoInitializeEx is available (not CoInitialize though), however
|
||||
on WinRT, main() is typically declared with the [MTAThread]
|
||||
attribute, which, AFAIK, should initialize COM.
|
||||
*/
|
||||
return S_OK;
|
||||
#else
|
||||
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
if (hr == RPC_E_CHANGED_MODE) {
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
}
|
||||
|
||||
/* S_FALSE means success, but someone else already initialized. */
|
||||
/* You still need to call CoUninitialize in this case! */
|
||||
if (hr == S_FALSE) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WIN_CoUninitialize(void)
|
||||
{
|
||||
#ifndef __WINRT__
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __WINRT__
|
||||
static BOOL
|
||||
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi;
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
|
||||
|
||||
SDL_zero(osvi);
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL WIN_IsWindowsVistaOrGreater(void)
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
return TRUE;
|
||||
#else
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL WIN_IsWindows7OrGreater(void)
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
return TRUE;
|
||||
#else
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
WAVExxxCAPS gives you 31 bytes for the device name, and just truncates if it's
|
||||
longer. However, since WinXP, you can use the WAVExxxCAPS2 structure, which
|
||||
will give you a name GUID. The full name is in the Windows Registry under
|
||||
that GUID, located here: HKLM\System\CurrentControlSet\Control\MediaCategories
|
||||
|
||||
Note that drivers can report GUID_NULL for the name GUID, in which case,
|
||||
Windows makes a best effort to fill in those 31 bytes in the usual place.
|
||||
This info summarized from MSDN:
|
||||
|
||||
http://web.archive.org/web/20131027093034/http://msdn.microsoft.com/en-us/library/windows/hardware/ff536382(v=vs.85).aspx
|
||||
|
||||
Always look this up in the registry if possible, because the strings are
|
||||
different! At least on Win10, I see "Yeti Stereo Microphone" in the
|
||||
Registry, and a unhelpful "Microphone(Yeti Stereo Microph" in winmm. Sigh.
|
||||
|
||||
(Also, DirectSound shouldn't be limited to 32 chars, but its device enum
|
||||
has the same problem.)
|
||||
|
||||
WASAPI doesn't need this. This is just for DirectSound/WinMM.
|
||||
*/
|
||||
char *
|
||||
WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
|
||||
{
|
||||
#if __WINRT__
|
||||
return WIN_StringToUTF8(name); /* No registry access on WinRT/UWP, go with what we've got. */
|
||||
#else
|
||||
static const GUID nullguid = { 0 };
|
||||
const unsigned char *ptr;
|
||||
char keystr[128];
|
||||
WCHAR *strw = NULL;
|
||||
SDL_bool rc;
|
||||
HKEY hkey;
|
||||
DWORD len = 0;
|
||||
char *retval = NULL;
|
||||
|
||||
if (WIN_IsEqualGUID(guid, &nullguid)) {
|
||||
return WIN_StringToUTF8(name); /* No GUID, go with what we've got. */
|
||||
}
|
||||
|
||||
ptr = (const unsigned char *) guid;
|
||||
SDL_snprintf(keystr, sizeof (keystr),
|
||||
"System\\CurrentControlSet\\Control\\MediaCategories\\{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
ptr[3], ptr[2], ptr[1], ptr[0], ptr[5], ptr[4], ptr[7], ptr[6],
|
||||
ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
|
||||
|
||||
strw = WIN_UTF8ToString(keystr);
|
||||
rc = (RegOpenKeyExW(HKEY_LOCAL_MACHINE, strw, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS);
|
||||
SDL_free(strw);
|
||||
if (!rc) {
|
||||
return WIN_StringToUTF8(name); /* oh well. */
|
||||
}
|
||||
|
||||
rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, NULL, &len) == ERROR_SUCCESS);
|
||||
if (!rc) {
|
||||
RegCloseKey(hkey);
|
||||
return WIN_StringToUTF8(name); /* oh well. */
|
||||
}
|
||||
|
||||
strw = (WCHAR *) SDL_malloc(len + sizeof (WCHAR));
|
||||
if (!strw) {
|
||||
RegCloseKey(hkey);
|
||||
return WIN_StringToUTF8(name); /* oh well. */
|
||||
}
|
||||
|
||||
rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, (LPBYTE) strw, &len) == ERROR_SUCCESS);
|
||||
RegCloseKey(hkey);
|
||||
if (!rc) {
|
||||
SDL_free(strw);
|
||||
return WIN_StringToUTF8(name); /* oh well. */
|
||||
}
|
||||
|
||||
strw[len / 2] = 0; /* make sure it's null-terminated. */
|
||||
|
||||
retval = WIN_StringToUTF8(strw);
|
||||
SDL_free(strw);
|
||||
return retval ? retval : WIN_StringToUTF8(name);
|
||||
#endif /* if __WINRT__ / else */
|
||||
}
|
||||
|
||||
BOOL
|
||||
WIN_IsEqualGUID(const GUID * a, const GUID * b)
|
||||
{
|
||||
return (SDL_memcmp(a, b, sizeof (*a)) == 0);
|
||||
}
|
||||
|
||||
BOOL
|
||||
WIN_IsEqualIID(REFIID a, REFIID b)
|
||||
{
|
||||
return (SDL_memcmp(a, b, sizeof (*a)) == 0);
|
||||
}
|
||||
|
||||
#endif /* __WIN32__ || __WINRT__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
75
externals/SDL/src/core/windows/SDL_windows.h
vendored
Executable file
75
externals/SDL/src/core/windows/SDL_windows.h
vendored
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is an include file for windows.h with the SDL build settings */
|
||||
|
||||
#ifndef _INCLUDED_WINDOWS_H
|
||||
#define _INCLUDED_WINDOWS_H
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define STRICT
|
||||
#ifndef UNICODE
|
||||
#define UNICODE 1
|
||||
#endif
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <basetyps.h> /* for REFIID with broken mingw.org headers */
|
||||
|
||||
/* Routines to convert from UTF8 to native Windows text */
|
||||
#if UNICODE
|
||||
#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UTF-16LE", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR))
|
||||
#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UTF-16LE", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#else
|
||||
/* !!! FIXME: UTF8ToString() can just be a SDL_strdup() here. */
|
||||
#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)(S), (SDL_strlen(S)+1))
|
||||
#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#endif
|
||||
|
||||
/* Sets an error message based on a given HRESULT */
|
||||
extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
|
||||
|
||||
/* Sets an error message based on GetLastError(). Always return -1. */
|
||||
extern int WIN_SetError(const char *prefix);
|
||||
|
||||
/* Wrap up the oddities of CoInitialize() into a common function. */
|
||||
extern HRESULT WIN_CoInitialize(void);
|
||||
extern void WIN_CoUninitialize(void);
|
||||
|
||||
/* Returns SDL_TRUE if we're running on Windows Vista and newer */
|
||||
extern BOOL WIN_IsWindowsVistaOrGreater(void);
|
||||
|
||||
/* Returns SDL_TRUE if we're running on Windows 7 and newer */
|
||||
extern BOOL WIN_IsWindows7OrGreater(void);
|
||||
|
||||
/* You need to SDL_free() the result of this call. */
|
||||
extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);
|
||||
|
||||
/* Checks to see if two GUID are the same. */
|
||||
extern BOOL WIN_IsEqualGUID(const GUID * a, const GUID * b);
|
||||
extern BOOL WIN_IsEqualIID(REFIID a, REFIID b);
|
||||
|
||||
#endif /* _INCLUDED_WINDOWS_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
139
externals/SDL/src/core/windows/SDL_xinput.c
vendored
Executable file
139
externals/SDL/src/core/windows/SDL_xinput.c
vendored
Executable file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_xinput.h"
|
||||
|
||||
|
||||
#ifdef HAVE_XINPUT_H
|
||||
|
||||
XInputGetState_t SDL_XInputGetState = NULL;
|
||||
XInputSetState_t SDL_XInputSetState = NULL;
|
||||
XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
|
||||
XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation = NULL;
|
||||
DWORD SDL_XInputVersion = 0;
|
||||
|
||||
static HANDLE s_pXInputDLL = 0;
|
||||
static int s_XInputDLLRefCount = 0;
|
||||
|
||||
|
||||
#ifdef __WINRT__
|
||||
|
||||
int
|
||||
WIN_LoadXInputDLL(void)
|
||||
{
|
||||
/* Getting handles to system dlls (via LoadLibrary and its variants) is not
|
||||
* supported on WinRT, thus, pointers to XInput's functions can't be
|
||||
* retrieved via GetProcAddress.
|
||||
*
|
||||
* When on WinRT, assume that XInput is already loaded, and directly map
|
||||
* its XInput.h-declared functions to the SDL_XInput* set of function
|
||||
* pointers.
|
||||
*
|
||||
* Side-note: XInputGetStateEx is not available for use in WinRT.
|
||||
* This seems to mean that support for the guide button is not available
|
||||
* in WinRT, unfortunately.
|
||||
*/
|
||||
SDL_XInputGetState = (XInputGetState_t)XInputGetState;
|
||||
SDL_XInputSetState = (XInputSetState_t)XInputSetState;
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)XInputGetCapabilities;
|
||||
SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)XInputGetBatteryInformation;
|
||||
|
||||
/* XInput 1.4 ships with Windows 8 and 8.1: */
|
||||
SDL_XInputVersion = (1 << 16) | 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_UnloadXInputDLL(void)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !__WINRT__ */
|
||||
|
||||
int
|
||||
WIN_LoadXInputDLL(void)
|
||||
{
|
||||
DWORD version = 0;
|
||||
|
||||
if (s_pXInputDLL) {
|
||||
SDL_assert(s_XInputDLLRefCount > 0);
|
||||
s_XInputDLLRefCount++;
|
||||
return 0; /* already loaded */
|
||||
}
|
||||
|
||||
version = (1 << 16) | 4;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_4.dll"); /* 1.4 Ships with Windows 8. */
|
||||
if (!s_pXInputDLL) {
|
||||
version = (1 << 16) | 3;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_3.dll"); /* 1.3 can be installed as a redistributable component. */
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
/* "9.1.0" Ships with Vista and Win7, and is more limited than 1.3+ (e.g. XInputGetStateEx is not available.) */
|
||||
s_pXInputDLL = LoadLibrary(L"XInput9_1_0.dll");
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(s_XInputDLLRefCount == 0);
|
||||
SDL_XInputVersion = version;
|
||||
s_XInputDLLRefCount = 1;
|
||||
|
||||
/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
|
||||
SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, (LPCSTR)100);
|
||||
if (!SDL_XInputGetState) {
|
||||
SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetState");
|
||||
}
|
||||
SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
|
||||
SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetBatteryInformation" );
|
||||
if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
|
||||
WIN_UnloadXInputDLL();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_UnloadXInputDLL(void)
|
||||
{
|
||||
if (s_pXInputDLL) {
|
||||
SDL_assert(s_XInputDLLRefCount > 0);
|
||||
if (--s_XInputDLLRefCount == 0) {
|
||||
FreeLibrary(s_pXInputDLL);
|
||||
s_pXInputDLL = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_assert(s_XInputDLLRefCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
#endif /* HAVE_XINPUT_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
177
externals/SDL/src/core/windows/SDL_xinput.h
vendored
Executable file
177
externals/SDL/src/core/windows/SDL_xinput.h
vendored
Executable file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_xinput_h_
|
||||
#define SDL_xinput_h_
|
||||
|
||||
#ifdef HAVE_XINPUT_H
|
||||
|
||||
#include "SDL_windows.h"
|
||||
#include <xinput.h>
|
||||
|
||||
#ifndef XUSER_MAX_COUNT
|
||||
#define XUSER_MAX_COUNT 4
|
||||
#endif
|
||||
#ifndef XUSER_INDEX_ANY
|
||||
#define XUSER_INDEX_ANY 0x000000FF
|
||||
#endif
|
||||
#ifndef XINPUT_CAPS_FFB_SUPPORTED
|
||||
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
|
||||
#endif
|
||||
|
||||
#ifndef XINPUT_DEVSUBTYPE_UNKNOWN
|
||||
#define XINPUT_DEVSUBTYPE_UNKNOWN 0x00
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GAMEPAD
|
||||
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
||||
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE 0x07
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR_BASS
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR_BASS 0x0B
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
||||
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
||||
#endif
|
||||
|
||||
#ifndef XINPUT_GAMEPAD_GUIDE
|
||||
#define XINPUT_GAMEPAD_GUIDE 0x0400
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_DEVTYPE_GAMEPAD
|
||||
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
||||
#endif
|
||||
#ifndef BATTERY_TYPE_WIRED
|
||||
#define BATTERY_TYPE_WIRED 0x01
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_TYPE_UNKNOWN
|
||||
#define BATTERY_TYPE_UNKNOWN 0xFF
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_EMPTY
|
||||
#define BATTERY_LEVEL_EMPTY 0x00
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_LOW
|
||||
#define BATTERY_LEVEL_LOW 0x01
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_MEDIUM
|
||||
#define BATTERY_LEVEL_MEDIUM 0x02
|
||||
#endif
|
||||
#ifndef BATTERY_LEVEL_FULL
|
||||
#define BATTERY_LEVEL_FULL 0x03
|
||||
#endif
|
||||
|
||||
/* typedef's for XInput structs we use */
|
||||
|
||||
#ifndef HAVE_XINPUT_GAMEPAD_EX
|
||||
typedef struct
|
||||
{
|
||||
WORD wButtons;
|
||||
BYTE bLeftTrigger;
|
||||
BYTE bRightTrigger;
|
||||
SHORT sThumbLX;
|
||||
SHORT sThumbLY;
|
||||
SHORT sThumbRX;
|
||||
SHORT sThumbRY;
|
||||
DWORD dwPaddingReserved;
|
||||
} XINPUT_GAMEPAD_EX;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_XINPUT_STATE_EX
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwPacketNumber;
|
||||
XINPUT_GAMEPAD_EX Gamepad;
|
||||
} XINPUT_STATE_EX;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE BatteryType;
|
||||
BYTE BatteryLevel;
|
||||
} XINPUT_BATTERY_INFORMATION_EX;
|
||||
|
||||
/* Forward decl's for XInput API's we load dynamically and use if available */
|
||||
typedef DWORD (WINAPI *XInputGetState_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
XINPUT_STATE_EX* pState /* [out] Receives the current state */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputSetState_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
XINPUT_VIBRATION* pVibration /* [in, out] The vibration information to send to the controller */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputGetCapabilities_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
DWORD dwFlags, /* [in] Input flags that identify the device type */
|
||||
XINPUT_CAPABILITIES* pCapabilities /* [out] Receives the capabilities */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputGetBatteryInformation_t)
|
||||
(
|
||||
DWORD dwUserIndex,
|
||||
BYTE devType,
|
||||
XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation
|
||||
);
|
||||
|
||||
extern int WIN_LoadXInputDLL(void);
|
||||
extern void WIN_UnloadXInputDLL(void);
|
||||
|
||||
extern XInputGetState_t SDL_XInputGetState;
|
||||
extern XInputSetState_t SDL_XInputSetState;
|
||||
extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
|
||||
extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation;
|
||||
extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
|
||||
|
||||
#define XINPUTGETSTATE SDL_XInputGetState
|
||||
#define XINPUTSETSTATE SDL_XInputSetState
|
||||
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
|
||||
#define XINPUTGETBATTERYINFORMATION SDL_XInputGetBatteryInformation
|
||||
|
||||
#endif /* HAVE_XINPUT_H */
|
||||
|
||||
#endif /* SDL_xinput_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
67
externals/SDL/src/core/winrt/SDL_winrtapp_common.cpp
vendored
Executable file
67
externals/SDL/src/core/winrt/SDL_winrtapp_common.cpp
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_main.h"
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_winrtapp_direct3d.h"
|
||||
#include "SDL_winrtapp_xaml.h"
|
||||
|
||||
#include <wrl.h>
|
||||
|
||||
int (*WINRT_SDLAppEntryPoint)(int, char **) = NULL;
|
||||
|
||||
extern "C" DECLSPEC int
|
||||
SDL_WinRTRunApp(SDL_main_func mainFunction, void * xamlBackgroundPanel)
|
||||
{
|
||||
if (xamlBackgroundPanel) {
|
||||
return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel);
|
||||
} else {
|
||||
if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) {
|
||||
return 1;
|
||||
}
|
||||
return SDL_WinRTInitNonXAMLApp(mainFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" DECLSPEC SDL_WinRT_DeviceFamily
|
||||
SDL_WinRTGetDeviceFamily()
|
||||
{
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10 /* !!! FIXME: I have no idea if this is the right test. This is a UWP API, I think. Older windows should...just return "mobile"? I don't know. --ryan. */
|
||||
Platform::String^ deviceFamily = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily;
|
||||
|
||||
if (deviceFamily->Equals("Windows.Desktop"))
|
||||
{
|
||||
return SDL_WINRT_DEVICEFAMILY_DESKTOP;
|
||||
}
|
||||
else if (deviceFamily->Equals("Windows.Mobile"))
|
||||
{
|
||||
return SDL_WINRT_DEVICEFAMILY_MOBILE;
|
||||
}
|
||||
else if (deviceFamily->Equals("Windows.Xbox"))
|
||||
{
|
||||
return SDL_WINRT_DEVICEFAMILY_XBOX;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_WINRT_DEVICEFAMILY_UNKNOWN;
|
||||
}
|
31
externals/SDL/src/core/winrt/SDL_winrtapp_common.h
vendored
Executable file
31
externals/SDL/src/core/winrt/SDL_winrtapp_common.h
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef SDL_winrtapp_common_h_
|
||||
#define SDL_winrtapp_common_h_
|
||||
|
||||
/* A pointer to the app's C-style main() function (which is a different
|
||||
function than the WinRT app's actual entry point).
|
||||
*/
|
||||
extern int (*WINRT_SDLAppEntryPoint)(int, char **);
|
||||
|
||||
#endif // SDL_winrtapp_common_h_
|
855
externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp
vendored
Executable file
855
externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp
vendored
Executable file
@@ -0,0 +1,855 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
/* Standard C++11 includes */
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
/* Windows includes */
|
||||
#include "ppltasks.h"
|
||||
using namespace concurrency;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Input;
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
using namespace Windows::Phone::UI::Input;
|
||||
#endif
|
||||
|
||||
|
||||
/* SDL includes */
|
||||
extern "C" {
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_main.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_render.h"
|
||||
#include "../../video/SDL_sysvideo.h"
|
||||
//#include "../../SDL_hints_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../../render/SDL_sysrender.h"
|
||||
#include "../windows/SDL_windows.h"
|
||||
}
|
||||
|
||||
#include "../../video/winrt/SDL_winrtevents_c.h"
|
||||
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
|
||||
#include "SDL_winrtapp_common.h"
|
||||
#include "SDL_winrtapp_direct3d.h"
|
||||
|
||||
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
|
||||
/* Calling IDXGIDevice3::Trim on the active Direct3D 11.x device is necessary
|
||||
* when Windows 8.1 apps are about to get suspended.
|
||||
*/
|
||||
extern "C" void D3D11_Trim(SDL_Renderer *);
|
||||
#endif
|
||||
|
||||
|
||||
// Compile-time debugging options:
|
||||
// To enable, uncomment; to disable, comment them out.
|
||||
//#define LOG_POINTER_EVENTS 1
|
||||
//#define LOG_WINDOW_EVENTS 1
|
||||
//#define LOG_ORIENTATION_EVENTS 1
|
||||
|
||||
|
||||
// HACK, DLudwig: record a reference to the global, WinRT 'app'/view.
|
||||
// SDL/WinRT will use this throughout its code.
|
||||
//
|
||||
// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
|
||||
// non-global, such as something created inside
|
||||
// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
|
||||
// SDL_CreateWindow().
|
||||
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
|
||||
|
||||
ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
|
||||
{
|
||||
public:
|
||||
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
|
||||
};
|
||||
|
||||
IFrameworkView^ SDLApplicationSource::CreateView()
|
||||
{
|
||||
// TODO, WinRT: see if this function (CreateView) can ever get called
|
||||
// more than once. For now, just prevent it from ever assigning
|
||||
// SDL_WinRTGlobalApp more than once.
|
||||
SDL_assert(!SDL_WinRTGlobalApp);
|
||||
SDL_WinRTApp ^ app = ref new SDL_WinRTApp();
|
||||
if (!SDL_WinRTGlobalApp)
|
||||
{
|
||||
SDL_WinRTGlobalApp = app;
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **))
|
||||
{
|
||||
WINRT_SDLAppEntryPoint = mainFunction;
|
||||
auto direct3DApplicationSource = ref new SDLApplicationSource();
|
||||
CoreApplication::Run(direct3DApplicationSource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
|
||||
{
|
||||
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
|
||||
|
||||
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
|
||||
* from being changed on startup, by detecting when SDL_HINT_ORIENTATIONS
|
||||
* is getting registered.
|
||||
*
|
||||
* TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'.
|
||||
*/
|
||||
if ((oldValue == NULL) && (newValue == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start with no orientation flags, then add each in as they're parsed
|
||||
// from newValue.
|
||||
unsigned int orientationFlags = 0;
|
||||
if (newValue) {
|
||||
std::istringstream tokenizer(newValue);
|
||||
while (!tokenizer.eof()) {
|
||||
std::string orientationName;
|
||||
std::getline(tokenizer, orientationName, ' ');
|
||||
if (orientationName == "LandscapeLeft") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::LandscapeFlipped;
|
||||
} else if (orientationName == "LandscapeRight") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::Landscape;
|
||||
} else if (orientationName == "Portrait") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::Portrait;
|
||||
} else if (orientationName == "PortraitUpsideDown") {
|
||||
orientationFlags |= (unsigned int) DisplayOrientations::PortraitFlipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no valid orientation flags were specified, use a reasonable set of defaults:
|
||||
if (!orientationFlags) {
|
||||
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
|
||||
orientationFlags = (unsigned int) ( \
|
||||
DisplayOrientations::Landscape |
|
||||
DisplayOrientations::LandscapeFlipped |
|
||||
DisplayOrientations::Portrait |
|
||||
DisplayOrientations::PortraitFlipped);
|
||||
}
|
||||
|
||||
// Set the orientation/rotation preferences. Please note that this does
|
||||
// not constitute a 100%-certain lock of a given set of possible
|
||||
// orientations. According to Microsoft's documentation on WinRT [1]
|
||||
// when a device is not capable of being rotated, Windows may ignore
|
||||
// the orientation preferences, and stick to what the device is capable of
|
||||
// displaying.
|
||||
//
|
||||
// [1] Documentation on the 'InitialRotationPreference' setting for a
|
||||
// Windows app's manifest file describes how some orientation/rotation
|
||||
// preferences may be ignored. See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
|
||||
// for details. Microsoft's "Display orientation sample" also gives an
|
||||
// outline of how Windows treats device rotation
|
||||
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations) orientationFlags;
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
|
||||
{
|
||||
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
|
||||
if (coreWindow) {
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
int x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
|
||||
int y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
|
||||
/* WinPhone 8.0 always keeps its native window size in portrait,
|
||||
regardless of orientation. This changes in WinPhone 8.1,
|
||||
in which the native window's size changes along with
|
||||
orientation.
|
||||
|
||||
Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with
|
||||
regards to window size. This fixes a rendering bug that occurs
|
||||
when a WinPhone 8.0 app is rotated to either 90 or 270 degrees.
|
||||
*/
|
||||
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
|
||||
switch (currentOrientation) {
|
||||
case DisplayOrientations::Landscape:
|
||||
case DisplayOrientations::LandscapeFlipped: {
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
} break;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Uint32 latestFlags = WINRT_DetectWindowFlags(window);
|
||||
if (latestFlags & SDL_WINDOW_MAXIMIZED) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
|
||||
} else {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
}
|
||||
|
||||
WINRT_UpdateWindowFlags(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
|
||||
/* The window can move during a resize event, such as when maximizing
|
||||
or resizing from a corner */
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_WinRTApp::SDL_WinRTApp() :
|
||||
m_windowClosed(false),
|
||||
m_windowVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
|
||||
{
|
||||
applicationView->Activated +=
|
||||
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnAppActivated);
|
||||
|
||||
CoreApplication::Suspending +=
|
||||
ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
|
||||
|
||||
CoreApplication::Resuming +=
|
||||
ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnResuming);
|
||||
|
||||
CoreApplication::Exiting +=
|
||||
ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnExiting);
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
/* HACK ALERT! Xbox One doesn't seem to detect gamepads unless something
|
||||
gets registered to receive Win10's Windows.Gaming.Input.Gamepad.GamepadAdded
|
||||
events. We'll register an event handler for these events here, to make
|
||||
sure that gamepad detection works later on, if requested.
|
||||
*/
|
||||
Windows::Gaming::Input::Gamepad::GamepadAdded +=
|
||||
ref new Windows::Foundation::EventHandler<Windows::Gaming::Input::Gamepad^>(
|
||||
this, &SDL_WinRTApp::OnGamepadAdded
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
void SDL_WinRTApp::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
|
||||
#else
|
||||
void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
|
||||
#endif
|
||||
{
|
||||
#if LOG_ORIENTATION_EVENTS==1
|
||||
{
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
if (window) {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.X,
|
||||
window->Bounds.Y,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
} else {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
WINRT_ProcessWindowSizeChange();
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// HACK: Make sure that orientation changes
|
||||
// lead to the Direct3D renderer's viewport getting updated:
|
||||
//
|
||||
// For some reason, this doesn't seem to need to be done on Windows 8.x,
|
||||
// even when going from Landscape to LandscapeFlipped. It only seems to
|
||||
// be needed on Windows Phone, at least when I tested on my devices.
|
||||
// I'm not currently sure why this is, but it seems to work fine. -- David L.
|
||||
//
|
||||
// TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
if (window) {
|
||||
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SIZE_CHANGED, w, h);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n",
|
||||
__FUNCTION__,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.X,
|
||||
window->Bounds.Y,
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
#endif
|
||||
|
||||
window->SizeChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &SDL_WinRTApp::OnWindowSizeChanged);
|
||||
|
||||
window->VisibilityChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
|
||||
|
||||
window->Activated +=
|
||||
ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &SDL_WinRTApp::OnWindowActivated);
|
||||
|
||||
window->Closed +=
|
||||
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
|
||||
#endif
|
||||
|
||||
window->PointerPressed +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerPressed);
|
||||
|
||||
window->PointerMoved +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);
|
||||
|
||||
window->PointerReleased +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
|
||||
|
||||
window->PointerEntered +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerEntered);
|
||||
|
||||
window->PointerExited +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerExited);
|
||||
|
||||
window->PointerWheelChanged +=
|
||||
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
// Retrieves relative-only mouse movements:
|
||||
Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
|
||||
ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);
|
||||
#endif
|
||||
|
||||
window->KeyDown +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);
|
||||
|
||||
window->KeyUp +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
|
||||
|
||||
window->CharacterReceived +=
|
||||
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &SDL_WinRTApp::OnCharacterReceived);
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested +=
|
||||
ref new EventHandler<BackRequestedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
|
||||
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
HardwareButtons::BackPressed +=
|
||||
ref new EventHandler<BackPressedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
|
||||
#endif
|
||||
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
DisplayInformation::GetForCurrentView()->OrientationChanged +=
|
||||
ref new TypedEventHandler<Windows::Graphics::Display::DisplayInformation^, Object^>(this, &SDL_WinRTApp::OnOrientationChanged);
|
||||
#else
|
||||
DisplayProperties::OrientationChanged +=
|
||||
ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged);
|
||||
#endif
|
||||
|
||||
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
|
||||
// TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
|
||||
SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
// Make sure we know when a user has opened the app's settings pane.
|
||||
// This is needed in order to display a privacy policy, which needs
|
||||
// to be done for network-enabled apps, as per Windows Store requirements.
|
||||
using namespace Windows::UI::ApplicationSettings;
|
||||
SettingsPane::GetForCurrentView()->CommandsRequested +=
|
||||
ref new TypedEventHandler<SettingsPane^, SettingsPaneCommandsRequestedEventArgs^>
|
||||
(this, &SDL_WinRTApp::OnSettingsPaneCommandsRequested);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Load(Platform::String^ entryPoint)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Run()
|
||||
{
|
||||
SDL_SetMainReady();
|
||||
if (WINRT_SDLAppEntryPoint)
|
||||
{
|
||||
// TODO, WinRT: pass the C-style main() a reasonably realistic
|
||||
// representation of command line arguments.
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
WINRT_SDLAppEntryPoint(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSDLWindowEventPending(SDL_WindowEventID windowEventID)
|
||||
{
|
||||
SDL_Event events[128];
|
||||
const int count = SDL_PeepEvents(events, sizeof(events)/sizeof(SDL_Event), SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (events[i].window.event == windowEventID) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDL_WinRTApp::ShouldWaitForAppResumeEvents()
|
||||
{
|
||||
/* Don't wait if the app is visible: */
|
||||
if (m_windowVisible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't wait until the window-hide events finish processing.
|
||||
* Do note that if an app-suspend event is sent (as indicated
|
||||
* by SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND
|
||||
* events), then this code may be a moot point, as WinRT's
|
||||
* own event pump (aka ProcessEvents()) will pause regardless
|
||||
* of what we do here. This happens on Windows Phone 8, to note.
|
||||
* Windows 8.x apps, on the other hand, may get a chance to run
|
||||
* these.
|
||||
*/
|
||||
if (IsSDLWindowEventPending(SDL_WINDOWEVENT_HIDDEN)) {
|
||||
return false;
|
||||
} else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_FOCUS_LOST)) {
|
||||
return false;
|
||||
} else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_MINIMIZED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::PumpEvents()
|
||||
{
|
||||
if (!m_windowClosed) {
|
||||
if (!ShouldWaitForAppResumeEvents()) {
|
||||
/* This is the normal way in which events should be pumped.
|
||||
* 'ProcessAllIfPresent' will make ProcessEvents() process anywhere
|
||||
* from zero to N events, and will then return.
|
||||
*/
|
||||
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
} else {
|
||||
/* This style of event-pumping, with 'ProcessOneAndAllPending',
|
||||
* will cause anywhere from one to N events to be processed. If
|
||||
* at least one event is processed, the call will return. If
|
||||
* no events are pending, then the call will wait until one is
|
||||
* available, and will not return (to the caller) until this
|
||||
* happens! This should only occur when the app is hidden.
|
||||
*/
|
||||
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::Uninitialize()
|
||||
{
|
||||
}
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
void SDL_WinRTApp::OnSettingsPaneCommandsRequested(
|
||||
Windows::UI::ApplicationSettings::SettingsPane ^p,
|
||||
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args)
|
||||
{
|
||||
using namespace Platform;
|
||||
using namespace Windows::UI::ApplicationSettings;
|
||||
using namespace Windows::UI::Popups;
|
||||
|
||||
String ^privacyPolicyURL = nullptr; // a URL to an app's Privacy Policy
|
||||
String ^privacyPolicyLabel = nullptr; // label/link text
|
||||
const char *tmpHintValue = NULL; // SDL_GetHint-retrieved value, used immediately
|
||||
wchar_t *tmpStr = NULL; // used for UTF8 to UCS2 conversion
|
||||
|
||||
// Setup a 'Privacy Policy' link, if one is available (via SDL_GetHint):
|
||||
tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_URL);
|
||||
if (tmpHintValue && tmpHintValue[0] != '\0') {
|
||||
// Convert the privacy policy's URL to UCS2:
|
||||
tmpStr = WIN_UTF8ToString(tmpHintValue);
|
||||
privacyPolicyURL = ref new String(tmpStr);
|
||||
SDL_free(tmpStr);
|
||||
|
||||
// Optionally retrieve custom label-text for the link. If this isn't
|
||||
// available, a default value will be used instead.
|
||||
tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_LABEL);
|
||||
if (tmpHintValue && tmpHintValue[0] != '\0') {
|
||||
tmpStr = WIN_UTF8ToString(tmpHintValue);
|
||||
privacyPolicyLabel = ref new String(tmpStr);
|
||||
SDL_free(tmpStr);
|
||||
} else {
|
||||
privacyPolicyLabel = ref new String(L"Privacy Policy");
|
||||
}
|
||||
|
||||
// Register the link, along with a handler to be called if and when it is
|
||||
// clicked:
|
||||
auto cmd = ref new SettingsCommand(L"privacyPolicy", privacyPolicyLabel,
|
||||
ref new UICommandInvokedHandler([=](IUICommand ^) {
|
||||
Windows::System::Launcher::LaunchUriAsync(ref new Uri(privacyPolicyURL));
|
||||
}));
|
||||
args->Request->ApplicationCommands->Append(cmd);
|
||||
}
|
||||
}
|
||||
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
|
||||
void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
|
||||
__FUNCTION__,
|
||||
args->Size.Width, args->Size.Height,
|
||||
sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessWindowSizeChange();
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n",
|
||||
__FUNCTION__,
|
||||
(args->Visible ? "yes" : "no"),
|
||||
sender->Bounds.X, sender->Bounds.Y,
|
||||
sender->Bounds.Width, sender->Bounds.Height,
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
m_windowVisible = args->Visible;
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
|
||||
Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow);
|
||||
if (args->Visible) {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
||||
if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
|
||||
} else {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
}
|
||||
} else {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
||||
}
|
||||
|
||||
// HACK: Prevent SDL's window-hide handling code, which currently
|
||||
// triggers a fake window resize (possibly erronously), from
|
||||
// marking the SDL window's surface as invalid.
|
||||
//
|
||||
// A better solution to this probably involves figuring out if the
|
||||
// fake window resize can be prevented.
|
||||
WINRT_GlobalSDLWindow->surface_valid = wasSDLWindowSurfaceValid;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n",
|
||||
__FUNCTION__,
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
/* There's no property in Win 8.x to tell whether a window is active or
|
||||
not. [De]activation events are, however, sent to the app. We'll just
|
||||
record those, in case the CoreWindow gets wrapped by an SDL_Window at
|
||||
some future time.
|
||||
*/
|
||||
sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState);
|
||||
|
||||
SDL_Window * window = WINRT_GlobalSDLWindow;
|
||||
if (window) {
|
||||
if (args->WindowActivationState != CoreWindowActivationState::Deactivated) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
if (SDL_GetKeyboardFocus() != window) {
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
|
||||
/* Send a mouse-motion event as appropriate.
|
||||
This doesn't work when called from OnPointerEntered, at least
|
||||
not in WinRT CoreWindow apps (as OnPointerEntered doesn't
|
||||
appear to be called after window-reactivation, at least not
|
||||
in Windows 10, Build 10586.3 (November 2015 update, non-beta).
|
||||
|
||||
Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition'
|
||||
property isn't available.
|
||||
*/
|
||||
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
|
||||
Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
|
||||
SDL_SendMouseMotion(window, 0, 0, (int)cursorPos.X, (int)cursorPos.Y);
|
||||
#endif
|
||||
|
||||
/* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
|
||||
//WIN_CheckAsyncMouseRelease(data);
|
||||
|
||||
/* TODO, WinRT: implement clipboard support, if possible */
|
||||
///*
|
||||
// * FIXME: Update keyboard state
|
||||
// */
|
||||
//WIN_CheckClipboardUpdate(data->videodata);
|
||||
|
||||
// HACK: Resetting the mouse-cursor here seems to fix
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=3217, whereby a
|
||||
// WinRT app's mouse cursor may switch to Windows' 'wait' cursor,
|
||||
// after a user alt-tabs back into a full-screened SDL app.
|
||||
// This bug does not appear to reproduce 100% of the time.
|
||||
// It may be a bug in Windows itself (v.10.0.586.36, as tested,
|
||||
// and the most-recent as of this writing).
|
||||
SDL_SetCursor(NULL);
|
||||
} else {
|
||||
if (SDL_GetKeyboardFocus() == window) {
|
||||
SDL_SetKeyboardFocus(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
{
|
||||
#if LOG_WINDOW_EVENTS==1
|
||||
SDL_Log("%s\n", __FUNCTION__);
|
||||
#endif
|
||||
m_windowClosed = true;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
||||
{
|
||||
// Save app state asynchronously after requesting a deferral. Holding a deferral
|
||||
// indicates that the application is busy performing suspending operations. Be
|
||||
// aware that a deferral may not be held indefinitely. After about five seconds,
|
||||
// the app will be forced to exit.
|
||||
|
||||
// ... but first, let the app know it's about to go to the background.
|
||||
// The separation of events may be important, given that the deferral
|
||||
// runs in a separate thread. This'll make SDL_APP_WILLENTERBACKGROUND
|
||||
// the only event among the two that runs in the main thread. Given
|
||||
// that a few WinRT operations can only be done from the main thread
|
||||
// (things that access the WinRT CoreWindow are one example of this),
|
||||
// this could be important.
|
||||
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||
|
||||
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
|
||||
create_task([this, deferral]()
|
||||
{
|
||||
// Send an app did-enter-background event immediately to observers.
|
||||
// CoreDispatcher::ProcessEvents, which is the backbone on which
|
||||
// SDL_WinRTApp::PumpEvents is built, will not return to its caller
|
||||
// once it sends out a suspend event. Any events posted to SDL's
|
||||
// event queue won't get received until the WinRT app is resumed.
|
||||
// SDL_AddEventWatch() may be used to receive app-suspend events on
|
||||
// WinRT.
|
||||
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
||||
|
||||
// Let the Direct3D 11 renderer prepare for the app to be backgrounded.
|
||||
// This is necessary for Windows 8.1, possibly elsewhere in the future.
|
||||
// More details at: http://msdn.microsoft.com/en-us/library/windows/apps/Hh994929.aspx
|
||||
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
SDL_Renderer * renderer = SDL_GetRenderer(WINRT_GlobalSDLWindow);
|
||||
if (renderer && (SDL_strcmp(renderer->info.name, "direct3d11") == 0)) {
|
||||
D3D11_Trim(renderer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
deferral->Complete();
|
||||
});
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
||||
{
|
||||
// Restore any data or state that was unloaded on suspend. By default, data
|
||||
// and state are persisted when resuming from suspend. Note that these events
|
||||
// do not occur if the app was previously terminated.
|
||||
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
|
||||
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
|
||||
{
|
||||
SDL_SendAppEvent(SDL_APP_TERMINATING);
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
|
||||
{
|
||||
Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
|
||||
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n",
|
||||
header,
|
||||
pt->Position.X, pt->Position.Y,
|
||||
transformedPoint.X, transformedPoint.Y,
|
||||
pt->Properties->MouseWheelDelta,
|
||||
pt->FrameId,
|
||||
pt->PointerId,
|
||||
WINRT_GetSDLButtonForPointerPoint(pt));
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer pressed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer moved", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerEntered(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer wheel changed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessKeyDownEvent(args);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessKeyUpEvent(args);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessCharacterReceivedEvent(args);
|
||||
}
|
||||
|
||||
template <typename BackButtonEventArgs>
|
||||
static void WINRT_OnBackButtonPressed(BackButtonEventArgs ^ args)
|
||||
{
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_AC_BACK);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_AC_BACK);
|
||||
|
||||
if (SDL_GetHintBoolean(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, SDL_FALSE)) {
|
||||
args->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args)
|
||||
|
||||
{
|
||||
WINRT_OnBackButtonPressed(args);
|
||||
}
|
||||
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args)
|
||||
|
||||
{
|
||||
WINRT_OnBackButtonPressed(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
void SDL_WinRTApp::OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad)
|
||||
{
|
||||
/* HACK ALERT: Nothing needs to be done here, as this method currently
|
||||
only exists to allow something to be registered with Win10's
|
||||
GamepadAdded event, an operation that seems to be necessary to get
|
||||
Xinput-based detection to work on Xbox One.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
92
externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.h
vendored
Executable file
92
externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.h
vendored
Executable file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <Windows.h>
|
||||
|
||||
extern int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **));
|
||||
|
||||
ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFrameworkView
|
||||
{
|
||||
public:
|
||||
SDL_WinRTApp();
|
||||
|
||||
// IFrameworkView Methods.
|
||||
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
|
||||
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
|
||||
virtual void Load(Platform::String^ entryPoint);
|
||||
virtual void Run();
|
||||
virtual void Uninitialize();
|
||||
|
||||
internal:
|
||||
// SDL-specific methods
|
||||
void PumpEvents();
|
||||
|
||||
protected:
|
||||
bool ShouldWaitForAppResumeEvents();
|
||||
|
||||
// Event Handlers.
|
||||
|
||||
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
void OnSettingsPaneCommandsRequested(
|
||||
Windows::UI::ApplicationSettings::SettingsPane ^p,
|
||||
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args);
|
||||
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
|
||||
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
#else
|
||||
void OnOrientationChanged(Platform::Object^ sender);
|
||||
#endif
|
||||
void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
|
||||
void OnLogicalDpiChanged(Platform::Object^ sender);
|
||||
void OnAppActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
|
||||
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
|
||||
void OnResuming(Platform::Object^ sender, Platform::Object^ args);
|
||||
void OnExiting(Platform::Object^ sender, Platform::Object^ args);
|
||||
void OnWindowActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args);
|
||||
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
|
||||
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
|
||||
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
void OnBackButtonPressed(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args);
|
||||
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args);
|
||||
#endif
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
void OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_windowClosed;
|
||||
bool m_windowVisible;
|
||||
};
|
||||
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
160
externals/SDL/src/core/winrt/SDL_winrtapp_xaml.cpp
vendored
Executable file
160
externals/SDL/src/core/winrt/SDL_winrtapp_xaml.cpp
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Windows includes */
|
||||
#include <agile.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* SDL includes */
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL.h"
|
||||
#include "../../video/winrt/SDL_winrtevents_c.h"
|
||||
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
|
||||
#include "SDL_winrtapp_common.h"
|
||||
#include "SDL_winrtapp_xaml.h"
|
||||
|
||||
|
||||
|
||||
/* SDL-internal globals: */
|
||||
SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
extern "C"
|
||||
ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative = NULL;
|
||||
static Windows::Foundation::EventRegistrationToken WINRT_XAMLAppEventToken;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Input event handlers (XAML)
|
||||
*/
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
static void
|
||||
WINRT_OnPointerPressedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerMovedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerReleasedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerWheelChangedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
|
||||
/*
|
||||
* XAML-to-SDL Rendering Callback
|
||||
*/
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
static void
|
||||
WINRT_OnRenderViaXAML(_In_ Platform::Object^ sender, _In_ Platform::Object^ args)
|
||||
{
|
||||
WINRT_CycleXAMLThread();
|
||||
}
|
||||
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
|
||||
/*
|
||||
* SDL + XAML Initialization
|
||||
*/
|
||||
|
||||
int
|
||||
SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void * backgroundPanelAsIInspectable)
|
||||
{
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
return SDL_SetError("XAML support is not yet available in Windows Phone.");
|
||||
#else
|
||||
// Declare C++/CX namespaces:
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
|
||||
// Make sure we have a valid XAML element (to draw onto):
|
||||
if ( ! backgroundPanelAsIInspectable) {
|
||||
return SDL_SetError("'backgroundPanelAsIInspectable' can't be NULL");
|
||||
}
|
||||
|
||||
Platform::Object ^ backgroundPanel = reinterpret_cast<Object ^>((IInspectable *) backgroundPanelAsIInspectable);
|
||||
SwapChainBackgroundPanel ^swapChainBackgroundPanel = dynamic_cast<SwapChainBackgroundPanel ^>(backgroundPanel);
|
||||
if ( ! swapChainBackgroundPanel) {
|
||||
return SDL_SetError("An unknown or unsupported type of XAML control was specified.");
|
||||
}
|
||||
|
||||
// Setup event handlers:
|
||||
swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML);
|
||||
swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML);
|
||||
swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML);
|
||||
swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML);
|
||||
|
||||
// Setup for rendering:
|
||||
IInspectable *panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainBackgroundPanel);
|
||||
panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative);
|
||||
|
||||
WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(WINRT_OnRenderViaXAML));
|
||||
|
||||
// Make sure the app is ready to call the SDL-centric main() function:
|
||||
WINRT_SDLAppEntryPoint = mainFunction;
|
||||
SDL_SetMainReady();
|
||||
|
||||
// Make sure video-init knows that we're initializing XAML:
|
||||
SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled;
|
||||
WINRT_XAMLWasEnabled = SDL_TRUE;
|
||||
|
||||
// Make sure video modes are detected now, while we still have access to the WinRT
|
||||
// CoreWindow. WinRT will not allow the app's CoreWindow to be accessed via the
|
||||
// SDL/WinRT thread.
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
||||
// SDL_InitSubSystem will, on error, set the SDL error. Let that propogate to
|
||||
// the caller to here:
|
||||
WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// All done, for now.
|
||||
return 0;
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP / else
|
||||
}
|
33
externals/SDL/src/core/winrt/SDL_winrtapp_xaml.h
vendored
Executable file
33
externals/SDL/src/core/winrt/SDL_winrtapp_xaml.h
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef SDL_winrtapp_xaml_h_
|
||||
#define SDL_winrtapp_xaml_h_
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern SDL_bool WINRT_XAMLWasEnabled;
|
||||
extern int SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void * backgroundPanelAsIInspectable);
|
||||
#endif // ifdef __cplusplus
|
||||
|
||||
#endif // SDL_winrtapp_xaml_h_
|
Reference in New Issue
Block a user