mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-28 13:16:40 +00:00
release 0.1.0
This commit is contained in:
+1043
-788
File diff suppressed because it is too large
Load Diff
+26
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -33,11 +33,14 @@ extern "C" {
|
||||
|
||||
#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);
|
||||
@@ -45,6 +48,7 @@ extern void Android_JNI_HideTextInput(void);
|
||||
extern SDL_bool Android_JNI_IsScreenKeyboardShown(void);
|
||||
extern ANativeWindow* Android_JNI_GetNativeWindow(void);
|
||||
|
||||
extern SDL_DisplayOrientation Android_JNI_GetDisplayOrientation(void);
|
||||
extern int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi);
|
||||
|
||||
/* Audio support */
|
||||
@@ -54,10 +58,11 @@ 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();
|
||||
extern SDL_bool Android_IsChromebook();
|
||||
extern SDL_bool Android_IsDeXMode(void);
|
||||
extern SDL_bool Android_IsChromebook(void);
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
|
||||
@@ -91,15 +96,16 @@ void Android_JNI_HapticStop(int device_id);
|
||||
void Android_JNI_SuspendScreenSaver(SDL_bool suspend);
|
||||
|
||||
/* Touch support */
|
||||
int Android_JNI_InitTouch(void);
|
||||
void Android_JNI_SetSeparateMouseAndTouch(SDL_bool new_value);
|
||||
int Android_JNI_GetTouchDeviceIds(int **ids);
|
||||
void Android_JNI_InitTouch(void);
|
||||
|
||||
/* Threads */
|
||||
#include <jni.h>
|
||||
JNIEnv *Android_JNI_GetEnv(void);
|
||||
int Android_JNI_SetupThread(void);
|
||||
|
||||
/* Locale */
|
||||
int Android_JNI_GetLocale(char *buf, size_t buflen);
|
||||
|
||||
/* Generic messages */
|
||||
int Android_JNI_SendMessage(int command, int param);
|
||||
|
||||
@@ -112,6 +118,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu
|
||||
|
||||
/* Cursor support */
|
||||
int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y);
|
||||
void Android_JNI_DestroyCustomCursor(int cursorID);
|
||||
SDL_bool Android_JNI_SetCustomCursor(int cursorID);
|
||||
SDL_bool Android_JNI_SetSystemCursor(int cursorID);
|
||||
|
||||
@@ -119,12 +126,25 @@ SDL_bool Android_JNI_SetSystemCursor(int cursorID);
|
||||
SDL_bool Android_JNI_SupportsRelativeMouse(void);
|
||||
SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled);
|
||||
|
||||
/* Request permission */
|
||||
SDL_bool Android_JNI_RequestPermission(const char *permission);
|
||||
|
||||
/* Show toast notification */
|
||||
int Android_JNI_ShowToast(const char* message, int duration, int gravity, int xOffset, int yOffset);
|
||||
|
||||
int Android_JNI_OpenURL(const char *url);
|
||||
|
||||
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* */
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <sys/kbio.h>
|
||||
|
||||
/*
|
||||
* Automatically generated from /usr/share/vt/keymaps/us.acc.kbd.
|
||||
* DO NOT EDIT!
|
||||
*/
|
||||
static keymap_t keymap_default_us_acc = { 0x6d, {
|
||||
/* alt
|
||||
* scan cntrl alt alt cntrl
|
||||
* code base shift cntrl shift alt shift cntrl shift spcl flgs
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
/*00*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 },
|
||||
/*01*/{{ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, DBG, }, 0x03,0x00 },
|
||||
/*02*/{{ '1', '!', NOP, NOP, '1', '!', NOP, NOP, }, 0x33,0x00 },
|
||||
/*03*/{{ '2', '@', 0x00, 0x00, '2', '@', 0x00, 0x00, }, 0x00,0x00 },
|
||||
/*04*/{{ '3', '#', NOP, NOP, '3', '#', NOP, NOP, }, 0x33,0x00 },
|
||||
/*05*/{{ '4', '$', NOP, NOP, '4', '$', NOP, NOP, }, 0x33,0x00 },
|
||||
/*06*/{{ '5', '%', NOP, NOP, '5', '%', NOP, NOP, }, 0x33,0x00 },
|
||||
/*07*/{{ '6', '^', 0x1E, 0x1E, '6', DCIR, 0x1E, 0x1E, }, 0x04,0x00 },
|
||||
/*08*/{{ '7', '&', NOP, NOP, '7', '&', NOP, NOP, }, 0x33,0x00 },
|
||||
/*09*/{{ '8', '*', NOP, NOP, '8', DRIN, NOP, NOP, }, 0x37,0x00 },
|
||||
/*0a*/{{ '9', '(', NOP, NOP, '9', '(', NOP, NOP, }, 0x33,0x00 },
|
||||
/*0b*/{{ '0', ')', NOP, NOP, '0', ')', NOP, NOP, }, 0x33,0x00 },
|
||||
/*0c*/{{ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, }, 0x00,0x00 },
|
||||
/*0d*/{{ '=', '+', NOP, NOP, '=', '+', NOP, NOP, }, 0x33,0x00 },
|
||||
/*0e*/{{ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, }, 0x00,0x00 },
|
||||
/*0f*/{{ 0x09, BTAB, NEXT, NEXT, 0x09, BTAB, NOP, NOP, }, 0x77,0x00 },
|
||||
/*10*/{{ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, }, 0x00,0x01 },
|
||||
/*11*/{{ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, }, 0x00,0x01 },
|
||||
/*12*/{{ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, }, 0x00,0x01 },
|
||||
/*13*/{{ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, }, 0x00,0x01 },
|
||||
/*14*/{{ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, }, 0x00,0x01 },
|
||||
/*15*/{{ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, }, 0x00,0x01 },
|
||||
/*16*/{{ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, }, 0x00,0x01 },
|
||||
/*17*/{{ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, }, 0x00,0x01 },
|
||||
/*18*/{{ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, }, 0x00,0x01 },
|
||||
/*19*/{{ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, }, 0x00,0x01 },
|
||||
/*1a*/{{ '[', '{', 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, }, 0x00,0x00 },
|
||||
/*1b*/{{ ']', '}', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, }, 0x00,0x00 },
|
||||
/*1c*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 },
|
||||
/*1d*/{{ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, }, 0xFF,0x00 },
|
||||
/*1e*/{{ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, }, 0x00,0x01 },
|
||||
/*1f*/{{ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, }, 0x00,0x01 },
|
||||
/*20*/{{ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, }, 0x00,0x01 },
|
||||
/*21*/{{ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, }, 0x00,0x01 },
|
||||
/*22*/{{ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, }, 0x00,0x01 },
|
||||
/*23*/{{ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, }, 0x00,0x01 },
|
||||
/*24*/{{ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, }, 0x00,0x01 },
|
||||
/*25*/{{ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, }, 0x00,0x01 },
|
||||
/*26*/{{ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, }, 0x00,0x01 },
|
||||
/*27*/{{ ';', ':', NOP, NOP, ';', ':', NOP, NOP, }, 0x33,0x00 },
|
||||
/*28*/{{ '\'', '"', NOP, NOP, DACU, DUML, NOP, NOP, }, 0x3F,0x00 },
|
||||
/*29*/{{ '`', '~', NOP, NOP, DGRA, DTIL, NOP, NOP, }, 0x3F,0x00 },
|
||||
/*2a*/{{ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, }, 0xFF,0x00 },
|
||||
/*2b*/{{ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, }, 0x00,0x00 },
|
||||
/*2c*/{{ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, }, 0x00,0x01 },
|
||||
/*2d*/{{ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, }, 0x00,0x01 },
|
||||
/*2e*/{{ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, }, 0x00,0x01 },
|
||||
/*2f*/{{ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, }, 0x00,0x01 },
|
||||
/*30*/{{ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, }, 0x00,0x01 },
|
||||
/*31*/{{ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, }, 0x00,0x01 },
|
||||
/*32*/{{ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, }, 0x00,0x01 },
|
||||
/*33*/{{ ',', '<', NOP, NOP, DCED, '<', NOP, NOP, }, 0x3B,0x00 },
|
||||
/*34*/{{ '.', '>', NOP, NOP, '.', '>', NOP, NOP, }, 0x33,0x00 },
|
||||
/*35*/{{ '/', '?', NOP, NOP, '/', '?', NOP, NOP, }, 0x33,0x00 },
|
||||
/*36*/{{ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, }, 0xFF,0x00 },
|
||||
/*37*/{{ '*', '*', '*', '*', '*', '*', '*', '*', }, 0x00,0x00 },
|
||||
/*38*/{{ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, }, 0xFF,0x00 },
|
||||
/*39*/{{ ' ', ' ', 0x00, 0x00, ' ', ' ', SUSP, SUSP, }, 0x03,0x00 },
|
||||
/*3a*/{{ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, }, 0xFF,0x00 },
|
||||
/*3b*/{{ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11),}, 0xFF,0x00 },
|
||||
/*3c*/{{ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12),}, 0xFF,0x00 },
|
||||
/*3d*/{{ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13),}, 0xFF,0x00 },
|
||||
/*3e*/{{ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14),}, 0xFF,0x00 },
|
||||
/*3f*/{{ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15),}, 0xFF,0x00 },
|
||||
/*40*/{{ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16),}, 0xFF,0x00 },
|
||||
/*41*/{{ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7),}, 0xFF,0x00 },
|
||||
/*42*/{{ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8),}, 0xFF,0x00 },
|
||||
/*43*/{{ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9),}, 0xFF,0x00 },
|
||||
/*44*/{{ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10),}, 0xFF,0x00 },
|
||||
/*45*/{{ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, }, 0xFF,0x00 },
|
||||
/*46*/{{ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, }, 0xFF,0x00 },
|
||||
/*47*/{{ F(49), '7', '7', '7', '7', '7', '7', '7', }, 0x80,0x02 },
|
||||
/*48*/{{ F(50), '8', '8', '8', '8', '8', '8', '8', }, 0x80,0x02 },
|
||||
/*49*/{{ F(51), '9', '9', '9', '9', '9', '9', '9', }, 0x80,0x02 },
|
||||
/*4a*/{{ F(52), '-', '-', '-', '-', '-', '-', '-', }, 0x80,0x02 },
|
||||
/*4b*/{{ F(53), '4', '4', '4', '4', '4', '4', '4', }, 0x80,0x02 },
|
||||
/*4c*/{{ F(54), '5', '5', '5', '5', '5', '5', '5', }, 0x80,0x02 },
|
||||
/*4d*/{{ F(55), '6', '6', '6', '6', '6', '6', '6', }, 0x80,0x02 },
|
||||
/*4e*/{{ F(56), '+', '+', '+', '+', '+', '+', '+', }, 0x80,0x02 },
|
||||
/*4f*/{{ F(57), '1', '1', '1', '1', '1', '1', '1', }, 0x80,0x02 },
|
||||
/*50*/{{ F(58), '2', '2', '2', '2', '2', '2', '2', }, 0x80,0x02 },
|
||||
/*51*/{{ F(59), '3', '3', '3', '3', '3', '3', '3', }, 0x80,0x02 },
|
||||
/*52*/{{ F(60), '0', '0', '0', '0', '0', '0', '0', }, 0x80,0x02 },
|
||||
/*53*/{{ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, }, 0x03,0x02 },
|
||||
/*54*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 },
|
||||
/*55*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 },
|
||||
/*56*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 },
|
||||
/*57*/{{ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11),}, 0xFF,0x00 },
|
||||
/*58*/{{ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12),}, 0xFF,0x00 },
|
||||
/*59*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 },
|
||||
/*5a*/{{ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, }, 0xFF,0x00 },
|
||||
/*5b*/{{ '/', '/', '/', '/', '/', '/', '/', '/', }, 0x00,0x02 },
|
||||
/*5c*/{{ NEXT, NEXT, NOP, NOP, DBG, DBG, DBG, DBG, }, 0xFF,0x00 },
|
||||
/*5d*/{{ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, }, 0xFF,0x00 },
|
||||
/*5e*/{{ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49),}, 0xFF,0x00 },
|
||||
/*5f*/{{ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50),}, 0xFF,0x00 },
|
||||
/*60*/{{ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51),}, 0xFF,0x00 },
|
||||
/*61*/{{ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53),}, 0xFF,0x00 },
|
||||
/*62*/{{ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55),}, 0xFF,0x00 },
|
||||
/*63*/{{ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57),}, 0xFF,0x00 },
|
||||
/*64*/{{ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58),}, 0xFF,0x00 },
|
||||
/*65*/{{ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59),}, 0xFF,0x00 },
|
||||
/*66*/{{ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60),}, 0xFF,0x00 },
|
||||
/*67*/{{ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61),}, 0xFF,0x00 },
|
||||
/*68*/{{ SPSC, SPSC, SUSP, SUSP, NOP, NOP, SUSP, SUSP, }, 0xFF,0x00 },
|
||||
/*69*/{{ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62),}, 0xFF,0x00 },
|
||||
/*6a*/{{ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63),}, 0xFF,0x00 },
|
||||
/*6b*/{{ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64),}, 0xFF,0x00 },
|
||||
/*6c*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 },
|
||||
} };
|
||||
|
||||
static accentmap_t accentmap_default_us_acc = { 11, {
|
||||
/* dgra=0 */
|
||||
{ '`', { { 'a',0xe0 }, { 'A',0xc0 }, { 'e',0xe8 }, { 'E',0xc8 },
|
||||
{ 'i',0xec }, { 'I',0xcc }, { 'o',0xf2 }, { 'O',0xd2 },
|
||||
{ 'u',0xf9 }, { 'U',0xd9 }, }, },
|
||||
/* dacu=1 */
|
||||
{ 0xb4, { { 'a',0xe1 }, { 'A',0xc1 }, { 'e',0xe9 }, { 'E',0xc9 },
|
||||
{ 'i',0xed }, { 'I',0xcd }, { 'o',0xf3 }, { 'O',0xd3 },
|
||||
{ 'u',0xfa }, { 'U',0xda }, { 'y',0xfd }, { 'Y',0xdd }, }, },
|
||||
/* dcir=2 */
|
||||
{ '^', { { 'a',0xe2 }, { 'A',0xc2 }, { 'e',0xea }, { 'E',0xca },
|
||||
{ 'i',0xee }, { 'I',0xce }, { 'o',0xf4 }, { 'O',0xd4 },
|
||||
{ 'u',0xfb }, { 'U',0xdb }, }, },
|
||||
/* dtil=3 */
|
||||
{ '~', { { 'a',0xe3 }, { 'A',0xc3 }, { 'n',0xf1 }, { 'N',0xd1 },
|
||||
{ 'o',0xf5 }, { 'O',0xd5 }, }, },
|
||||
/* dmac=4 */
|
||||
{ 0x00 },
|
||||
/* dbre=5 */
|
||||
{ 0x00 },
|
||||
/* ddot=6 */
|
||||
{ 0x00 },
|
||||
/* duml=7 */
|
||||
{ 0xa8, { { 'a',0xe4 }, { 'A',0xc4 }, { 'e',0xeb }, { 'E',0xcb },
|
||||
{ 'i',0xef }, { 'I',0xcf }, { 'o',0xf6 }, { 'O',0xd6 },
|
||||
{ 'u',0xfc }, { 'U',0xdc }, { 'y',0xff }, }, },
|
||||
/* dsla=8 */
|
||||
{ 0x00 },
|
||||
/* drin=9 */
|
||||
{ 0xb0, { { 'a',0xe5 }, { 'A',0xc5 }, }, },
|
||||
/* dced=10 */
|
||||
{ 0xb8, { { 'c',0xe7 }, { 'C',0xc7 }, }, },
|
||||
/* dapo=11 */
|
||||
{ 0x00 },
|
||||
/* ddac=12 */
|
||||
{ 0x00 },
|
||||
/* dogo=13 */
|
||||
{ 0x00 },
|
||||
/* dcar=14 */
|
||||
{ 0x00 },
|
||||
} };
|
||||
|
||||
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 "../linux/SDL_evdev_kbd.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#ifdef SDL_INPUT_FBSDKBIO
|
||||
|
||||
/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <sys/consio.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_evdev_kbd_default_keyaccmap.h"
|
||||
|
||||
typedef void (fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
|
||||
|
||||
/*
|
||||
* Keyboard State
|
||||
*/
|
||||
|
||||
struct SDL_EVDEV_keyboard_state
|
||||
{
|
||||
int console_fd;
|
||||
int keyboard_fd;
|
||||
unsigned long old_kbd_mode;
|
||||
unsigned short **key_maps;
|
||||
keymap_t* key_map;
|
||||
keyboard_info_t* kbInfo;
|
||||
unsigned char shift_down[4]; /* shift state counters.. */
|
||||
SDL_bool dead_key_next;
|
||||
int npadch; /* -1 or number assembled on pad */
|
||||
accentmap_t *accents;
|
||||
unsigned int diacr;
|
||||
SDL_bool rep; /* flag telling character repeat */
|
||||
unsigned char lockstate;
|
||||
unsigned char ledflagstate;
|
||||
char shift_state;
|
||||
char text[128];
|
||||
unsigned int text_len;
|
||||
};
|
||||
|
||||
static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
return (ioctl(kbd->keyboard_fd, GIO_KEYMAP, kbd->key_map) >= 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)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
SDL_EVDEV_keyboard_state* kbd = kbd_cleanup_state;
|
||||
if (kbd == NULL) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_SHOW;
|
||||
ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
if (kbd->keyboard_fd != kbd->console_fd) close(kbd->keyboard_fd);
|
||||
ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index));
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
}
|
||||
|
||||
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;
|
||||
struct mouse_info mData;
|
||||
char flag_state;
|
||||
char* devicePath;
|
||||
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_HIDE;
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state));
|
||||
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->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
kbd->shift_state = 0;
|
||||
|
||||
kbd->accents = SDL_calloc(sizeof(accentmap_t), 1);
|
||||
kbd->key_map = SDL_calloc(sizeof(keymap_t), 1);
|
||||
kbd->kbInfo = SDL_calloc(sizeof(keyboard_info_t), 1);
|
||||
|
||||
ioctl(kbd->console_fd, KDGKBINFO, kbd->kbInfo);
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
|
||||
if (ioctl(kbd->console_fd, KDGKBSTATE, &flag_state) == 0) {
|
||||
kbd->ledflagstate = flag_state;
|
||||
}
|
||||
|
||||
if (ioctl(kbd->console_fd, GIO_DEADKEYMAP, kbd->accents) < 0)
|
||||
{
|
||||
SDL_free(kbd->accents);
|
||||
kbd->accents = &accentmap_default_us_acc;
|
||||
}
|
||||
|
||||
if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
|
||||
/* Set the keyboard in XLATE mode and load the keymaps */
|
||||
ioctl(kbd->console_fd, KDSKBMODE, (unsigned long)(K_XLATE));
|
||||
if(!SDL_EVDEV_kbd_load_keymaps(kbd))
|
||||
{
|
||||
SDL_free(kbd->key_map);
|
||||
kbd->key_map = &keymap_default_us_acc;
|
||||
}
|
||||
/* Allow inhibiting keyboard mute with env. variable for debugging etc. */
|
||||
if (SDL_getenv("SDL_INPUT_FREEBSD_KEEP_KBD") == NULL) {
|
||||
/* Take keyboard from console and open the actual keyboard device.
|
||||
* Ensures that the keystrokes do not leak through to the console.
|
||||
*/
|
||||
ioctl(kbd->console_fd, CONS_RELKBD, 1ul);
|
||||
SDL_asprintf(&devicePath, "/dev/kbd%d", kbd->kbInfo->kb_index);
|
||||
kbd->keyboard_fd = open(devicePath, O_WRONLY | O_CLOEXEC);
|
||||
if (kbd->keyboard_fd == -1)
|
||||
{
|
||||
// Give keyboard back.
|
||||
ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index));
|
||||
kbd->keyboard_fd = kbd->console_fd;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
SDL_free(devicePath);
|
||||
}
|
||||
else kbd->keyboard_fd = kbd->console_fd;
|
||||
}
|
||||
|
||||
return kbd;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_SHOW;
|
||||
ioctl(kbd->console_fd, CONS_MOUSECTL, &mData);
|
||||
|
||||
kbd_unregister_emerg_cleanup();
|
||||
|
||||
if (kbd->keyboard_fd >= 0) {
|
||||
/* Restore the original keyboard mode */
|
||||
ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
|
||||
close(kbd->keyboard_fd);
|
||||
if (kbd->console_fd != kbd->keyboard_fd && kbd->console_fd >= 0)
|
||||
{
|
||||
// Give back keyboard.
|
||||
ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index));
|
||||
}
|
||||
kbd->console_fd = kbd->keyboard_fd = -1;
|
||||
}
|
||||
|
||||
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, j;
|
||||
|
||||
kbd->diacr = 0;
|
||||
|
||||
for (i = 0; i < kbd->accents->n_accs; i++) {
|
||||
if (kbd->accents->acc[i].accchar == d)
|
||||
{
|
||||
for (j = 0; j < NUM_ACCENTCHARS; ++j) {
|
||||
if (kbd->accents->acc[i].map[j][0] == 0) /* end of table */
|
||||
break;
|
||||
if (kbd->accents->acc[i].map[j][0] == ch)
|
||||
return kbd->accents->acc[i].map[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == ' ' || ch == d) {
|
||||
put_utf8(kbd, d);
|
||||
return 0;
|
||||
}
|
||||
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 chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate ^= flag;
|
||||
ioctl(kbd->keyboard_fd, KDSKBSTATE, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
/*
|
||||
* Special function handlers
|
||||
*/
|
||||
|
||||
static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned int 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_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||
{
|
||||
int old_state = kbd->shift_state;
|
||||
|
||||
if (kbd->rep)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down)
|
||||
{
|
||||
keymap_t key_map;
|
||||
struct keyent_t keysym;
|
||||
unsigned int final_key_state;
|
||||
unsigned int map_from_key_sym;
|
||||
|
||||
key_map = *kbd->key_map;
|
||||
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
|
||||
kbd->rep = (down == 2);
|
||||
|
||||
if (keycode < NUM_KEYS) {
|
||||
if (keycode >= 89 && keycode <= 95) {
|
||||
/* These constitute unprintable language-related keys, so ignore them. */
|
||||
return;
|
||||
}
|
||||
if (keycode > 95)
|
||||
keycode -= 7;
|
||||
if (vc_kbd_led(kbd, ALKED) || (kbd->shift_state & 0x8))
|
||||
{
|
||||
keycode += ALTGR_OFFSET;
|
||||
}
|
||||
keysym = key_map.key[keycode];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
final_key_state = kbd->shift_state & 0x7;
|
||||
if ((keysym.flgs & FLAG_LOCK_C) && vc_kbd_led(kbd, LED_CAP))
|
||||
final_key_state ^= 0x1;
|
||||
if ((keysym.flgs & FLAG_LOCK_N) && vc_kbd_led(kbd, LED_NUM))
|
||||
final_key_state ^= 0x1;
|
||||
|
||||
map_from_key_sym = keysym.map[final_key_state];
|
||||
if ((keysym.spcl & (0x80 >> final_key_state)) || (map_from_key_sym & SPCLKEY)) {
|
||||
/* Special function.*/
|
||||
if (map_from_key_sym == 0)
|
||||
return; /* Nothing to do. */
|
||||
if (map_from_key_sym & SPCLKEY)
|
||||
map_from_key_sym &= ~SPCLKEY;
|
||||
if (map_from_key_sym >= F_ACC && map_from_key_sym <= L_ACC) {
|
||||
/* Accent function.*/
|
||||
unsigned int accent_index = map_from_key_sym - F_ACC;
|
||||
if (kbd->accents->acc[accent_index].accchar != 0) {
|
||||
k_deadunicode(kbd, kbd->accents->acc[accent_index].accchar, !down);
|
||||
}
|
||||
} else {
|
||||
switch(map_from_key_sym) {
|
||||
case ASH: /* alt/meta shift */
|
||||
k_shift(kbd, 3, down == 0);
|
||||
break;
|
||||
case LSHA: /* left shift + alt lock */
|
||||
case RSHA: /* right shift + alt lock */
|
||||
if (down == 0) chg_vc_kbd_led(kbd, ALKED);
|
||||
case LSH: /* left shift */
|
||||
case RSH: /* right shift */
|
||||
k_shift(kbd, 0, down == 0);
|
||||
break;
|
||||
case LCTRA: /* left ctrl + alt lock */
|
||||
case RCTRA: /* right ctrl + alt lock */
|
||||
if (down == 0) chg_vc_kbd_led(kbd, ALKED);
|
||||
case LCTR: /* left ctrl */
|
||||
case RCTR: /* right ctrl */
|
||||
k_shift(kbd, 1, down == 0);
|
||||
break;
|
||||
case LALTA: /* left alt + alt lock */
|
||||
case RALTA: /* right alt + alt lock */
|
||||
if (down == 0) chg_vc_kbd_led(kbd, ALKED);
|
||||
case LALT: /* left alt */
|
||||
case RALT: /* right alt */
|
||||
k_shift(kbd, 2, down == 0);
|
||||
break;
|
||||
case ALK: /* alt lock */
|
||||
if (down == 1) chg_vc_kbd_led(kbd, ALKED);
|
||||
break;
|
||||
case CLK: /* caps lock*/
|
||||
if (down == 1) chg_vc_kbd_led(kbd, CLKED);
|
||||
break;
|
||||
case NLK: /* num lock */
|
||||
if (down == 1) chg_vc_kbd_led(kbd, NLKED);
|
||||
break;
|
||||
case SLK: /* scroll lock */
|
||||
if (down == 1) chg_vc_kbd_led(kbd, SLKED);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (map_from_key_sym == '\n' || map_from_key_sym == '\r') {
|
||||
if (kbd->diacr) {
|
||||
kbd->diacr = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (map_from_key_sym >= ' ' && map_from_key_sym != 127) {
|
||||
k_self(kbd, map_from_key_sym, !down);
|
||||
}
|
||||
}
|
||||
|
||||
if (kbd->text_len > 0) {
|
||||
kbd->text[kbd->text_len] = '\0';
|
||||
SDL_SendKeyboardText(kbd->text);
|
||||
kbd->text_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_INPUT_FBSDKBIO */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+67
-18
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -19,7 +19,9 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* we never link directly to libdbus. */
|
||||
@@ -57,6 +59,10 @@ LoadDBUSSyms(void)
|
||||
SDL_DBUS_SYM(message_new_method_call);
|
||||
SDL_DBUS_SYM(message_append_args);
|
||||
SDL_DBUS_SYM(message_append_args_valist);
|
||||
SDL_DBUS_SYM(message_iter_init_append);
|
||||
SDL_DBUS_SYM(message_iter_open_container);
|
||||
SDL_DBUS_SYM(message_iter_append_basic);
|
||||
SDL_DBUS_SYM(message_iter_close_container);
|
||||
SDL_DBUS_SYM(message_get_args);
|
||||
SDL_DBUS_SYM(message_get_args_valist);
|
||||
SDL_DBUS_SYM(message_iter_init);
|
||||
@@ -65,6 +71,7 @@ LoadDBUSSyms(void)
|
||||
SDL_DBUS_SYM(message_iter_get_arg_type);
|
||||
SDL_DBUS_SYM(message_iter_recurse);
|
||||
SDL_DBUS_SYM(message_unref);
|
||||
SDL_DBUS_SYM(threads_init_default);
|
||||
SDL_DBUS_SYM(error_init);
|
||||
SDL_DBUS_SYM(error_is_set);
|
||||
SDL_DBUS_SYM(error_free);
|
||||
@@ -108,26 +115,61 @@ LoadDBUSLibrary(void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Init(void)
|
||||
|
||||
static SDL_SpinLock spinlock_dbus_init = 0;
|
||||
|
||||
/* you must hold spinlock_dbus_init before calling this! */
|
||||
static void
|
||||
SDL_DBus_Init_Spinlocked(void)
|
||||
{
|
||||
if (!dbus.session_conn && LoadDBUSLibrary() != -1) {
|
||||
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;
|
||||
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 (LoadDBUSLibrary() == -1) {
|
||||
is_dbus_available = SDL_FALSE; /* can't load at all? Don't keep trying. */
|
||||
return; /* oh well */
|
||||
}
|
||||
|
||||
if (!dbus.threads_init_default()) {
|
||||
is_dbus_available = SDL_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
dbus.error_init(&err);
|
||||
/* session bus is required */
|
||||
|
||||
dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &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);
|
||||
|
||||
/* system bus is optional */
|
||||
dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err);
|
||||
if (!dbus.error_is_set(&err)) {
|
||||
dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
|
||||
}
|
||||
|
||||
dbus.error_free(&err);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Init(void)
|
||||
{
|
||||
SDL_AtomicLock(&spinlock_dbus_init); /* make sure two threads can't init at same time, since this can happen before SDL_Init. */
|
||||
SDL_DBus_Init_Spinlocked();
|
||||
SDL_AtomicUnlock(&spinlock_dbus_init);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Quit(void)
|
||||
{
|
||||
@@ -154,15 +196,11 @@ SDL_DBus_Quit(void)
|
||||
SDL_DBusContext *
|
||||
SDL_DBus_GetContext(void)
|
||||
{
|
||||
if(!dbus_handle || !dbus.session_conn){
|
||||
if (!dbus_handle || !dbus.session_conn) {
|
||||
SDL_DBus_Init();
|
||||
}
|
||||
|
||||
if(dbus_handle && dbus.session_conn){
|
||||
return &dbus;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return (dbus_handle && dbus.session_conn) ? &dbus : NULL;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
@@ -310,7 +348,11 @@ SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface
|
||||
void
|
||||
SDL_DBus_ScreensaverTickle(void)
|
||||
{
|
||||
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
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
|
||||
@@ -324,8 +366,15 @@ SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
const char *interface = "org.freedesktop.ScreenSaver";
|
||||
|
||||
if (inhibit) {
|
||||
const char *app = "My SDL application";
|
||||
const char *reason = "Playing a game";
|
||||
const char *app = SDL_GetHint(SDL_HINT_APP_NAME);
|
||||
const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME);
|
||||
if (!app || !app[0]) {
|
||||
app = "My SDL application";
|
||||
}
|
||||
if (!reason || !reason[0]) {
|
||||
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)) {
|
||||
|
||||
+6
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -54,6 +54,10 @@ typedef struct SDL_DBusContext {
|
||||
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);
|
||||
void (*message_iter_init_append)(DBusMessage *, DBusMessageIter *);
|
||||
dbus_bool_t (*message_iter_open_container)(DBusMessageIter *, int, const char *, DBusMessageIter *);
|
||||
dbus_bool_t (*message_iter_append_basic)(DBusMessageIter *, int, const void *);
|
||||
dbus_bool_t (*message_iter_close_container)(DBusMessageIter *, DBusMessageIter *);
|
||||
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 *);
|
||||
@@ -62,6 +66,7 @@ typedef struct SDL_DBusContext {
|
||||
int (*message_iter_get_arg_type)(DBusMessageIter *);
|
||||
void (*message_iter_recurse)(DBusMessageIter *, DBusMessageIter *);
|
||||
void (*message_unref)(DBusMessage *);
|
||||
dbus_bool_t (*threads_init_default)(void);
|
||||
void (*error_init)(DBusError *);
|
||||
dbus_bool_t (*error_is_set)(const DBusError *);
|
||||
void (*error_free)(DBusError *);
|
||||
|
||||
+158
-30
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -39,11 +39,11 @@
|
||||
#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_evdev_capabilities.h"
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
|
||||
/* These are not defined in older Linux kernel headers */
|
||||
@@ -55,6 +55,11 @@
|
||||
#define ABS_MT_POSITION_X 0x35
|
||||
#define ABS_MT_POSITION_Y 0x36
|
||||
#define ABS_MT_TRACKING_ID 0x39
|
||||
#define ABS_MT_PRESSURE 0x3a
|
||||
#endif
|
||||
#ifndef REL_WHEEL_HI_RES
|
||||
#define REL_WHEEL_HI_RES 0x0b
|
||||
#define REL_HWHEEL_HI_RES 0x0c
|
||||
#endif
|
||||
|
||||
typedef struct SDL_evdevlist_item
|
||||
@@ -74,6 +79,7 @@ typedef struct SDL_evdevlist_item
|
||||
|
||||
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;
|
||||
@@ -85,10 +91,14 @@ typedef struct SDL_evdevlist_item
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE
|
||||
} delta;
|
||||
int tracking_id;
|
||||
int x, y;
|
||||
int x, y, pressure;
|
||||
} * slots;
|
||||
|
||||
} * touchscreen_data;
|
||||
|
||||
SDL_bool high_res_wheel;
|
||||
SDL_bool high_res_hwheel;
|
||||
|
||||
struct SDL_evdevlist_item *next;
|
||||
} SDL_evdevlist_item;
|
||||
|
||||
@@ -126,6 +136,14 @@ static Uint8 EVDEV_MouseButtons[] = {
|
||||
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)
|
||||
{
|
||||
@@ -159,6 +177,8 @@ SDL_EVDEV_Init(void)
|
||||
_this->kbd = SDL_EVDEV_kbd_init();
|
||||
}
|
||||
|
||||
SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
|
||||
|
||||
_this->ref_count += 1;
|
||||
|
||||
return 0;
|
||||
@@ -205,8 +225,14 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl
|
||||
|
||||
switch(udev_event) {
|
||||
case SDL_UDEV_DEVICEADDED:
|
||||
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
|
||||
SDL_UDEV_DEVICE_TOUCHSCREEN)))
|
||||
if (udev_class & SDL_UDEV_DEVICE_TOUCHPAD) {
|
||||
udev_class |= SDL_UDEV_DEVICE_TOUCHSCREEN;
|
||||
}
|
||||
|
||||
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD | SDL_UDEV_DEVICE_TOUCHSCREEN)))
|
||||
return;
|
||||
|
||||
if ((udev_class & SDL_UDEV_DEVICE_JOYSTICK))
|
||||
return;
|
||||
|
||||
SDL_EVDEV_device_added(dev_path, udev_class);
|
||||
@@ -229,7 +255,7 @@ SDL_EVDEV_Poll(void)
|
||||
SDL_Scancode scan_code;
|
||||
int mouse_button;
|
||||
SDL_Mouse *mouse;
|
||||
float norm_x, norm_y;
|
||||
float norm_x, norm_y, norm_pressure;
|
||||
|
||||
if (!_this) {
|
||||
return;
|
||||
@@ -264,6 +290,20 @@ SDL_EVDEV_Poll(void)
|
||||
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) {
|
||||
@@ -308,15 +348,29 @@ SDL_EVDEV_Poll(void)
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_X:
|
||||
if (item->is_touchscreen) /* FIXME: temp hack */
|
||||
case ABS_MT_PRESSURE:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
|
||||
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) /* FIXME: temp hack */
|
||||
break;
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
|
||||
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;
|
||||
@@ -331,10 +385,20 @@ SDL_EVDEV_Poll(void)
|
||||
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);
|
||||
if (!item->high_res_wheel)
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
case REL_WHEEL_HI_RES:
|
||||
SDL_assert(item->high_res_wheel);
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value / 120.0f, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
if (!item->high_res_hwheel)
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
case REL_HWHEEL_HI_RES:
|
||||
SDL_assert(item->high_res_hwheel);
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value / 120.0f, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -352,18 +416,29 @@ SDL_EVDEV_Poll(void)
|
||||
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, SDL_TRUE, norm_x, norm_y, 1.0f);
|
||||
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, SDL_FALSE, norm_x, norm_y, 1.0f);
|
||||
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, norm_x, norm_y, 1.0f);
|
||||
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:
|
||||
@@ -394,13 +469,20 @@ SDL_EVDEV_translate_keycode(int keycode)
|
||||
{
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
|
||||
if (keycode < SDL_arraysize(linux_scancode_table))
|
||||
if (keycode < SDL_arraysize(linux_scancode_table)) {
|
||||
scancode = linux_scancode_table[keycode];
|
||||
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
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);
|
||||
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;
|
||||
@@ -411,6 +493,7 @@ 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;
|
||||
|
||||
@@ -433,7 +516,24 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
|
||||
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);
|
||||
@@ -443,7 +543,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
item->touchscreen_data->max_x = abs_info.maximum;
|
||||
item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
|
||||
ret = ioctl(item->fd, yreq, &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
@@ -453,13 +553,15 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
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_SLOT), &abs_info);
|
||||
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->max_slots = abs_info.maximum + 1;
|
||||
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,
|
||||
@@ -475,6 +577,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -512,8 +615,8 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
||||
*
|
||||
* this is the structure we're trying to emulate
|
||||
*/
|
||||
__u32* mt_req_code;
|
||||
__s32* mt_req_values;
|
||||
Uint32* mt_req_code;
|
||||
Sint32* mt_req_values;
|
||||
size_t mt_req_size;
|
||||
|
||||
/* TODO: sync devices other than touchscreen */
|
||||
@@ -528,7 +631,7 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
||||
return;
|
||||
}
|
||||
|
||||
mt_req_values = (__s32*)mt_req_code + 1;
|
||||
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);
|
||||
@@ -593,6 +696,24 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
||||
}
|
||||
}
|
||||
|
||||
*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);
|
||||
@@ -611,6 +732,7 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
{
|
||||
int ret;
|
||||
SDL_evdevlist_item *item;
|
||||
unsigned long relbit[NBITS(REL_MAX)] = { 0 };
|
||||
|
||||
/* Check to make sure it's not already in list. */
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
@@ -624,7 +746,7 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
|
||||
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (item->fd < 0) {
|
||||
SDL_free(item);
|
||||
return SDL_SetError("Unable to open %s", dev_path);
|
||||
@@ -637,11 +759,17 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
if (ioctl(item->fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) {
|
||||
item->high_res_wheel = test_bit(REL_WHEEL_HI_RES, relbit);
|
||||
item->high_res_hwheel = test_bit(REL_HWHEEL_HI_RES, relbit);
|
||||
}
|
||||
|
||||
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->path);
|
||||
SDL_free(item);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 2020 Collabora Ltd.
|
||||
|
||||
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_evdev_capabilities.h"
|
||||
|
||||
#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)
|
||||
|
||||
/* missing defines in older Linux kernel headers */
|
||||
#ifndef BTN_TRIGGER_HAPPY
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#endif
|
||||
#ifndef BTN_DPAD_UP
|
||||
#define BTN_DPAD_UP 0x220
|
||||
#endif
|
||||
#ifndef KEY_ALS_TOGGLE
|
||||
#define KEY_ALS_TOGGLE 0x230
|
||||
#endif
|
||||
|
||||
extern int
|
||||
SDL_EVDEV_GuessDeviceClass(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)])
|
||||
{
|
||||
struct range {
|
||||
unsigned start;
|
||||
unsigned end;
|
||||
};
|
||||
|
||||
/* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/
|
||||
static const struct range high_key_blocks[] = {
|
||||
{ KEY_OK, BTN_DPAD_UP },
|
||||
{ KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
|
||||
};
|
||||
|
||||
int devclass = 0;
|
||||
unsigned long keyboard_mask;
|
||||
|
||||
/* X, Y, Z axes but no buttons probably means an accelerometer */
|
||||
if (test_bit(EV_ABS, bitmask_ev) &&
|
||||
test_bit(ABS_X, bitmask_abs) &&
|
||||
test_bit(ABS_Y, bitmask_abs) &&
|
||||
test_bit(ABS_Z, bitmask_abs) &&
|
||||
!test_bit(EV_KEY, bitmask_ev)) {
|
||||
return SDL_UDEV_DEVICE_ACCELEROMETER;
|
||||
}
|
||||
|
||||
/* RX, RY, RZ axes but no buttons also probably means an accelerometer */
|
||||
if (test_bit(EV_ABS, bitmask_ev) &&
|
||||
test_bit(ABS_RX, bitmask_abs) &&
|
||||
test_bit(ABS_RY, bitmask_abs) &&
|
||||
test_bit(ABS_RZ, bitmask_abs) &&
|
||||
!test_bit(EV_KEY, bitmask_ev)) {
|
||||
return SDL_UDEV_DEVICE_ACCELEROMETER;
|
||||
}
|
||||
|
||||
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)) {
|
||||
devclass |= SDL_UDEV_DEVICE_TOUCHPAD; /* 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 */
|
||||
}
|
||||
|
||||
if (test_bit(EV_KEY, bitmask_ev)) {
|
||||
unsigned i;
|
||||
unsigned long found = 0;
|
||||
|
||||
for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) {
|
||||
found |= bitmask_key[i];
|
||||
}
|
||||
/* If there are no keys in the lower block, check the higher blocks */
|
||||
if (!found) {
|
||||
unsigned block;
|
||||
for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) {
|
||||
for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) {
|
||||
if (test_bit(i, bitmask_key)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found > 0) {
|
||||
devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEY */
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 2020 Collabora Ltd.
|
||||
|
||||
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_capabilities_h_
|
||||
#define SDL_evdev_capabilities_h_
|
||||
|
||||
#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
/* 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_DEVICE_ACCELEROMETER = 0x0020,
|
||||
SDL_UDEV_DEVICE_TOUCHPAD = 0x0040
|
||||
} SDL_UDEV_deviceclass;
|
||||
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
|
||||
#define EVDEV_OFF(x) ((x)%BITS_PER_LONG)
|
||||
#define EVDEV_LONG(x) ((x)/BITS_PER_LONG)
|
||||
#define test_bit(bit, array) ((array[EVDEV_LONG(bit)] >> EVDEV_OFF(bit)) & 1)
|
||||
|
||||
extern int SDL_EVDEV_GuessDeviceClass(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)]);
|
||||
|
||||
#endif /* HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX) */
|
||||
|
||||
#endif /* SDL_evdev_capabilities_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+13
-11
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -216,11 +216,10 @@ static void kbd_cleanup(void)
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
|
||||
fprintf(stderr, "(SDL restoring keyboard) ");
|
||||
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
SDL_EVDEV_kbd_reraise_signal(int sig)
|
||||
{
|
||||
raise(sig);
|
||||
@@ -345,7 +344,7 @@ SDL_EVDEV_kbd_init(void)
|
||||
SDL_EVDEV_keyboard_state *kbd;
|
||||
int i;
|
||||
char flag_state;
|
||||
char shift_state[2] = {TIOCL_GETSHIFTSTATE, 0};
|
||||
char shift_state[ sizeof (long) ] = {TIOCL_GETSHIFTSTATE, 0};
|
||||
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
|
||||
if (!kbd) {
|
||||
@@ -355,7 +354,7 @@ SDL_EVDEV_kbd_init(void)
|
||||
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);
|
||||
kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
|
||||
kbd->shift_state = *shift_state;
|
||||
@@ -387,7 +386,7 @@ SDL_EVDEV_kbd_init(void)
|
||||
}
|
||||
|
||||
/* Allow inhibiting keyboard mute with env. variable for debugging etc. */
|
||||
if (getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
|
||||
if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
|
||||
/* Mute the keyboard so keystrokes only generate evdev events
|
||||
* and do not leak through to the console
|
||||
*/
|
||||
@@ -510,17 +509,19 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
|
||||
|
||||
static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
return ((kbd->ledflagstate >> flag) & 1);
|
||||
return (kbd->ledflagstate & flag) != 0;
|
||||
}
|
||||
|
||||
static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate |= 1 << 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 &= ~(1 << 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)
|
||||
@@ -535,7 +536,8 @@ static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
|
||||
static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate ^= 1 << flag;
|
||||
kbd->ledflagstate ^= flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -817,7 +819,7 @@ SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int d
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !SDL_INPUT_LINUXKD */
|
||||
#elif !defined(SDL_INPUT_FBSDKBIO) /* !SDL_INPUT_LINUXKD */
|
||||
|
||||
SDL_EVDEV_keyboard_state *
|
||||
SDL_EVDEV_kbd_init(void)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
+148
-91
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -20,9 +20,6 @@
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
|
||||
#include <fcitx/frontend.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "SDL_fcitx.h"
|
||||
@@ -36,23 +33,20 @@
|
||||
#endif
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
|
||||
#define FCITX_DBUS_SERVICE "org.freedesktop.portal.Fcitx"
|
||||
|
||||
#define FCITX_IM_DBUS_PATH "/inputmethod"
|
||||
#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
|
||||
#define FCITX_IM_DBUS_PATH "/org/freedesktop/portal/inputmethod"
|
||||
|
||||
#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
|
||||
#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
|
||||
#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod1"
|
||||
#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext1"
|
||||
|
||||
#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];
|
||||
char *ic_path;
|
||||
|
||||
int id;
|
||||
|
||||
@@ -61,34 +55,6 @@ typedef struct _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()
|
||||
{
|
||||
@@ -118,6 +84,55 @@ GetAppName()
|
||||
return SDL_strdup("SDL_App");
|
||||
}
|
||||
|
||||
static size_t
|
||||
Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
|
||||
char *text = NULL, *subtext;
|
||||
size_t text_bytes = 0;
|
||||
DBusMessageIter iter, array, sub;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
/* Message type is a(si)i, we only need string part */
|
||||
if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
|
||||
/* First pass: calculate string length */
|
||||
dbus->message_iter_recurse(&iter, &array);
|
||||
while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
|
||||
dbus->message_iter_recurse(&array, &sub);
|
||||
if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
|
||||
dbus->message_iter_get_basic(&sub, &subtext);
|
||||
if (subtext && *subtext) {
|
||||
text_bytes += SDL_strlen(subtext);
|
||||
}
|
||||
}
|
||||
dbus->message_iter_next(&array);
|
||||
}
|
||||
if (text_bytes) {
|
||||
text = SDL_malloc(text_bytes + 1);
|
||||
}
|
||||
|
||||
if (text) {
|
||||
char* pivot = text;
|
||||
/* Second pass: join all the sub string */
|
||||
dbus->message_iter_recurse(&iter, &array);
|
||||
while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
|
||||
dbus->message_iter_recurse(&array, &sub);
|
||||
if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
|
||||
dbus->message_iter_get_basic(&sub, &subtext);
|
||||
if (subtext && *subtext) {
|
||||
size_t length = SDL_strlen(subtext);
|
||||
SDL_strlcpy(pivot, subtext, length + 1);
|
||||
pivot += length;
|
||||
}
|
||||
}
|
||||
dbus->message_iter_next(&array);
|
||||
}
|
||||
} else {
|
||||
text_bytes = 0;
|
||||
}
|
||||
}
|
||||
*ret= text;
|
||||
return text_bytes;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -130,22 +145,27 @@ DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
dbus->message_iter_get_basic(&iter, &text);
|
||||
|
||||
if (text)
|
||||
SDL_SendKeyboardText(text);
|
||||
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, 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) {
|
||||
if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdateFormattedPreedit")) {
|
||||
char *text = NULL;
|
||||
size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text);
|
||||
if (text_bytes) {
|
||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
size_t i = 0;
|
||||
size_t cursor = 0;
|
||||
|
||||
while (i < text_bytes) {
|
||||
@@ -157,6 +177,9 @@ DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||
i += sz;
|
||||
cursor += chars;
|
||||
}
|
||||
SDL_free(text);
|
||||
} else {
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
}
|
||||
|
||||
SDL_Fcitx_UpdateTextRect(NULL);
|
||||
@@ -169,7 +192,10 @@ DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||
static void
|
||||
FcitxClientICCallMethod(FcitxClient *client, const char *method)
|
||||
{
|
||||
SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
|
||||
if (!client->ic_path) {
|
||||
return;
|
||||
}
|
||||
SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
@@ -179,40 +205,68 @@ Fcitx_SetCapabilities(void *data,
|
||||
const char *internal_editing)
|
||||
{
|
||||
FcitxClient *client = (FcitxClient *)data;
|
||||
Uint32 caps = CAPACITY_NONE;
|
||||
|
||||
if (!(internal_editing && *internal_editing == '1')) {
|
||||
caps |= CAPACITY_PREEDIT;
|
||||
Uint64 caps = 0;
|
||||
if (!client->ic_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
|
||||
if (!(internal_editing && *internal_editing == '1')) {
|
||||
caps |= (1 << 1); /* Preedit Flag */
|
||||
caps |= (1 << 4); /* Formatted Preedit Flag */
|
||||
}
|
||||
|
||||
SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, "SetCapability", DBUS_TYPE_UINT64, &caps, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
FcitxCreateInputContext(SDL_DBusContext* dbus, const char *appname, char **ic_path) {
|
||||
const char *program = "program";
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
if (dbus->session_conn) {
|
||||
DBusMessage *msg = dbus->message_new_method_call(FCITX_DBUS_SERVICE, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateInputContext");
|
||||
if (msg) {
|
||||
DBusMessage *reply = NULL;
|
||||
DBusMessageIter args, array, sub;
|
||||
dbus->message_iter_init_append(msg, &args);
|
||||
dbus->message_iter_open_container(&args, DBUS_TYPE_ARRAY, "(ss)", &array);
|
||||
dbus->message_iter_open_container(&array, DBUS_TYPE_STRUCT, 0, &sub);
|
||||
dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &program);
|
||||
dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &appname);
|
||||
dbus->message_iter_close_container(&array, &sub);
|
||||
dbus->message_iter_close_container(&args, &array);
|
||||
reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
if (dbus->message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, ic_path, DBUS_TYPE_INVALID)) {
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
dbus->message_unref(reply);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
FcitxClientCreateIC(FcitxClient *client)
|
||||
{
|
||||
char *appname = GetAppName();
|
||||
pid_t pid = getpid();
|
||||
int id = -1;
|
||||
Uint32 enable, arg1, arg2, arg3, arg4;
|
||||
char *ic_path = NULL;
|
||||
SDL_DBusContext *dbus = client->dbus;
|
||||
|
||||
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_DBus_CallMethod cannot handle a(ss) type, call dbus function directly */
|
||||
if (!FcitxCreateInputContext(dbus, appname, &ic_path)) {
|
||||
ic_path = NULL; /* 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);
|
||||
if (ic_path) {
|
||||
SDL_free(client->ic_path);
|
||||
client->ic_path = SDL_strdup(ic_path);
|
||||
|
||||
dbus->bus_add_match(dbus->session_conn,
|
||||
"type='signal', interface='org.fcitx.Fcitx.InputContext'",
|
||||
"type='signal', interface='org.fcitx.Fcitx.InputContext1'",
|
||||
NULL);
|
||||
dbus->connection_add_filter(dbus->session_conn,
|
||||
&DBus_MessageFilter, dbus,
|
||||
@@ -232,13 +286,14 @@ 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;
|
||||
if (sdl_mods & KMOD_SHIFT) fcitx_mods |= (1 << 0);
|
||||
if (sdl_mods & KMOD_CAPS) fcitx_mods |= (1 << 1);
|
||||
if (sdl_mods & KMOD_CTRL) fcitx_mods |= (1 << 2);
|
||||
if (sdl_mods & KMOD_ALT) fcitx_mods |= (1 << 3);
|
||||
if (sdl_mods & KMOD_NUM) fcitx_mods |= (1 << 4);
|
||||
if (sdl_mods & KMOD_MODE) fcitx_mods |= (1 << 7);
|
||||
if (sdl_mods & KMOD_LGUI) fcitx_mods |= (1 << 6);
|
||||
if (sdl_mods & KMOD_RGUI) fcitx_mods |= (1 << 28);
|
||||
|
||||
return fcitx_mods;
|
||||
}
|
||||
@@ -253,10 +308,6 @@ SDL_Fcitx_Init()
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -264,6 +315,10 @@ void
|
||||
SDL_Fcitx_Quit()
|
||||
{
|
||||
FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
|
||||
if (fcitx_client.ic_path) {
|
||||
SDL_free(fcitx_client.ic_path);
|
||||
fcitx_client.ic_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -284,16 +339,20 @@ SDL_Fcitx_Reset(void)
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
|
||||
{
|
||||
Uint32 state = Fcitx_ModState();
|
||||
Uint32 mod_state = Fcitx_ModState();
|
||||
Uint32 handled = SDL_FALSE;
|
||||
int type = FCITX_PRESS_KEY;
|
||||
Uint32 is_release = (state == SDL_RELEASED);
|
||||
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 (!fcitx_client.ic_path) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
|
||||
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
|
||||
if (handled) {
|
||||
SDL_Fcitx_UpdateTextRect(NULL);
|
||||
return SDL_TRUE;
|
||||
@@ -350,7 +409,7 @@ SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
|
||||
x += cursor->x;
|
||||
y += cursor->y;
|
||||
|
||||
SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
|
||||
SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, 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);
|
||||
}
|
||||
|
||||
@@ -368,6 +427,4 @@ SDL_Fcitx_PumpEvents(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_FCITX_FRONTEND_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -31,7 +31,7 @@ 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 SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
|
||||
extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
|
||||
extern void SDL_Fcitx_PumpEvents(void);
|
||||
|
||||
|
||||
+16
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -257,7 +257,12 @@ IBus_GetDBusAddressFilename(void)
|
||||
}
|
||||
|
||||
if (!*host) {
|
||||
host = "unix";
|
||||
const char *session = SDL_getenv("XDG_SESSION_TYPE");
|
||||
if (session != NULL && SDL_strcmp(session, "wayland") == 0) {
|
||||
host = "unix-wayland";
|
||||
} else {
|
||||
host = "unix";
|
||||
}
|
||||
}
|
||||
|
||||
SDL_memset(config_dir, 0, sizeof(config_dir));
|
||||
@@ -479,7 +484,7 @@ IBus_SimpleMessage(const char *method)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
if ((input_ctx_path != NULL) && (IBus_CheckConnection(dbus))) {
|
||||
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
@@ -498,15 +503,20 @@ SDL_IBus_Reset(void)
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
|
||||
{
|
||||
Uint32 result = 0;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
Uint32 mods = IBus_ModState();
|
||||
Uint32 ibus_keycode = keycode - 8;
|
||||
if (state == SDL_RELEASED) {
|
||||
mods |= (1 << 30); // IBUS_RELEASE_MASK
|
||||
}
|
||||
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_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -41,7 +41,7 @@ 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);
|
||||
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
|
||||
|
||||
/* 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. */
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -23,13 +23,13 @@
|
||||
#include "SDL_ibus.h"
|
||||
#include "SDL_fcitx.h"
|
||||
|
||||
typedef SDL_bool (*_SDL_IME_Init)();
|
||||
typedef void (*_SDL_IME_Quit)();
|
||||
typedef SDL_bool (*_SDL_IME_Init)(void);
|
||||
typedef void (*_SDL_IME_Quit)(void);
|
||||
typedef void (*_SDL_IME_SetFocus)(SDL_bool);
|
||||
typedef void (*_SDL_IME_Reset)();
|
||||
typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
|
||||
typedef void (*_SDL_IME_Reset)(void);
|
||||
typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32, Uint8 state);
|
||||
typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
|
||||
typedef void (*_SDL_IME_PumpEvents)();
|
||||
typedef void (*_SDL_IME_PumpEvents)(void);
|
||||
|
||||
static _SDL_IME_Init SDL_IME_Init_Real = NULL;
|
||||
static _SDL_IME_Quit SDL_IME_Quit_Real = NULL;
|
||||
@@ -43,7 +43,7 @@ static void
|
||||
InitIME()
|
||||
{
|
||||
static SDL_bool inited = SDL_FALSE;
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
#ifdef HAVE_FCITX
|
||||
const char *im_module = SDL_getenv("SDL_IM_MODULE");
|
||||
const char *xmodifiers = SDL_getenv("XMODIFIERS");
|
||||
#endif
|
||||
@@ -54,7 +54,7 @@ InitIME()
|
||||
inited = SDL_TRUE;
|
||||
|
||||
/* See if fcitx IME support is being requested */
|
||||
#ifdef HAVE_FCITX_FRONTEND_H
|
||||
#ifdef HAVE_FCITX
|
||||
if (!SDL_IME_Init_Real &&
|
||||
((im_module && SDL_strcmp(im_module, "fcitx") == 0) ||
|
||||
(!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) {
|
||||
@@ -66,7 +66,7 @@ InitIME()
|
||||
SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect;
|
||||
SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents;
|
||||
}
|
||||
#endif /* HAVE_FCITX_FRONTEND_H */
|
||||
#endif /* HAVE_FCITX */
|
||||
|
||||
/* default to IBus */
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
@@ -127,10 +127,10 @@ SDL_IME_Reset(void)
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
|
||||
{
|
||||
if (SDL_IME_ProcessKeyEvent_Real)
|
||||
return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
|
||||
return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state);
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -31,7 +31,7 @@ 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 SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
|
||||
extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
|
||||
extern void SDL_IME_PumpEvents(void);
|
||||
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#if !SDL_THREADS_DISABLED
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <pthread.h>
|
||||
#include "SDL_system.h"
|
||||
|
||||
/* RLIMIT_RTTIME requires kernel >= 2.6.25 and is in glibc >= 2.14 */
|
||||
#ifndef RLIMIT_RTTIME
|
||||
#define RLIMIT_RTTIME 15
|
||||
#endif
|
||||
/* SCHED_RESET_ON_FORK is in kernel >= 2.6.32. */
|
||||
#ifndef SCHED_RESET_ON_FORK
|
||||
#define SCHED_RESET_ON_FORK 0x40000000
|
||||
#endif
|
||||
|
||||
#include "SDL_dbus.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
#include <sched.h>
|
||||
|
||||
/* 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 Sint32 rtkit_max_realtime_priority = 99;
|
||||
static Sint64 rtkit_max_rttime_usec = 200000;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Try getting maximum realtime priority: this can be less than the POSIX default (99). */
|
||||
if (!dbus || !SDL_DBus_QueryPropertyOnConnection(dbus->system_conn, RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MaxRealtimePriority",
|
||||
DBUS_TYPE_INT32, &rtkit_max_realtime_priority)) {
|
||||
rtkit_max_realtime_priority = 99;
|
||||
}
|
||||
|
||||
/* Try getting maximum rttime allowed by rtkit: exceeding this value will result in SIGKILL */
|
||||
if (!dbus || !SDL_DBus_QueryPropertyOnConnection(dbus->system_conn, RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "RTTimeUSecMax",
|
||||
DBUS_TYPE_INT64, &rtkit_max_rttime_usec)) {
|
||||
rtkit_max_rttime_usec = 200000;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
rtkit_initialize_realtime_thread()
|
||||
{
|
||||
// Following is an excerpt from rtkit README that outlines the requirements
|
||||
// a thread must meet before making rtkit requests:
|
||||
//
|
||||
// * Only clients with RLIMIT_RTTIME set will get RT scheduling
|
||||
//
|
||||
// * RT scheduling will only be handed out to processes with
|
||||
// SCHED_RESET_ON_FORK set to guarantee that the scheduling
|
||||
// settings cannot 'leak' to child processes, thus making sure
|
||||
// that 'RT fork bombs' cannot be used to bypass RLIMIT_RTTIME
|
||||
// and take the system down.
|
||||
//
|
||||
// * Limits are enforced on all user controllable resources, only
|
||||
// a maximum number of users, processes, threads can request RT
|
||||
// scheduling at the same time.
|
||||
//
|
||||
// * Only a limited number of threads may be made RT in a
|
||||
// specific time frame.
|
||||
//
|
||||
// * Client authorization is verified with PolicyKit
|
||||
|
||||
int err;
|
||||
struct rlimit rlimit;
|
||||
int nLimit = RLIMIT_RTTIME;
|
||||
pid_t nPid = 0; //self
|
||||
int nSchedPolicy = sched_getscheduler(nPid) | SCHED_RESET_ON_FORK;
|
||||
struct sched_param schedParam;
|
||||
|
||||
SDL_zero(schedParam);
|
||||
|
||||
// Requirement #1: Set RLIMIT_RTTIME
|
||||
err = getrlimit(nLimit, &rlimit);
|
||||
if (err)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// Current rtkit allows a max of 200ms right now
|
||||
rlimit.rlim_max = rtkit_max_rttime_usec;
|
||||
rlimit.rlim_cur = rlimit.rlim_max / 2;
|
||||
err = setrlimit(nLimit, &rlimit);
|
||||
if (err)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// Requirement #2: Add SCHED_RESET_ON_FORK to the scheduler policy
|
||||
err = sched_getparam(nPid, &schedParam);
|
||||
if (err)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
err = sched_setscheduler(nPid, nSchedPolicy, &schedParam);
|
||||
if (err)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
rtkit_setpriority_nice(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;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
rtkit_setpriority_realtime(pid_t thread, int rt_priority)
|
||||
{
|
||||
Uint64 ui64 = (Uint64)thread;
|
||||
Uint32 ui32 = (Uint32)rt_priority;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
pthread_once(&rtkit_initialize_once, rtkit_initialize);
|
||||
|
||||
if (ui32 > rtkit_max_realtime_priority)
|
||||
ui32 = rtkit_max_realtime_priority;
|
||||
|
||||
// We always perform the thread state changes necessary for rtkit.
|
||||
// This wastes some system calls if the state is already set but
|
||||
// typically code sets a thread priority and leaves it so it's
|
||||
// not expected that this wasted effort will be an issue.
|
||||
// We also do not quit if this fails, we let the rtkit request
|
||||
// go through to determine whether it really needs to fail or not.
|
||||
rtkit_initialize_realtime_thread();
|
||||
|
||||
if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn,
|
||||
RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MakeThreadRealtime",
|
||||
DBUS_TYPE_UINT64, &ui64, DBUS_TYPE_UINT32, &ui32, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#else
|
||||
|
||||
#define rtkit_max_realtime_priority 99
|
||||
|
||||
#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_nice((pid_t)threadID, priority)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_SetError("setpriority() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* this is a public symbol, so it has to exist even if threads are disabled. */
|
||||
int
|
||||
SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return SDL_Unsupported();
|
||||
#else
|
||||
int osPriority;
|
||||
|
||||
if (schedPolicy == SCHED_RR || schedPolicy == SCHED_FIFO) {
|
||||
if (sdlPriority == SDL_THREAD_PRIORITY_LOW) {
|
||||
osPriority = 1;
|
||||
} else if (sdlPriority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
osPriority = rtkit_max_realtime_priority * 3 / 4;
|
||||
} else if (sdlPriority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
|
||||
osPriority = rtkit_max_realtime_priority;
|
||||
} else {
|
||||
osPriority = rtkit_max_realtime_priority / 2;
|
||||
}
|
||||
} else {
|
||||
if (sdlPriority == SDL_THREAD_PRIORITY_LOW) {
|
||||
osPriority = 19;
|
||||
} else if (sdlPriority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
osPriority = -10;
|
||||
} else if (sdlPriority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
|
||||
osPriority = -20;
|
||||
} else {
|
||||
osPriority = 0;
|
||||
}
|
||||
|
||||
if (setpriority(PRIO_PROCESS, (id_t)threadID, osPriority) == 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 (schedPolicy == SCHED_RR || schedPolicy == SCHED_FIFO) {
|
||||
if (rtkit_setpriority_realtime((pid_t)threadID, osPriority)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (rtkit_setpriority_nice((pid_t)threadID, osPriority)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_SetError("setpriority() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __LINUX__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+116
-100
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -19,7 +19,7 @@
|
||||
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)
|
||||
@@ -32,8 +32,10 @@
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_evdev_capabilities.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" };
|
||||
@@ -101,7 +103,7 @@ 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)) {
|
||||
if (SDL_IOReady(fd, SDL_IOR_READ, 0)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -113,23 +115,23 @@ 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
|
||||
|
||||
/* 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();
|
||||
@@ -141,18 +143,18 @@ SDL_UDEV_Init(void)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -160,15 +162,15 @@ 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;
|
||||
@@ -177,14 +179,14 @@ SDL_UDEV_Quit(void)
|
||||
_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;
|
||||
@@ -196,22 +198,22 @@ SDL_UDEV_Scan(void)
|
||||
{
|
||||
struct udev_enumerate *enumerate = NULL;
|
||||
struct udev_list_entry *devs = NULL;
|
||||
struct udev_list_entry *item = 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)) {
|
||||
@@ -226,6 +228,62 @@ SDL_UDEV_Scan(void)
|
||||
_this->syms.udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version)
|
||||
{
|
||||
struct udev_enumerate *enumerate = NULL;
|
||||
struct udev_list_entry *devs = NULL;
|
||||
struct udev_list_entry *item = NULL;
|
||||
SDL_bool found = SDL_FALSE;
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
enumerate = _this->syms.udev_enumerate_new(_this->udev);
|
||||
if (enumerate == NULL) {
|
||||
SDL_SetError("udev_enumerate_new() failed");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
_this->syms.udev_enumerate_scan_devices(enumerate);
|
||||
devs = _this->syms.udev_enumerate_get_list_entry(enumerate);
|
||||
for (item = devs; item && !found; 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) {
|
||||
const char *val = NULL;
|
||||
const char *existing_path;
|
||||
|
||||
existing_path = _this->syms.udev_device_get_devnode(dev);
|
||||
if (existing_path && SDL_strcmp(device_path, existing_path) == 0) {
|
||||
found = SDL_TRUE;
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID");
|
||||
if (val != NULL) {
|
||||
*vendor = (Uint16)SDL_strtol(val, NULL, 16);
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_MODEL_ID");
|
||||
if (val != NULL) {
|
||||
*product = (Uint16)SDL_strtol(val, NULL, 16);
|
||||
}
|
||||
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_REVISION");
|
||||
if (val != NULL) {
|
||||
*version = (Uint16)SDL_strtol(val, NULL, 16);
|
||||
}
|
||||
}
|
||||
_this->syms.udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
_this->syms.udev_enumerate_unref(enumerate);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
SDL_UDEV_UnloadLibrary(void)
|
||||
@@ -233,7 +291,7 @@ SDL_UDEV_UnloadLibrary(void)
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_this->udev_handle != NULL) {
|
||||
SDL_UnloadObject(_this->udev_handle);
|
||||
_this->udev_handle = NULL;
|
||||
@@ -244,11 +302,11 @@ 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;
|
||||
@@ -280,7 +338,7 @@ SDL_UDEV_LoadLibrary(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_this->udev_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
@@ -290,12 +348,6 @@ SDL_UDEV_LoadLibrary(void)
|
||||
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;
|
||||
@@ -329,13 +381,11 @@ static void get_caps(struct udev_device *dev, struct udev_device *pdev, const ch
|
||||
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 */
|
||||
@@ -352,80 +402,48 @@ guess_device_class(struct udev_device *dev)
|
||||
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;
|
||||
return SDL_EVDEV_GuessDeviceClass(&bitmask_ev[0],
|
||||
&bitmask_abs[0],
|
||||
&bitmask_key[0],
|
||||
&bitmask_rel[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
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;
|
||||
@@ -434,7 +452,7 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
/* 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");
|
||||
@@ -463,14 +481,14 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Process callbacks */
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
item->callback(type, devclass, path);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
SDL_UDEV_Poll(void)
|
||||
{
|
||||
struct udev_device *dev = NULL;
|
||||
@@ -487,20 +505,19 @@ SDL_UDEV_Poll(void)
|
||||
}
|
||||
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);
|
||||
if (action) {
|
||||
if (SDL_strcmp(action, "add") == 0) {
|
||||
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
|
||||
int
|
||||
SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
||||
{
|
||||
SDL_UDEV_CallbackList *item;
|
||||
@@ -508,7 +525,7 @@ SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
||||
if (item == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
|
||||
item->callback = cb;
|
||||
|
||||
if (_this->last == NULL) {
|
||||
@@ -517,11 +534,11 @@ SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
||||
_this->last->next = item;
|
||||
_this->last = item;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
||||
{
|
||||
SDL_UDEV_CallbackList *item;
|
||||
@@ -544,7 +561,6 @@ SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
||||
}
|
||||
prev = item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const SDL_UDEV_Symbols *
|
||||
|
||||
+2
-12
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -46,17 +46,6 @@ typedef enum
|
||||
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 {
|
||||
@@ -112,6 +101,7 @@ 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 SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version);
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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.
|
||||
*/
|
||||
|
||||
|
||||
void SDL_WSCONS_Init();
|
||||
void SDL_WSCONS_Quit();
|
||||
|
||||
void SDL_WSCONS_PumpEvents();
|
||||
|
||||
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 <dev/wscons/wsksymvar.h>
|
||||
#include <dev/wscons/wsksymdef.h>
|
||||
#include "SDL_scancode.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_keyboard.h"
|
||||
#include "SDL_wscons.h"
|
||||
#include "SDL_log.h"
|
||||
#include <sys/time.h>
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <dev/wscons/wsdisplay_usl_io.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define KS_GROUP_Ascii KS_GROUP_Plain
|
||||
#define KS_Cmd_ScrollBack KS_Cmd_ScrollFastUp
|
||||
#define KS_Cmd_ScrollFwd KS_Cmd_ScrollFastDown
|
||||
#endif
|
||||
|
||||
#define RETIFIOCTLERR(x) if (x == -1) { free(input); input = NULL; return NULL;}
|
||||
|
||||
typedef struct SDL_WSCONS_mouse_input_data SDL_WSCONS_mouse_input_data;
|
||||
extern SDL_WSCONS_mouse_input_data* SDL_WSCONS_Init_Mouse();
|
||||
extern void updateMouse(SDL_WSCONS_mouse_input_data* input);
|
||||
extern void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data* input);
|
||||
|
||||
/* Conversion table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */
|
||||
static const unsigned char latin1_to_upper[256] = {
|
||||
/* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
|
||||
0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */
|
||||
'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */
|
||||
};
|
||||
|
||||
/* Compose table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */
|
||||
static struct SDL_wscons_compose_tab_s {
|
||||
keysym_t elem[2];
|
||||
keysym_t result;
|
||||
} compose_tab[] = {
|
||||
{ { KS_plus, KS_plus }, KS_numbersign },
|
||||
{ { KS_a, KS_a }, KS_at },
|
||||
{ { KS_parenleft, KS_parenleft }, KS_bracketleft },
|
||||
{ { KS_slash, KS_slash }, KS_backslash },
|
||||
{ { KS_parenright, KS_parenright }, KS_bracketright },
|
||||
{ { KS_parenleft, KS_minus }, KS_braceleft },
|
||||
{ { KS_slash, KS_minus }, KS_bar },
|
||||
{ { KS_parenright, KS_minus }, KS_braceright },
|
||||
{ { KS_exclam, KS_exclam }, KS_exclamdown },
|
||||
{ { KS_c, KS_slash }, KS_cent },
|
||||
{ { KS_l, KS_minus }, KS_sterling },
|
||||
{ { KS_y, KS_minus }, KS_yen },
|
||||
{ { KS_s, KS_o }, KS_section },
|
||||
{ { KS_x, KS_o }, KS_currency },
|
||||
{ { KS_c, KS_o }, KS_copyright },
|
||||
{ { KS_less, KS_less }, KS_guillemotleft },
|
||||
{ { KS_greater, KS_greater }, KS_guillemotright },
|
||||
{ { KS_question, KS_question }, KS_questiondown },
|
||||
{ { KS_dead_acute, KS_space }, KS_apostrophe },
|
||||
{ { KS_dead_grave, KS_space }, KS_grave },
|
||||
{ { KS_dead_tilde, KS_space }, KS_asciitilde },
|
||||
{ { KS_dead_circumflex, KS_space }, KS_asciicircum },
|
||||
{ { KS_dead_diaeresis, KS_space }, KS_quotedbl },
|
||||
{ { KS_dead_cedilla, KS_space }, KS_comma },
|
||||
{ { KS_dead_circumflex, KS_A }, KS_Acircumflex },
|
||||
{ { KS_dead_diaeresis, KS_A }, KS_Adiaeresis },
|
||||
{ { KS_dead_grave, KS_A }, KS_Agrave },
|
||||
{ { KS_dead_abovering, KS_A }, KS_Aring },
|
||||
{ { KS_dead_tilde, KS_A }, KS_Atilde },
|
||||
{ { KS_dead_cedilla, KS_C }, KS_Ccedilla },
|
||||
{ { KS_dead_acute, KS_E }, KS_Eacute },
|
||||
{ { KS_dead_circumflex, KS_E }, KS_Ecircumflex },
|
||||
{ { KS_dead_diaeresis, KS_E }, KS_Ediaeresis },
|
||||
{ { KS_dead_grave, KS_E }, KS_Egrave },
|
||||
{ { KS_dead_acute, KS_I }, KS_Iacute },
|
||||
{ { KS_dead_circumflex, KS_I }, KS_Icircumflex },
|
||||
{ { KS_dead_diaeresis, KS_I }, KS_Idiaeresis },
|
||||
{ { KS_dead_grave, KS_I }, KS_Igrave },
|
||||
{ { KS_dead_tilde, KS_N }, KS_Ntilde },
|
||||
{ { KS_dead_acute, KS_O }, KS_Oacute },
|
||||
{ { KS_dead_circumflex, KS_O }, KS_Ocircumflex },
|
||||
{ { KS_dead_diaeresis, KS_O }, KS_Odiaeresis },
|
||||
{ { KS_dead_grave, KS_O }, KS_Ograve },
|
||||
{ { KS_dead_tilde, KS_O }, KS_Otilde },
|
||||
{ { KS_dead_acute, KS_U }, KS_Uacute },
|
||||
{ { KS_dead_circumflex, KS_U }, KS_Ucircumflex },
|
||||
{ { KS_dead_diaeresis, KS_U }, KS_Udiaeresis },
|
||||
{ { KS_dead_grave, KS_U }, KS_Ugrave },
|
||||
{ { KS_dead_acute, KS_Y }, KS_Yacute },
|
||||
{ { KS_dead_acute, KS_a }, KS_aacute },
|
||||
{ { KS_dead_circumflex, KS_a }, KS_acircumflex },
|
||||
{ { KS_dead_diaeresis, KS_a }, KS_adiaeresis },
|
||||
{ { KS_dead_grave, KS_a }, KS_agrave },
|
||||
{ { KS_dead_abovering, KS_a }, KS_aring },
|
||||
{ { KS_dead_tilde, KS_a }, KS_atilde },
|
||||
{ { KS_dead_cedilla, KS_c }, KS_ccedilla },
|
||||
{ { KS_dead_acute, KS_e }, KS_eacute },
|
||||
{ { KS_dead_circumflex, KS_e }, KS_ecircumflex },
|
||||
{ { KS_dead_diaeresis, KS_e }, KS_ediaeresis },
|
||||
{ { KS_dead_grave, KS_e }, KS_egrave },
|
||||
{ { KS_dead_acute, KS_i }, KS_iacute },
|
||||
{ { KS_dead_circumflex, KS_i }, KS_icircumflex },
|
||||
{ { KS_dead_diaeresis, KS_i }, KS_idiaeresis },
|
||||
{ { KS_dead_grave, KS_i }, KS_igrave },
|
||||
{ { KS_dead_tilde, KS_n }, KS_ntilde },
|
||||
{ { KS_dead_acute, KS_o }, KS_oacute },
|
||||
{ { KS_dead_circumflex, KS_o }, KS_ocircumflex },
|
||||
{ { KS_dead_diaeresis, KS_o }, KS_odiaeresis },
|
||||
{ { KS_dead_grave, KS_o }, KS_ograve },
|
||||
{ { KS_dead_tilde, KS_o }, KS_otilde },
|
||||
{ { KS_dead_acute, KS_u }, KS_uacute },
|
||||
{ { KS_dead_circumflex, KS_u }, KS_ucircumflex },
|
||||
{ { KS_dead_diaeresis, KS_u }, KS_udiaeresis },
|
||||
{ { KS_dead_grave, KS_u }, KS_ugrave },
|
||||
{ { KS_dead_acute, KS_y }, KS_yacute },
|
||||
{ { KS_dead_diaeresis, KS_y }, KS_ydiaeresis },
|
||||
{ { KS_quotedbl, KS_A }, KS_Adiaeresis },
|
||||
{ { KS_quotedbl, KS_E }, KS_Ediaeresis },
|
||||
{ { KS_quotedbl, KS_I }, KS_Idiaeresis },
|
||||
{ { KS_quotedbl, KS_O }, KS_Odiaeresis },
|
||||
{ { KS_quotedbl, KS_U }, KS_Udiaeresis },
|
||||
{ { KS_quotedbl, KS_a }, KS_adiaeresis },
|
||||
{ { KS_quotedbl, KS_e }, KS_ediaeresis },
|
||||
{ { KS_quotedbl, KS_i }, KS_idiaeresis },
|
||||
{ { KS_quotedbl, KS_o }, KS_odiaeresis },
|
||||
{ { KS_quotedbl, KS_u }, KS_udiaeresis },
|
||||
{ { KS_quotedbl, KS_y }, KS_ydiaeresis },
|
||||
{ { KS_acute, KS_A }, KS_Aacute },
|
||||
{ { KS_asciicircum, KS_A }, KS_Acircumflex },
|
||||
{ { KS_grave, KS_A }, KS_Agrave },
|
||||
{ { KS_asterisk, KS_A }, KS_Aring },
|
||||
{ { KS_asciitilde, KS_A }, KS_Atilde },
|
||||
{ { KS_cedilla, KS_C }, KS_Ccedilla },
|
||||
{ { KS_acute, KS_E }, KS_Eacute },
|
||||
{ { KS_asciicircum, KS_E }, KS_Ecircumflex },
|
||||
{ { KS_grave, KS_E }, KS_Egrave },
|
||||
{ { KS_acute, KS_I }, KS_Iacute },
|
||||
{ { KS_asciicircum, KS_I }, KS_Icircumflex },
|
||||
{ { KS_grave, KS_I }, KS_Igrave },
|
||||
{ { KS_asciitilde, KS_N }, KS_Ntilde },
|
||||
{ { KS_acute, KS_O }, KS_Oacute },
|
||||
{ { KS_asciicircum, KS_O }, KS_Ocircumflex },
|
||||
{ { KS_grave, KS_O }, KS_Ograve },
|
||||
{ { KS_asciitilde, KS_O }, KS_Otilde },
|
||||
{ { KS_acute, KS_U }, KS_Uacute },
|
||||
{ { KS_asciicircum, KS_U }, KS_Ucircumflex },
|
||||
{ { KS_grave, KS_U }, KS_Ugrave },
|
||||
{ { KS_acute, KS_Y }, KS_Yacute },
|
||||
{ { KS_acute, KS_a }, KS_aacute },
|
||||
{ { KS_asciicircum, KS_a }, KS_acircumflex },
|
||||
{ { KS_grave, KS_a }, KS_agrave },
|
||||
{ { KS_asterisk, KS_a }, KS_aring },
|
||||
{ { KS_asciitilde, KS_a }, KS_atilde },
|
||||
{ { KS_cedilla, KS_c }, KS_ccedilla },
|
||||
{ { KS_acute, KS_e }, KS_eacute },
|
||||
{ { KS_asciicircum, KS_e }, KS_ecircumflex },
|
||||
{ { KS_grave, KS_e }, KS_egrave },
|
||||
{ { KS_acute, KS_i }, KS_iacute },
|
||||
{ { KS_asciicircum, KS_i }, KS_icircumflex },
|
||||
{ { KS_grave, KS_i }, KS_igrave },
|
||||
{ { KS_asciitilde, KS_n }, KS_ntilde },
|
||||
{ { KS_acute, KS_o }, KS_oacute },
|
||||
{ { KS_asciicircum, KS_o }, KS_ocircumflex },
|
||||
{ { KS_grave, KS_o }, KS_ograve },
|
||||
{ { KS_asciitilde, KS_o }, KS_otilde },
|
||||
{ { KS_acute, KS_u }, KS_uacute },
|
||||
{ { KS_asciicircum, KS_u }, KS_ucircumflex },
|
||||
{ { KS_grave, KS_u }, KS_ugrave },
|
||||
{ { KS_acute, KS_y }, KS_yacute },
|
||||
#ifndef __NetBSD__
|
||||
{ { KS_dead_caron, KS_space }, KS_L2_caron },
|
||||
{ { KS_dead_caron, KS_S }, KS_L2_Scaron },
|
||||
{ { KS_dead_caron, KS_Z }, KS_L2_Zcaron },
|
||||
{ { KS_dead_caron, KS_s }, KS_L2_scaron },
|
||||
{ { KS_dead_caron, KS_z }, KS_L2_zcaron }
|
||||
#endif
|
||||
};
|
||||
|
||||
static keysym_t ksym_upcase(keysym_t ksym)
|
||||
{
|
||||
if (ksym >= KS_f1 && ksym <= KS_f20)
|
||||
return(KS_F1 - KS_f1 + ksym);
|
||||
|
||||
if (KS_GROUP(ksym) == KS_GROUP_Ascii && ksym <= 0xff &&
|
||||
latin1_to_upper[ksym] != 0x00)
|
||||
return(latin1_to_upper[ksym]);
|
||||
|
||||
return(ksym);
|
||||
}
|
||||
static struct wscons_keycode_to_SDL {
|
||||
keysym_t sourcekey;
|
||||
SDL_Scancode targetKey;
|
||||
} conversion_table[] = {
|
||||
{KS_Menu, SDL_SCANCODE_APPLICATION},
|
||||
{KS_Up, SDL_SCANCODE_UP},
|
||||
{KS_Down, SDL_SCANCODE_DOWN},
|
||||
{KS_Left, SDL_SCANCODE_LEFT},
|
||||
{KS_Right, SDL_SCANCODE_RIGHT},
|
||||
{KS_Hold_Screen, SDL_SCANCODE_SCROLLLOCK},
|
||||
{KS_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR},
|
||||
{KS_Caps_Lock, SDL_SCANCODE_CAPSLOCK},
|
||||
{KS_BackSpace, SDL_SCANCODE_BACKSPACE},
|
||||
{KS_space, SDL_SCANCODE_SPACE},
|
||||
{KS_Delete, SDL_SCANCODE_BACKSPACE},
|
||||
{KS_Home, SDL_SCANCODE_HOME},
|
||||
{KS_End, SDL_SCANCODE_END},
|
||||
{KS_Pause, SDL_SCANCODE_PAUSE},
|
||||
{KS_Print_Screen, SDL_SCANCODE_PRINTSCREEN},
|
||||
{KS_Insert, SDL_SCANCODE_INSERT},
|
||||
{KS_Escape, SDL_SCANCODE_ESCAPE},
|
||||
{KS_Return, SDL_SCANCODE_RETURN},
|
||||
{KS_Linefeed, SDL_SCANCODE_RETURN},
|
||||
{KS_KP_Delete, SDL_SCANCODE_DELETE},
|
||||
{KS_KP_Insert, SDL_SCANCODE_INSERT},
|
||||
{KS_Control_L, SDL_SCANCODE_LCTRL},
|
||||
{KS_Control_R, SDL_SCANCODE_RCTRL},
|
||||
{KS_Shift_L, SDL_SCANCODE_LSHIFT},
|
||||
{KS_Shift_R, SDL_SCANCODE_RSHIFT},
|
||||
{KS_Alt_L, SDL_SCANCODE_LALT},
|
||||
{KS_Alt_R, SDL_SCANCODE_RALT},
|
||||
{KS_grave, SDL_SCANCODE_GRAVE},
|
||||
|
||||
{KS_KP_0, SDL_SCANCODE_KP_0},
|
||||
{KS_KP_1, SDL_SCANCODE_KP_1},
|
||||
{KS_KP_2, SDL_SCANCODE_KP_2},
|
||||
{KS_KP_3, SDL_SCANCODE_KP_3},
|
||||
{KS_KP_4, SDL_SCANCODE_KP_4},
|
||||
{KS_KP_5, SDL_SCANCODE_KP_5},
|
||||
{KS_KP_6, SDL_SCANCODE_KP_6},
|
||||
{KS_KP_7, SDL_SCANCODE_KP_7},
|
||||
{KS_KP_8, SDL_SCANCODE_KP_8},
|
||||
{KS_KP_9, SDL_SCANCODE_KP_9},
|
||||
{KS_KP_Enter, SDL_SCANCODE_KP_ENTER},
|
||||
{KS_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY},
|
||||
{KS_KP_Add, SDL_SCANCODE_KP_PLUS},
|
||||
{KS_KP_Subtract, SDL_SCANCODE_KP_MINUS},
|
||||
{KS_KP_Divide, SDL_SCANCODE_KP_DIVIDE},
|
||||
{KS_KP_Up, SDL_SCANCODE_UP},
|
||||
{KS_KP_Down, SDL_SCANCODE_DOWN},
|
||||
{KS_KP_Left, SDL_SCANCODE_LEFT},
|
||||
{KS_KP_Right, SDL_SCANCODE_RIGHT},
|
||||
{KS_KP_Equal, SDL_SCANCODE_KP_EQUALS},
|
||||
{KS_f1, SDL_SCANCODE_F1},
|
||||
{KS_f2, SDL_SCANCODE_F2},
|
||||
{KS_f3, SDL_SCANCODE_F3},
|
||||
{KS_f4, SDL_SCANCODE_F4},
|
||||
{KS_f5, SDL_SCANCODE_F5},
|
||||
{KS_f6, SDL_SCANCODE_F6},
|
||||
{KS_f7, SDL_SCANCODE_F7},
|
||||
{KS_f8, SDL_SCANCODE_F8},
|
||||
{KS_f9, SDL_SCANCODE_F9},
|
||||
{KS_f10, SDL_SCANCODE_F10},
|
||||
{KS_f11, SDL_SCANCODE_F11},
|
||||
{KS_f12, SDL_SCANCODE_F12},
|
||||
{KS_f13, SDL_SCANCODE_F13},
|
||||
{KS_f14, SDL_SCANCODE_F14},
|
||||
{KS_f15, SDL_SCANCODE_F15},
|
||||
{KS_f16, SDL_SCANCODE_F16},
|
||||
{KS_f17, SDL_SCANCODE_F17},
|
||||
{KS_f18, SDL_SCANCODE_F18},
|
||||
{KS_f19, SDL_SCANCODE_F19},
|
||||
{KS_f20, SDL_SCANCODE_F20},
|
||||
#if !defined(__NetBSD__)
|
||||
{KS_f21, SDL_SCANCODE_F21},
|
||||
{KS_f22, SDL_SCANCODE_F22},
|
||||
{KS_f23, SDL_SCANCODE_F23},
|
||||
{KS_f24, SDL_SCANCODE_F24},
|
||||
#endif
|
||||
{KS_Meta_L, SDL_SCANCODE_LGUI},
|
||||
{KS_Meta_R, SDL_SCANCODE_RGUI},
|
||||
{KS_Zenkaku_Hankaku, SDL_SCANCODE_LANG5},
|
||||
{KS_Hiragana_Katakana, SDL_SCANCODE_INTERNATIONAL2},
|
||||
{KS_yen, SDL_SCANCODE_INTERNATIONAL3},
|
||||
{KS_Henkan, SDL_SCANCODE_INTERNATIONAL4},
|
||||
{KS_Muhenkan, SDL_SCANCODE_INTERNATIONAL5},
|
||||
{KS_KP_Prior, SDL_SCANCODE_PRIOR},
|
||||
|
||||
{KS_a, SDL_SCANCODE_A},
|
||||
{KS_b, SDL_SCANCODE_B},
|
||||
{KS_c, SDL_SCANCODE_C},
|
||||
{KS_d, SDL_SCANCODE_D},
|
||||
{KS_e, SDL_SCANCODE_E},
|
||||
{KS_f, SDL_SCANCODE_F},
|
||||
{KS_g, SDL_SCANCODE_G},
|
||||
{KS_h, SDL_SCANCODE_H},
|
||||
{KS_i, SDL_SCANCODE_I},
|
||||
{KS_j, SDL_SCANCODE_J},
|
||||
{KS_k, SDL_SCANCODE_K},
|
||||
{KS_l, SDL_SCANCODE_L},
|
||||
{KS_m, SDL_SCANCODE_M},
|
||||
{KS_n, SDL_SCANCODE_N},
|
||||
{KS_o, SDL_SCANCODE_O},
|
||||
{KS_p, SDL_SCANCODE_P},
|
||||
{KS_q, SDL_SCANCODE_Q},
|
||||
{KS_r, SDL_SCANCODE_R},
|
||||
{KS_s, SDL_SCANCODE_S},
|
||||
{KS_t, SDL_SCANCODE_T},
|
||||
{KS_u, SDL_SCANCODE_U},
|
||||
{KS_v, SDL_SCANCODE_V},
|
||||
{KS_w, SDL_SCANCODE_W},
|
||||
{KS_x, SDL_SCANCODE_X},
|
||||
{KS_y, SDL_SCANCODE_Y},
|
||||
{KS_z, SDL_SCANCODE_Z},
|
||||
|
||||
{KS_0, SDL_SCANCODE_0},
|
||||
{KS_1, SDL_SCANCODE_1},
|
||||
{KS_2, SDL_SCANCODE_2},
|
||||
{KS_3, SDL_SCANCODE_3},
|
||||
{KS_4, SDL_SCANCODE_4},
|
||||
{KS_5, SDL_SCANCODE_5},
|
||||
{KS_6, SDL_SCANCODE_6},
|
||||
{KS_7, SDL_SCANCODE_7},
|
||||
{KS_8, SDL_SCANCODE_8},
|
||||
{KS_9, SDL_SCANCODE_9},
|
||||
{KS_minus, SDL_SCANCODE_MINUS},
|
||||
{KS_equal, SDL_SCANCODE_EQUALS},
|
||||
{KS_Tab, SDL_SCANCODE_TAB},
|
||||
{KS_KP_Tab, SDL_SCANCODE_KP_TAB},
|
||||
{KS_apostrophe, SDL_SCANCODE_APOSTROPHE},
|
||||
{KS_bracketleft, SDL_SCANCODE_LEFTBRACKET},
|
||||
{KS_bracketright, SDL_SCANCODE_RIGHTBRACKET},
|
||||
{KS_semicolon, SDL_SCANCODE_SEMICOLON},
|
||||
{KS_comma, SDL_SCANCODE_COMMA},
|
||||
{KS_period, SDL_SCANCODE_PERIOD},
|
||||
{KS_slash, SDL_SCANCODE_SLASH},
|
||||
{KS_backslash, SDL_SCANCODE_BACKSLASH}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
struct wskbd_map_data keymap;
|
||||
int ledstate;
|
||||
int origledstate;
|
||||
int shiftstate[4];
|
||||
int shiftheldstate[8];
|
||||
int lockheldstate[5];
|
||||
kbd_t encoding;
|
||||
char text[128];
|
||||
unsigned int text_len;
|
||||
keysym_t composebuffer[2];
|
||||
unsigned char composelen;
|
||||
int type;
|
||||
} SDL_WSCONS_input_data;
|
||||
|
||||
static SDL_WSCONS_input_data* inputs[4] = {NULL, NULL, NULL, NULL};
|
||||
static SDL_WSCONS_mouse_input_data* mouseInputData = NULL;
|
||||
#define IS_CONTROL_HELD (input->shiftstate[2] > 0)
|
||||
#define IS_ALT_HELD (input->shiftstate[1] > 0)
|
||||
#define IS_SHIFT_HELD ((input->shiftstate[0] > 0) || (input->ledstate & (1 << 5)))
|
||||
|
||||
#define IS_ALTGR_MODE ((input->ledstate & (1 << 4)) || (input->shiftstate[3] > 0))
|
||||
#define IS_NUMLOCK_ON (input->ledstate & LED_NUM)
|
||||
#define IS_SCROLLLOCK_ON (input->ledstate & LED_SCR)
|
||||
#define IS_CAPSLOCK_ON (input->ledstate & LED_CAP)
|
||||
static SDL_WSCONS_input_data* SDL_WSCONS_Init_Keyboard(const char* dev)
|
||||
{
|
||||
#ifdef WSKBDIO_SETVERSION
|
||||
int version = WSKBDIO_EVENT_VERSION;
|
||||
#endif
|
||||
SDL_WSCONS_input_data* input = (SDL_WSCONS_input_data*)SDL_calloc(1, sizeof(SDL_WSCONS_input_data));
|
||||
|
||||
if (!input) {
|
||||
return input;
|
||||
}
|
||||
input->fd = open(dev,O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
||||
if (input->fd == -1) {
|
||||
free(input);
|
||||
input = NULL;
|
||||
return NULL;
|
||||
}
|
||||
input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES);
|
||||
if (input->keymap.map == NULL) {
|
||||
free(input);
|
||||
return NULL;
|
||||
}
|
||||
input->keymap.maplen = KS_NUMKEYCODES;
|
||||
RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETMAP, &input->keymap));
|
||||
RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETLEDS, &input->ledstate));
|
||||
input->origledstate = input->ledstate;
|
||||
RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETENCODING, &input->encoding));
|
||||
RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GTYPE, &input->type));
|
||||
#ifdef WSKBDIO_SETVERSION
|
||||
RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_SETVERSION, &version));
|
||||
#endif
|
||||
return input;
|
||||
}
|
||||
|
||||
void SDL_WSCONS_Init()
|
||||
{
|
||||
inputs[0] = SDL_WSCONS_Init_Keyboard("/dev/wskbd0");
|
||||
inputs[1] = SDL_WSCONS_Init_Keyboard("/dev/wskbd1");
|
||||
inputs[2] = SDL_WSCONS_Init_Keyboard("/dev/wskbd2");
|
||||
inputs[3] = SDL_WSCONS_Init_Keyboard("/dev/wskbd3");
|
||||
|
||||
mouseInputData = SDL_WSCONS_Init_Mouse();
|
||||
return;
|
||||
}
|
||||
|
||||
void SDL_WSCONS_Quit()
|
||||
{
|
||||
int i = 0;
|
||||
SDL_WSCONS_input_data* input = NULL;
|
||||
|
||||
SDL_WSCONS_Quit_Mouse(mouseInputData);
|
||||
mouseInputData = NULL;
|
||||
for (i = 0; i < 4; i++) {
|
||||
input = inputs[i];
|
||||
if (input) {
|
||||
if (input->fd != -1 && input->fd != 0) {
|
||||
ioctl(input->fd,WSKBDIO_SETLEDS, &input->origledstate);
|
||||
close(input->fd);
|
||||
input->fd = -1;
|
||||
}
|
||||
free(input);
|
||||
input = NULL;
|
||||
}
|
||||
inputs[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void put_queue(SDL_WSCONS_input_data *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_WSCONS_input_data* input, uint c)
|
||||
{
|
||||
if (c < 0x80)
|
||||
/* 0******* */
|
||||
put_queue(input, c);
|
||||
else if (c < 0x800) {
|
||||
/* 110***** 10****** */
|
||||
put_queue(input, 0xc0 | (c >> 6));
|
||||
put_queue(input, 0x80 | (c & 0x3f));
|
||||
} else if (c < 0x10000) {
|
||||
if (c >= 0xD800 && c <= 0xF500)
|
||||
return;
|
||||
if (c == 0xFFFF)
|
||||
return;
|
||||
/* 1110**** 10****** 10****** */
|
||||
put_queue(input, 0xe0 | (c >> 12));
|
||||
put_queue(input, 0x80 | ((c >> 6) & 0x3f));
|
||||
put_queue(input, 0x80 | (c & 0x3f));
|
||||
} else if (c < 0x110000) {
|
||||
/* 11110*** 10****** 10****** 10****** */
|
||||
put_queue(input, 0xf0 | (c >> 18));
|
||||
put_queue(input, 0x80 | ((c >> 12) & 0x3f));
|
||||
put_queue(input, 0x80 | ((c >> 6) & 0x3f));
|
||||
put_queue(input, 0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
static void Translate_to_text(SDL_WSCONS_input_data* input, keysym_t ksym)
|
||||
{
|
||||
if (KS_GROUP(ksym) == KS_GROUP_Keypad) {
|
||||
if (SDL_isprint(ksym & 0xFF)) ksym &= 0xFF;
|
||||
}
|
||||
switch(ksym) {
|
||||
case KS_Escape:
|
||||
case KS_Delete:
|
||||
case KS_BackSpace:
|
||||
case KS_Return:
|
||||
case KS_Linefeed:
|
||||
/* All of these are unprintable characters. Ignore them */
|
||||
break;
|
||||
default:
|
||||
put_utf8(input, ksym);
|
||||
break;
|
||||
}
|
||||
if (input->text_len > 0) {
|
||||
input->text[input->text_len] = '\0';
|
||||
SDL_SendKeyboardText(input->text);
|
||||
/*SDL_memset(input->text, 0, sizeof(input->text));*/
|
||||
input->text_len = 0;
|
||||
input->text[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void Translate_to_keycode(SDL_WSCONS_input_data* input, int type, keysym_t ksym)
|
||||
{
|
||||
struct wscons_keymap keyDesc = input->keymap.map[ksym];
|
||||
keysym_t* group = &keyDesc.group1[KS_GROUP(keyDesc.group1[0]) == KS_GROUP_Keypad && IS_NUMLOCK_ON ? !IS_SHIFT_HELD : 0];
|
||||
int i = 0;
|
||||
|
||||
/* Check command first, then group[0]*/
|
||||
switch (keyDesc.command) {
|
||||
case KS_Cmd_ScrollBack: {
|
||||
SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP);
|
||||
return;
|
||||
}
|
||||
case KS_Cmd_ScrollFwd: {
|
||||
SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sizeof(conversion_table) / sizeof(struct wscons_keycode_to_SDL); i++) {
|
||||
if (conversion_table[i].sourcekey == group[0]) {
|
||||
SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN);
|
||||
|
||||
}
|
||||
|
||||
static void updateKeyboard(SDL_WSCONS_input_data* input)
|
||||
{
|
||||
struct wscons_event events[64];
|
||||
int type;
|
||||
int n,i,gindex,acc_i;
|
||||
keysym_t *group;
|
||||
keysym_t ksym, result;
|
||||
|
||||
if (!input) return;
|
||||
if ((n = read(input->fd, events, sizeof(events))) > 0) {
|
||||
n /= sizeof(struct wscons_event);
|
||||
for (i = 0; i < n; i++) {
|
||||
type = events[i].type;
|
||||
switch(type) {
|
||||
case WSCONS_EVENT_KEY_DOWN: {
|
||||
switch (input->keymap.map[events[i].value].group1[0]) {
|
||||
case KS_Hold_Screen: {
|
||||
if (input->lockheldstate[0] >= 1) break;
|
||||
input->ledstate ^= LED_SCR;
|
||||
ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->lockheldstate[0] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Num_Lock: {
|
||||
if (input->lockheldstate[1] >= 1) break;
|
||||
input->ledstate ^= LED_NUM;
|
||||
ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->lockheldstate[1] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Caps_Lock: {
|
||||
if (input->lockheldstate[2] >= 1) break;
|
||||
input->ledstate ^= LED_CAP;
|
||||
ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->lockheldstate[2] = 1;
|
||||
break;
|
||||
}
|
||||
#ifndef __NetBSD__
|
||||
case KS_Mode_Lock: {
|
||||
if (input->lockheldstate[3] >= 1) break;
|
||||
input->ledstate ^= 1 << 4;
|
||||
ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->lockheldstate[3] = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case KS_Shift_Lock: {
|
||||
if (input->lockheldstate[4] >= 1) break;
|
||||
input->ledstate ^= 1 << 5;
|
||||
ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->lockheldstate[4] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Shift_L: {
|
||||
if (input->shiftheldstate[0]) break;
|
||||
input->shiftstate[0]++;
|
||||
input->shiftheldstate[0] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Shift_R: {
|
||||
if (input->shiftheldstate[1]) break;
|
||||
input->shiftstate[0]++;
|
||||
input->shiftheldstate[1] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Alt_L: {
|
||||
if (input->shiftheldstate[2]) break;
|
||||
input->shiftstate[1]++;
|
||||
input->shiftheldstate[2] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Alt_R: {
|
||||
if (input->shiftheldstate[3]) break;
|
||||
input->shiftstate[1]++;
|
||||
input->shiftheldstate[3] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Control_L: {
|
||||
if (input->shiftheldstate[4]) break;
|
||||
input->shiftstate[2]++;
|
||||
input->shiftheldstate[4] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Control_R: {
|
||||
if (input->shiftheldstate[5]) break;
|
||||
input->shiftstate[2]++;
|
||||
input->shiftheldstate[5] = 1;
|
||||
break;
|
||||
}
|
||||
case KS_Mode_switch: {
|
||||
if (input->shiftheldstate[6]) break;
|
||||
input->shiftstate[3]++;
|
||||
input->shiftheldstate[6] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WSCONS_EVENT_KEY_UP: {
|
||||
switch(input->keymap.map[events[i].value].group1[0]) {
|
||||
case KS_Hold_Screen: {
|
||||
if (input->lockheldstate[0]) input->lockheldstate[0] = 0;
|
||||
}
|
||||
break;
|
||||
case KS_Num_Lock: {
|
||||
if (input->lockheldstate[1]) input->lockheldstate[1] = 0;
|
||||
}
|
||||
break;
|
||||
case KS_Caps_Lock: {
|
||||
if (input->lockheldstate[2]) input->lockheldstate[2] = 0;
|
||||
}
|
||||
break;
|
||||
#ifndef __NetBSD__
|
||||
case KS_Mode_Lock: {
|
||||
if (input->lockheldstate[3]) input->lockheldstate[3] = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case KS_Shift_Lock: {
|
||||
if (input->lockheldstate[4]) input->lockheldstate[4] = 0;
|
||||
}
|
||||
break;
|
||||
case KS_Shift_L: {
|
||||
input->shiftheldstate[0] = 0;
|
||||
if (input->shiftstate[0]) input->shiftstate[0]--;
|
||||
break;
|
||||
}
|
||||
case KS_Shift_R: {
|
||||
input->shiftheldstate[1] = 0;
|
||||
if (input->shiftstate[0]) input->shiftstate[0]--;
|
||||
break;
|
||||
}
|
||||
case KS_Alt_L: {
|
||||
input->shiftheldstate[2] = 0;
|
||||
if (input->shiftstate[1]) input->shiftstate[1]--;
|
||||
break;
|
||||
}
|
||||
case KS_Alt_R: {
|
||||
input->shiftheldstate[3] = 0;
|
||||
if (input->shiftstate[1]) input->shiftstate[1]--;
|
||||
break;
|
||||
}
|
||||
case KS_Control_L: {
|
||||
input->shiftheldstate[4] = 0;
|
||||
if (input->shiftstate[2]) input->shiftstate[2]--;
|
||||
break;
|
||||
}
|
||||
case KS_Control_R: {
|
||||
input->shiftheldstate[5] = 0;
|
||||
if (input->shiftstate[2]) input->shiftstate[2]--;
|
||||
break;
|
||||
}
|
||||
case KS_Mode_switch: {
|
||||
input->shiftheldstate[6] = 0;
|
||||
if (input->shiftstate[3]) input->shiftstate[3]--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WSCONS_EVENT_ALL_KEYS_UP:
|
||||
for (i = 0; i < SDL_NUM_SCANCODES; i++) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7)
|
||||
SDL_SendKeyboardKey(type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value);
|
||||
else
|
||||
Translate_to_keycode(input, type, events[i].value);
|
||||
|
||||
if (type == WSCONS_EVENT_KEY_UP) continue;
|
||||
|
||||
if (IS_ALTGR_MODE && !IS_CONTROL_HELD)
|
||||
group = &input->keymap.map[events[i].value].group2[0];
|
||||
else
|
||||
group = &input->keymap.map[events[i].value].group1[0];
|
||||
|
||||
if (IS_NUMLOCK_ON && KS_GROUP(group[1]) == KS_GROUP_Keypad) {
|
||||
gindex = !IS_SHIFT_HELD;
|
||||
ksym = group[gindex];
|
||||
} else {
|
||||
if (IS_CAPSLOCK_ON && !IS_SHIFT_HELD) {
|
||||
gindex = 0;
|
||||
ksym = ksym_upcase(group[0]);
|
||||
} else {
|
||||
gindex = IS_SHIFT_HELD;
|
||||
ksym = group[gindex];
|
||||
}
|
||||
}
|
||||
result = KS_voidSymbol;
|
||||
|
||||
switch (KS_GROUP(ksym)) {
|
||||
case KS_GROUP_Ascii:
|
||||
case KS_GROUP_Keypad:
|
||||
case KS_GROUP_Function:
|
||||
result = ksym;
|
||||
break;
|
||||
case KS_GROUP_Mod:
|
||||
if (ksym == KS_Multi_key) {
|
||||
input->ledstate |= WSKBD_LED_COMPOSE;
|
||||
ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->composelen = 2;
|
||||
input->composebuffer[0] = input->composebuffer[1] = 0;
|
||||
}
|
||||
break;
|
||||
case KS_GROUP_Dead:
|
||||
if (input->composelen == 0) {
|
||||
input->ledstate |= WSKBD_LED_COMPOSE;
|
||||
ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
|
||||
input->composelen = 1;
|
||||
input->composebuffer[0] = ksym;
|
||||
input->composebuffer[1] = 0;
|
||||
} else result = ksym;
|
||||
break;
|
||||
}
|
||||
if (result == KS_voidSymbol) continue;
|
||||
|
||||
if (input->composelen > 0) {
|
||||
if (input->composelen == 2 && group == &input->keymap.map[events[i].value].group2[0]) {
|
||||
if (input->keymap.map[events[i].value].group2[gindex] == input->keymap.map[events[i].value].group1[gindex]) {
|
||||
input->composelen = 0;
|
||||
input->composebuffer[0] = input->composebuffer[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (input->composelen != 0) {
|
||||
input->composebuffer[2 - input->composelen] = result;
|
||||
if (--input->composelen == 0) {
|
||||
result = KS_voidSymbol;
|
||||
input->ledstate &= ~WSKBD_LED_COMPOSE;
|
||||
ioctl(input->fd,WSKBDIO_SETLEDS, &input->ledstate);
|
||||
for (acc_i = 0; acc_i < SDL_arraysize(compose_tab); acc_i++) {
|
||||
if ((compose_tab[acc_i].elem[0] == input->composebuffer[0]
|
||||
&& compose_tab[acc_i].elem[1] == input->composebuffer[1])
|
||||
|| (compose_tab[acc_i].elem[0] == input->composebuffer[1]
|
||||
&& compose_tab[acc_i].elem[1] == input->composebuffer[0])) {
|
||||
result = compose_tab[acc_i].result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (KS_GROUP(result) == KS_GROUP_Ascii) {
|
||||
if (IS_CONTROL_HELD) {
|
||||
if ((result >= KS_at && result <= KS_z) || result == KS_space)
|
||||
result = result & 0x1f;
|
||||
else if (result == KS_2)
|
||||
result = 0x00;
|
||||
else if (result >= KS_3 && result <= KS_7)
|
||||
result = KS_Escape + (result - KS_3);
|
||||
else if (result == KS_8)
|
||||
result = KS_Delete;
|
||||
}
|
||||
if (IS_ALT_HELD) {
|
||||
if (input->encoding & KB_METAESC) {
|
||||
Translate_to_keycode(input, WSCONS_EVENT_KEY_DOWN, KS_Escape);
|
||||
Translate_to_text(input, result);
|
||||
continue;
|
||||
} else result |= 0x80;
|
||||
}
|
||||
}
|
||||
Translate_to_text(input,result);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WSCONS_PumpEvents()
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
updateKeyboard(inputs[i]);
|
||||
if (mouseInputData != NULL) updateMouse(mouseInputData);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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_events.h"
|
||||
#include <sys/time.h>
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
typedef struct SDL_WSCONS_mouse_input_data
|
||||
{
|
||||
int fd;
|
||||
} SDL_WSCONS_mouse_input_data;
|
||||
|
||||
SDL_WSCONS_mouse_input_data* SDL_WSCONS_Init_Mouse()
|
||||
{
|
||||
#ifdef WSMOUSEIO_SETVERSION
|
||||
int version = WSMOUSE_EVENT_VERSION;
|
||||
#endif
|
||||
SDL_WSCONS_mouse_input_data* mouseInputData = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data));
|
||||
|
||||
if (!mouseInputData) return NULL;
|
||||
mouseInputData->fd = open("/dev/wsmouse",O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
||||
if (mouseInputData->fd == -1) {free(mouseInputData); return NULL; }
|
||||
#ifdef WSMOUSEIO_SETMODE
|
||||
ioctl(mouseInputData->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT);
|
||||
#endif
|
||||
#ifdef WSMOUSEIO_SETVERSION
|
||||
ioctl(mouseInputData->fd, WSMOUSEIO_SETVERSION, &version);
|
||||
#endif
|
||||
return mouseInputData;
|
||||
}
|
||||
|
||||
void updateMouse(SDL_WSCONS_mouse_input_data* inputData)
|
||||
{
|
||||
struct wscons_event events[64];
|
||||
int type;
|
||||
int n,i;
|
||||
SDL_Mouse* mouse = SDL_GetMouse();
|
||||
|
||||
if ((n = read(inputData->fd, events, sizeof(events))) > 0)
|
||||
{
|
||||
n /= sizeof(struct wscons_event);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
type = events[i].type;
|
||||
switch(type)
|
||||
{
|
||||
case WSCONS_EVENT_MOUSE_DOWN:
|
||||
{
|
||||
switch (events[i].value)
|
||||
{
|
||||
case 0: /* Left Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||
break;
|
||||
case 1: /* Middle Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE);
|
||||
break;
|
||||
case 2: /* Right Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WSCONS_EVENT_MOUSE_UP:
|
||||
{
|
||||
switch (events[i].value)
|
||||
{
|
||||
case 0: /* Left Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
break;
|
||||
case 1: /* Middle Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
||||
break;
|
||||
case 2: /* Right Mouse Button. */
|
||||
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WSCONS_EVENT_MOUSE_DELTA_X:
|
||||
{
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, events[i].value, 0);
|
||||
break;
|
||||
}
|
||||
case WSCONS_EVENT_MOUSE_DELTA_Y:
|
||||
{
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, 0, -events[i].value);
|
||||
break;
|
||||
}
|
||||
case WSCONS_EVENT_MOUSE_DELTA_W:
|
||||
{
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
}
|
||||
case WSCONS_EVENT_MOUSE_DELTA_Z:
|
||||
{
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data* inputData)
|
||||
{
|
||||
if (!inputData) return;
|
||||
close(inputData->fd);
|
||||
free(inputData);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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(__OS2__)
|
||||
|
||||
#include "SDL_os2.h"
|
||||
|
||||
/* SDL_OS2Quit() will be called from SDL_QuitSubSystem() */
|
||||
void SDL_OS2Quit(void)
|
||||
{
|
||||
/* Unload DLL used for iconv. We can do it at any time and use iconv again -
|
||||
* dynamic library will be loaded on first call iconv_open() (see geniconv). */
|
||||
libiconv_clean();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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_os2_h_
|
||||
#define SDL_os2_h_
|
||||
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#ifdef OS2DEBUG
|
||||
#if (OS2DEBUG-0 >= 2)
|
||||
# define debug_os2(s,...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, \
|
||||
__func__ "(): " ##s, ##__VA_ARGS__)
|
||||
#else
|
||||
# define debug_os2(s,...) printf(__func__ "(): " ##s "\n", ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#else /* no debug */
|
||||
|
||||
# define debug_os2(s,...) do {} while (0)
|
||||
|
||||
#endif /* OS2DEBUG */
|
||||
|
||||
#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
|
||||
#define OS2_SysToUTF8(S) SDL_iconv_string("UTF-8", "", (char *)(S), SDL_strlen(S)+1)
|
||||
#define OS2_UTF8ToSys(S) SDL_iconv_string("", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#define libiconv_clean() do {} while(0)
|
||||
#else
|
||||
/* StrUTF8New() - geniconv/sys2utf8.c */
|
||||
#include "geniconv/geniconv.h"
|
||||
#define OS2_SysToUTF8(S) StrUTF8New(1, (S), SDL_strlen((S)) + 1)
|
||||
#define OS2_UTF8ToSys(S) StrUTF8New(0, (char *)(S), SDL_strlen((S)) + 1)
|
||||
#endif
|
||||
|
||||
/* SDL_OS2Quit() will be called from SDL_QuitSubSystem() */
|
||||
void SDL_OS2Quit(void);
|
||||
|
||||
#endif /* SDL_os2_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#define INCL_DOSMODULEMGR /* Module Manager */
|
||||
#define INCL_DOSERRORS /* Error values */
|
||||
#include <os2.h>
|
||||
|
||||
#include "geniconv.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
# define iconv_debug(s,...) printf(__func__"(): "##s"\n" ,##__VA_ARGS__)
|
||||
#else
|
||||
# define iconv_debug(s,...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* Exports from os2iconv.c */
|
||||
extern iconv_t _System os2_iconv_open (const char* tocode, const char* fromcode);
|
||||
extern size_t _System os2_iconv (iconv_t cd,
|
||||
char **inbuf, size_t *inbytesleft,
|
||||
char **outbuf, size_t *outbytesleft);
|
||||
extern int _System os2_iconv_close (iconv_t cd);
|
||||
|
||||
/* Functions pointers */
|
||||
typedef iconv_t (_System *FNICONV_OPEN)(const char*, const char*);
|
||||
typedef size_t (_System *FNICONV) (iconv_t, char **, size_t *, char **, size_t *);
|
||||
typedef int (_System *FNICONV_CLOSE)(iconv_t);
|
||||
|
||||
static HMODULE hmIconv = NULLHANDLE;
|
||||
static FNICONV_OPEN fn_iconv_open = os2_iconv_open;
|
||||
static FNICONV fn_iconv = os2_iconv;
|
||||
static FNICONV_CLOSE fn_iconv_close = os2_iconv_close;
|
||||
|
||||
static int geniconv_init = 0;
|
||||
|
||||
|
||||
static BOOL _loadDLL(const char *dllname,
|
||||
const char *sym_iconvopen,
|
||||
const char *sym_iconv,
|
||||
const char *sym_iconvclose)
|
||||
{
|
||||
ULONG rc;
|
||||
char error[256];
|
||||
|
||||
rc = DosLoadModule(error, sizeof(error), dllname, &hmIconv);
|
||||
if (rc != NO_ERROR) {
|
||||
iconv_debug("DLL %s not loaded: %s", dllname, error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rc = DosQueryProcAddr(hmIconv, 0, sym_iconvopen, (PFN *)&fn_iconv_open);
|
||||
if (rc != NO_ERROR) {
|
||||
iconv_debug("Error: cannot find entry %s in %s", sym_iconvopen, dllname);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = DosQueryProcAddr(hmIconv, 0, sym_iconv, (PFN *)&fn_iconv);
|
||||
if (rc != NO_ERROR) {
|
||||
iconv_debug("Error: cannot find entry %s in %s", sym_iconv, dllname);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = DosQueryProcAddr(hmIconv, 0, sym_iconvclose, (PFN *)&fn_iconv_close);
|
||||
if (rc != NO_ERROR) {
|
||||
iconv_debug("Error: cannot find entry %s in %s", sym_iconvclose, dllname);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iconv_debug("DLL %s used", dllname);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
DosFreeModule(hmIconv);
|
||||
hmIconv = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
if (geniconv_init) {
|
||||
return; /* Already initialized */
|
||||
}
|
||||
|
||||
geniconv_init = 1;
|
||||
|
||||
/* Try to load kiconv.dll, iconv2.dll or iconv.dll */
|
||||
if (!_loadDLL("KICONV", "_libiconv_open", "_libiconv", "_libiconv_close") &&
|
||||
!_loadDLL("ICONV2", "_libiconv_open", "_libiconv", "_libiconv_close") &&
|
||||
!_loadDLL("ICONV", "_iconv_open", "_iconv", "_iconv_close") ) {
|
||||
/* No DLL was loaded - use OS/2 conversion objects API */
|
||||
iconv_debug("Uni*() API used");
|
||||
fn_iconv_open = os2_iconv_open;
|
||||
fn_iconv = os2_iconv;
|
||||
fn_iconv_close = os2_iconv_close;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Public routines.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/* function to unload the used iconv dynamic library */
|
||||
void libiconv_clean(void)
|
||||
{
|
||||
geniconv_init = 0;
|
||||
|
||||
/* reset the function pointers. */
|
||||
fn_iconv_open = os2_iconv_open;
|
||||
fn_iconv = os2_iconv;
|
||||
fn_iconv_close = os2_iconv_close;
|
||||
|
||||
if (hmIconv != NULLHANDLE) {
|
||||
DosFreeModule(hmIconv);
|
||||
hmIconv = NULLHANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_t libiconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
_init();
|
||||
return fn_iconv_open(tocode, fromcode);
|
||||
}
|
||||
|
||||
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
return fn_iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
|
||||
}
|
||||
|
||||
int libiconv_close(iconv_t cd)
|
||||
{
|
||||
return fn_iconv_close(cd);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#ifndef GENICONV_H
|
||||
#define GENICONV_H
|
||||
|
||||
#include "iconv.h"
|
||||
|
||||
#ifdef iconv_open
|
||||
#undef iconv_open
|
||||
#endif
|
||||
#define iconv_open libiconv_open
|
||||
|
||||
#ifdef iconv
|
||||
#undef iconv
|
||||
#endif
|
||||
#define iconv libiconv
|
||||
|
||||
#ifdef iconv_close
|
||||
#undef iconv_close
|
||||
#endif
|
||||
#define iconv_close libiconv_close
|
||||
|
||||
#define iconv_clean libiconv_clean
|
||||
|
||||
/* Non-standard function for iconv to unload the used dynamic library */
|
||||
void libiconv_clean(void);
|
||||
|
||||
iconv_t libiconv_open (const char *tocode, const char *fromcode);
|
||||
int libiconv_close(iconv_t cd);
|
||||
size_t libiconv (iconv_t cd, char **inbuf, size_t *inbytesleft,
|
||||
char **outbuf, size_t *outbytesleft);
|
||||
|
||||
/* System codepage <-> UTF-8
|
||||
*
|
||||
* StrUTF8()
|
||||
* Converts string from system cp to UTF-8 (to_utf8 is not 0) or from UTF-8 to
|
||||
* the system cp (to_utf8 is 0). Converted ASCIIZ string will be placed at the
|
||||
* buffer dst, up to c_dst - 1 (for sys->utf8) or 2 (for utf8->sys) bytes.
|
||||
* Returns the number of bytes written into dst, not counting the terminating
|
||||
* 0 byte(s) or -1 on error.
|
||||
*/
|
||||
int StrUTF8(int to_utf8, char *dst, int c_dst, char *src, int c_src);
|
||||
|
||||
/* StrUTF8New()
|
||||
* Converts string from system cp to UTF-8 (to_utf8 is not 0) or from UTF-8
|
||||
* to the system cp (to_utf8 is 0). Memory for the new string is obtained by
|
||||
* using libc malloc().
|
||||
* Returns converted string, terminating two bytes 0 is appended to the result.
|
||||
* Returns null on error.
|
||||
*/
|
||||
char *StrUTF8New(int to_utf8, char *str, int c_str);
|
||||
|
||||
/* StrUTF8Free()
|
||||
* Deallocates the memory block allocated by StrUTF8New() (just libc free()).
|
||||
*/
|
||||
void StrUTF8Free(char *str);
|
||||
|
||||
#endif /* GENICONV_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef ICONV_H_ /* minimal iconv.h header based on public knowledge */
|
||||
#define ICONV_H_
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <errno.h>
|
||||
|
||||
typedef void *iconv_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern iconv_t iconv_open(const char *, const char *);
|
||||
extern size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
|
||||
extern int iconv_close(iconv_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ICONV_H_ */
|
||||
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Universal iconv implementation for OS/2.
|
||||
#
|
||||
# OpenWatcom makefile to build a library that uses kiconv.dll / iconv2.dll /
|
||||
# iconv.dll or OS/2 Uni*() API.
|
||||
#
|
||||
# Andrey Vasilkin, 2016.
|
||||
#
|
||||
|
||||
LIBFILE = geniconv.lib
|
||||
|
||||
all: $(LIBFILE) test.exe .symbolic
|
||||
|
||||
CFLAGS = -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h -I. -bt=os2 -q -d0 -w2 -DGENICONV_STANDALONE=1
|
||||
|
||||
SRCS = geniconv.c os2cp.c os2iconv.c
|
||||
SRCS+= sys2utf8.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
LIBS = libuls.lib libconv.lib $(LIBFILE)
|
||||
|
||||
test.exe: $(LIBFILE) test.obj
|
||||
wlink op quiet system os2v2 file test.obj lib {$(LIBS)} name $*
|
||||
|
||||
$(LIBFILE): $(OBJS)
|
||||
@if exist $@ rm $@
|
||||
@for %f in ($(OBJS)) do wlib -q -b $* +%f
|
||||
|
||||
.c.obj:
|
||||
wcc386 $(CFLAGS) -fo=$^@ $<
|
||||
|
||||
clean: .SYMBOLIC
|
||||
@if exist *.obj rm *.obj
|
||||
@if exist *.err rm *.err
|
||||
@if exist $(LIBFILE) rm $(LIBFILE)
|
||||
@if exist test.exe rm test.exe
|
||||
+416
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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.
|
||||
*/
|
||||
|
||||
#define INCL_DOSNLS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
#include "os2cp.h"
|
||||
|
||||
#ifndef GENICONV_STANDALONE
|
||||
#include "../../../SDL_internal.h"
|
||||
#else
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define SDL_isspace isspace
|
||||
#define SDL_strchr strchr
|
||||
#define SDL_memcpy memcpy
|
||||
#define SDL_strupr strupr
|
||||
#define SDL_strcmp strcmp
|
||||
#endif
|
||||
|
||||
typedef struct _CP2NAME {
|
||||
ULONG ulCode;
|
||||
PSZ pszName;
|
||||
} CP2NAME;
|
||||
|
||||
typedef struct _NAME2CP {
|
||||
PSZ pszName;
|
||||
ULONG ulCode;
|
||||
} NAME2CP;
|
||||
|
||||
static CP2NAME aCP2Name[] = {
|
||||
{367, "ANSI_X3.4-1968"},
|
||||
{813, "ECMA-118"},
|
||||
{819, "CP819"},
|
||||
{850, "850"},
|
||||
{862, "862"},
|
||||
{866, "866"},
|
||||
{874, "ISO-IR-166"},
|
||||
{878, "KOI8-R"},
|
||||
{896, "JISX0201-1976"},
|
||||
{901, "ISO-8859-13"},
|
||||
{912, "ISO-8859-2"},
|
||||
{913, "ISO-8859-3"},
|
||||
{914, "ISO-8859-4"},
|
||||
{915, "CYRILLIC"},
|
||||
{920, "ISO-8859-9"},
|
||||
{923, "ISO-8859-15"},
|
||||
{943, "MS_KANJI"},
|
||||
{954, "EUC-JP"},
|
||||
{964, "EUC-TW"},
|
||||
{970, "EUC-KR"},
|
||||
{1051, "HP-ROMAN8"},
|
||||
{1089, "ARABIC"},
|
||||
{1129, "VISCII"},
|
||||
{1168, "KOI8-U"},
|
||||
{1200, "ISO-10646-UCS-2"},
|
||||
{1202, "UTF-16LE"},
|
||||
{1204, "UCS-2BE"},
|
||||
{1208, "UTF-8"},
|
||||
{1232, "UTF-32BE"},
|
||||
{1234, "UTF-32LE"},
|
||||
{1236, "ISO-10646-UCS-4"},
|
||||
{1250, "CP1250"},
|
||||
{1251, "CP1251"},
|
||||
{1252, "CP1252"},
|
||||
{1253, "CP1253"},
|
||||
{1254, "CP1254"},
|
||||
{1255, "CP1255"},
|
||||
{1256, "CP1256"},
|
||||
{1257, "CP1257"},
|
||||
{1275, "MAC"},
|
||||
{1383, "CN-GB"},
|
||||
{1386, "GBK"},
|
||||
{1392, "GB18030"},
|
||||
{62210, "HEBREW"}
|
||||
};
|
||||
|
||||
static NAME2CP aName2CP[] = {
|
||||
{"850", 850},
|
||||
{"862", 862},
|
||||
{"866", 866},
|
||||
{"ANSI_X3.4-1968", 367},
|
||||
{"ANSI_X3.4-1986", 367},
|
||||
{"ARABIC", 1089},
|
||||
{"ASCII", 367},
|
||||
{"ASMO-708", 1089},
|
||||
{"CN-GB", 1383},
|
||||
{"CP1250", 1250},
|
||||
{"CP1251", 1251},
|
||||
{"CP1252", 1252},
|
||||
{"CP1253", 1253},
|
||||
{"CP1254", 1254},
|
||||
{"CP1255", 1255},
|
||||
{"CP1256", 1256},
|
||||
{"CP1257", 1257},
|
||||
{"CP367", 367},
|
||||
{"CP819", 819},
|
||||
{"CP850", 850},
|
||||
{"CP862", 862},
|
||||
{"CP866", 866},
|
||||
{"CP936", 1386},
|
||||
{"CSASCII", 367},
|
||||
{"CSEUCKR", 970},
|
||||
{"CSEUCPKDFMTJAPANESE", 954},
|
||||
{"CSEUCTW", 964},
|
||||
{"CSGB2312", 1383},
|
||||
{"CSHALFWIDTHKATAKANA", 896},
|
||||
{"CSHPROMAN8", 1051},
|
||||
{"CSIBM866", 866},
|
||||
{"CSISOLATIN1", 819},
|
||||
{"CSISOLATIN2", 912},
|
||||
{"CSISOLATIN3", 913},
|
||||
{"CSISOLATIN4", 914},
|
||||
{"CSISOLATIN5", 920},
|
||||
{"CSISOLATINARABIC", 1089},
|
||||
{"CSISOLATINCYRILLIC", 915},
|
||||
{"CSISOLATINGREEK", 813},
|
||||
{"CSISOLATINHEBREW", 62210},
|
||||
{"CSKOI8R", 878},
|
||||
{"CSKSC56011987", 970},
|
||||
{"CSMACINTOSH", 1275},
|
||||
{"CSPC850MULTILINGUAL", 850},
|
||||
{"CSPC862LATINHEBREW", 862},
|
||||
{"CSSHIFTJIS", 943},
|
||||
{"CSUCS4", 1236},
|
||||
{"CSUNICODE", 1200},
|
||||
{"CSUNICODE11", 1204},
|
||||
{"CSVISCII", 1129},
|
||||
{"CYRILLIC", 915},
|
||||
{"ECMA-114", 1089},
|
||||
{"ECMA-118", 813},
|
||||
{"ELOT_928", 813},
|
||||
{"EUC-CN", 1383},
|
||||
{"EUC-JP", 954},
|
||||
{"EUC-KR", 970},
|
||||
{"EUC-TW", 964},
|
||||
{"EUCCN", 1383},
|
||||
{"EUCJP", 954},
|
||||
{"EUCKR", 970},
|
||||
{"EUCTW", 964},
|
||||
{"EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE", 954},
|
||||
{"GB18030", 1392},
|
||||
{"GB2312", 1383},
|
||||
{"GBK", 1386},
|
||||
{"GREEK", 813},
|
||||
{"GREEK8", 813},
|
||||
{"HEBREW", 62210},
|
||||
{"HP-ROMAN8", 1051},
|
||||
{"IBM367", 367},
|
||||
{"IBM819", 819},
|
||||
{"IBM850", 850},
|
||||
{"IBM862", 862},
|
||||
{"IBM866", 866},
|
||||
{"ISO-10646-UCS-2", 1200},
|
||||
{"ISO-10646-UCS-4", 1236},
|
||||
{"ISO-8859-1", 819},
|
||||
{"ISO-8859-13", 901},
|
||||
{"ISO-8859-15", 923},
|
||||
{"ISO-8859-2", 912},
|
||||
{"ISO-8859-3", 913},
|
||||
{"ISO-8859-4", 914},
|
||||
{"ISO-8859-5", 915},
|
||||
{"ISO-8859-6", 1089},
|
||||
{"ISO-8859-7", 813},
|
||||
{"ISO-8859-8", 62210},
|
||||
{"ISO-8859-9", 920},
|
||||
{"ISO-IR-100", 819},
|
||||
{"ISO-IR-101", 912},
|
||||
{"ISO-IR-109", 913},
|
||||
{"ISO-IR-110", 914},
|
||||
{"ISO-IR-126", 813},
|
||||
{"ISO-IR-127", 1089},
|
||||
{"ISO-IR-138", 62210},
|
||||
{"ISO-IR-144", 915},
|
||||
{"ISO-IR-148", 920},
|
||||
{"ISO-IR-149", 970},
|
||||
{"ISO-IR-166", 874},
|
||||
{"ISO-IR-179", 901},
|
||||
{"ISO-IR-203", 923},
|
||||
{"ISO-IR-6", 367},
|
||||
{"ISO646-US", 367},
|
||||
{"ISO8859-1", 819},
|
||||
{"ISO8859-13", 901},
|
||||
{"ISO8859-15", 923},
|
||||
{"ISO8859-2", 912},
|
||||
{"ISO8859-3", 913},
|
||||
{"ISO8859-4", 914},
|
||||
{"ISO8859-5", 915},
|
||||
{"ISO8859-6", 1089},
|
||||
{"ISO8859-7", 813},
|
||||
{"ISO8859-8", 62210},
|
||||
{"ISO8859-9", 920},
|
||||
{"ISO_646.IRV:1991", 367},
|
||||
{"ISO_8859-1", 819},
|
||||
{"ISO_8859-13", 901},
|
||||
{"ISO_8859-15", 923},
|
||||
{"ISO_8859-15:1998", 923},
|
||||
{"ISO_8859-1:1987", 819},
|
||||
{"ISO_8859-2", 912},
|
||||
{"ISO_8859-2:1987", 912},
|
||||
{"ISO_8859-3", 913},
|
||||
{"ISO_8859-3:1988", 913},
|
||||
{"ISO_8859-4", 914},
|
||||
{"ISO_8859-4:1988", 914},
|
||||
{"ISO_8859-5", 915},
|
||||
{"ISO_8859-5:1988", 915},
|
||||
{"ISO_8859-6", 1089},
|
||||
{"ISO_8859-6:1987", 1089},
|
||||
{"ISO_8859-7", 813},
|
||||
{"ISO_8859-7:1987", 813},
|
||||
{"ISO_8859-7:2003", 813},
|
||||
{"ISO_8859-8", 62210},
|
||||
{"ISO_8859-8:1988", 62210},
|
||||
{"ISO_8859-9", 920},
|
||||
{"ISO_8859-9:1989", 920},
|
||||
{"JISX0201-1976", 896},
|
||||
{"JIS_X0201", 896},
|
||||
{"KOI8-R", 878},
|
||||
{"KOI8-U", 1168},
|
||||
{"KOREAN", 970},
|
||||
{"KSC_5601", 970},
|
||||
{"KS_C_5601-1987", 970},
|
||||
{"KS_C_5601-1989", 970},
|
||||
{"L1", 819},
|
||||
{"L2", 912},
|
||||
{"L3", 913},
|
||||
{"L4", 914},
|
||||
{"L5", 920},
|
||||
{"L7", 901},
|
||||
{"LATIN-9", 923},
|
||||
{"LATIN1", 819},
|
||||
{"LATIN2", 912},
|
||||
{"LATIN3", 913},
|
||||
{"LATIN4", 914},
|
||||
{"LATIN5", 920},
|
||||
{"LATIN7", 901},
|
||||
{"MAC", 1275},
|
||||
{"MACINTOSH", 1275},
|
||||
{"MACROMAN", 1275},
|
||||
{"MS-ANSI", 1252},
|
||||
{"MS-ARAB", 1256},
|
||||
{"MS-CYRL", 1251},
|
||||
{"MS-EE", 1250},
|
||||
{"MS-GREEK", 1253},
|
||||
{"MS-HEBR", 1255},
|
||||
{"MS-TURK", 1254},
|
||||
{"MS936", 1386},
|
||||
{"MS_KANJI", 943},
|
||||
{"R8", 1051},
|
||||
{"ROMAN8", 1051},
|
||||
{"SHIFT-JIS", 943},
|
||||
{"SHIFT_JIS", 943},
|
||||
{"SJIS", 943},
|
||||
{"TIS-620", 874},
|
||||
{"TIS620", 874},
|
||||
{"TIS620-0", 874},
|
||||
{"TIS620.2529-1", 874},
|
||||
{"TIS620.2533-0", 874},
|
||||
{"TIS620.2533-1", 874},
|
||||
{"UCS-2", 1200},
|
||||
{"UCS-2BE", 1204},
|
||||
{"UCS-4", 1236},
|
||||
{"UNICODE-1-1", 1204},
|
||||
{"UNICODEBIG", 1204},
|
||||
{"US", 367},
|
||||
{"US-ASCII", 367},
|
||||
{"UTF-16", 1204},
|
||||
{"UTF-16BE", 1200},
|
||||
{"UTF-16LE", 1202},
|
||||
{"UTF-32", 1236},
|
||||
{"UTF-32BE", 1232},
|
||||
{"UTF-32LE", 1234},
|
||||
{"UTF-8", 1208},
|
||||
{"VISCII", 1129},
|
||||
{"VISCII1.1-1", 1129},
|
||||
{"WINBALTRIM", 1257},
|
||||
{"WINDOWS-1250", 1250},
|
||||
{"WINDOWS-1251", 1251},
|
||||
{"WINDOWS-1252", 1252},
|
||||
{"WINDOWS-1253", 1253},
|
||||
{"WINDOWS-1254", 1254},
|
||||
{"WINDOWS-1255", 1255},
|
||||
{"WINDOWS-1256", 1256},
|
||||
{"WINDOWS-1257", 1257},
|
||||
{"WINDOWS-936", 1386},
|
||||
{"X0201", 896}
|
||||
};
|
||||
|
||||
char *os2cpToName(unsigned long cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = (sizeof(aCP2Name) / sizeof(struct _CP2NAME)) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
|
||||
if (cp == SYSTEM_CP) {
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
if (DosQueryCp(sizeof(aulCP), aulCP, &cCP) != NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
cp = aulCP[0];
|
||||
}
|
||||
|
||||
if (aCP2Name[0].ulCode > cp || aCP2Name[ulHi].ulCode < cp) {
|
||||
return NULL;
|
||||
}
|
||||
if (aCP2Name[0].ulCode == cp) {
|
||||
return aCP2Name[0].pszName;
|
||||
}
|
||||
if (aCP2Name[ulHi].ulCode == cp) {
|
||||
return aCP2Name[ulHi].pszName;
|
||||
}
|
||||
|
||||
while ((ulHi - ulLo) > 1) {
|
||||
ulNext = (ulLo + ulHi) / 2;
|
||||
|
||||
if (aCP2Name[ulNext].ulCode < cp) {
|
||||
ulLo = ulNext;
|
||||
} else if (aCP2Name[ulNext].ulCode > cp) {
|
||||
ulHi = ulNext;
|
||||
} else {
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (lFound == -1)? NULL : aCP2Name[lFound].pszName;
|
||||
}
|
||||
|
||||
unsigned long os2cpFromName(char *cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = (sizeof(aName2CP) / sizeof(struct _NAME2CP)) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
LONG lCmp;
|
||||
PCHAR pcEnd;
|
||||
CHAR acBuf[64];
|
||||
|
||||
if (cp == NULL) {
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
return (DosQueryCp(sizeof(aulCP), aulCP, &cCP) != NO_ERROR)? 0 : aulCP[0];
|
||||
}
|
||||
|
||||
while (SDL_isspace((unsigned char) *cp)) {
|
||||
cp++;
|
||||
}
|
||||
|
||||
pcEnd = SDL_strchr(cp, ' ');
|
||||
if (pcEnd == NULL) {
|
||||
pcEnd = SDL_strchr(cp, '\0');
|
||||
}
|
||||
ulNext = pcEnd - cp;
|
||||
if (ulNext >= sizeof(acBuf)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_memcpy(acBuf, cp, ulNext);
|
||||
acBuf[ulNext] = '\0';
|
||||
SDL_strupr(acBuf);
|
||||
|
||||
lCmp = SDL_strcmp(aName2CP[0].pszName, acBuf);
|
||||
if (lCmp > 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lCmp == 0) {
|
||||
return aName2CP[0].ulCode;
|
||||
}
|
||||
|
||||
lCmp = SDL_strcmp(aName2CP[ulHi].pszName, acBuf);
|
||||
if (lCmp < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lCmp == 0) {
|
||||
return aName2CP[ulHi].ulCode;
|
||||
}
|
||||
|
||||
while ((ulHi - ulLo) > 1) {
|
||||
ulNext = (ulLo + ulHi) / 2;
|
||||
|
||||
lCmp = SDL_strcmp(aName2CP[ulNext].pszName, acBuf);
|
||||
if (lCmp < 0) {
|
||||
ulLo = ulNext;
|
||||
} else if (lCmp > 0) {
|
||||
ulHi = ulNext;
|
||||
} else {
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (lFound == -1)? 0 : aName2CP[lFound].ulCode;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 OS2CP_H
|
||||
#define OS2CP_H 1
|
||||
|
||||
#define SYSTEM_CP 0
|
||||
|
||||
char *os2cpToName(unsigned long cp);
|
||||
unsigned long os2cpFromName(char *cp);
|
||||
|
||||
#endif /* OS2CP_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Implementation iconv via OS/2 conversion objects API.
|
||||
|
||||
Andrey Vasilkin.
|
||||
*/
|
||||
|
||||
#define ICONV_THREAD_SAFE 1
|
||||
|
||||
#include "geniconv.h"
|
||||
#define _ULS_CALLCONV_
|
||||
#define CALLCONV _System
|
||||
#include <uconv.h>
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#endif
|
||||
|
||||
#include "os2cp.h"
|
||||
|
||||
#ifndef GENICONV_STANDALONE
|
||||
#include "../../../SDL_internal.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if !defined(min)
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#define SDL_min min
|
||||
#define SDL_strcasecmp stricmp
|
||||
#define SDL_snprintf _snprintf
|
||||
#define SDL_malloc malloc
|
||||
#define SDL_free free
|
||||
#define SDL_memcpy memcpy
|
||||
#endif
|
||||
|
||||
#define MAX_CP_NAME_LEN 64
|
||||
|
||||
typedef struct iuconv_obj {
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int buf_len;
|
||||
UniChar *buf;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
HMTX hMtx;
|
||||
#endif
|
||||
} iuconv_obj;
|
||||
|
||||
|
||||
static int _createUconvObj(const char *code, UconvObject *uobj)
|
||||
{
|
||||
UniChar uc_code[MAX_CP_NAME_LEN];
|
||||
int i;
|
||||
const unsigned char *ch =
|
||||
(const unsigned char *)code;
|
||||
|
||||
if (code == NULL)
|
||||
uc_code[0] = 0;
|
||||
else {
|
||||
for (i = 0; i < MAX_CP_NAME_LEN; i++) {
|
||||
uc_code[i] = (unsigned short)*ch;
|
||||
if (! (*ch))
|
||||
break;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
return UniCreateUconvObject(uc_code, uobj);
|
||||
}
|
||||
|
||||
static int uconv_open(const char *code, UconvObject *uobj)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!SDL_strcasecmp(code, "UTF-16")) {
|
||||
*uobj = NULL;
|
||||
return ULS_SUCCESS;
|
||||
}
|
||||
|
||||
rc = _createUconvObj(code, uobj);
|
||||
if (rc != ULS_SUCCESS) {
|
||||
unsigned long cp = os2cpFromName((char *)code);
|
||||
char cp_name[16];
|
||||
if (cp != 0 && SDL_snprintf(cp_name, sizeof(cp_name), "IBM-%u", cp) > 0) {
|
||||
rc = _createUconvObj(cp_name, uobj);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int rc;
|
||||
iuconv_obj *iuobj;
|
||||
|
||||
if (tocode == NULL) {
|
||||
tocode = "";
|
||||
}
|
||||
if (fromcode == NULL) {
|
||||
fromcode = "";
|
||||
}
|
||||
|
||||
if (SDL_strcasecmp(tocode, fromcode) != 0) {
|
||||
rc = uconv_open(fromcode, &uo_fromcode);
|
||||
if (rc != ULS_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
rc = uconv_open(tocode, &uo_tocode);
|
||||
if (rc != ULS_SUCCESS) {
|
||||
UniFreeUconvObject(uo_fromcode);
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
} else {
|
||||
uo_tocode = NULL;
|
||||
uo_fromcode = NULL;
|
||||
}
|
||||
|
||||
iuobj = (iuconv_obj *) SDL_malloc(sizeof(iuconv_obj));
|
||||
iuobj->uo_tocode = uo_tocode;
|
||||
iuobj->uo_fromcode = uo_fromcode;
|
||||
iuobj->buf_len = 0;
|
||||
iuobj->buf = NULL;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCreateMutexSem(NULL, &iuobj->hMtx, 0, FALSE);
|
||||
#endif
|
||||
|
||||
return iuobj;
|
||||
}
|
||||
|
||||
size_t _System os2_iconv(iconv_t cd,
|
||||
char **inbuf, size_t *inbytesleft ,
|
||||
char **outbuf, size_t *outbytesleft)
|
||||
{
|
||||
UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
|
||||
UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
|
||||
size_t nonIdenticalConv = 0;
|
||||
UniChar *uc_buf;
|
||||
size_t uc_buf_len;
|
||||
UniChar **uc_str;
|
||||
size_t *uc_str_len;
|
||||
int rc;
|
||||
size_t ret = (size_t)(-1);
|
||||
|
||||
if (uo_tocode == NULL && uo_fromcode == NULL) {
|
||||
uc_buf_len = SDL_min(*inbytesleft, *outbytesleft);
|
||||
SDL_memcpy(*outbuf, *inbuf, uc_buf_len);
|
||||
*inbytesleft -= uc_buf_len;
|
||||
*outbytesleft -= uc_buf_len;
|
||||
outbuf += uc_buf_len;
|
||||
inbuf += uc_buf_len;
|
||||
return uc_buf_len;
|
||||
}
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosRequestMutexSem(((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT);
|
||||
#endif
|
||||
|
||||
if (uo_tocode && uo_fromcode && (((iuconv_obj *)cd)->buf_len >> 1) < *inbytesleft) {
|
||||
if (((iuconv_obj *)cd)->buf != NULL) {
|
||||
SDL_free(((iuconv_obj *)cd)->buf);
|
||||
}
|
||||
((iuconv_obj *)cd)->buf_len = *inbytesleft << 1;
|
||||
((iuconv_obj *)cd)->buf = (UniChar *) SDL_malloc(((iuconv_obj *)cd)->buf_len);
|
||||
}
|
||||
|
||||
if (uo_fromcode) {
|
||||
if (uo_tocode) {
|
||||
uc_buf = ((iuconv_obj *)cd)->buf;
|
||||
uc_buf_len = ((iuconv_obj *)cd)->buf_len;
|
||||
uc_str = &uc_buf;
|
||||
} else {
|
||||
uc_str = (UniChar **)outbuf;
|
||||
uc_buf_len = *outbytesleft;
|
||||
}
|
||||
uc_buf_len = uc_buf_len >> 1;
|
||||
uc_str_len = &uc_buf_len;
|
||||
rc = UniUconvToUcs(uo_fromcode, (void **)inbuf, inbytesleft,
|
||||
uc_str, uc_str_len, &nonIdenticalConv);
|
||||
uc_buf_len = uc_buf_len << 1;
|
||||
if (!uo_tocode) {
|
||||
*outbytesleft = uc_buf_len;
|
||||
}
|
||||
|
||||
if (rc != ULS_SUCCESS) {
|
||||
errno = EILSEQ;
|
||||
goto done;
|
||||
} else if (*inbytesleft && !*uc_str_len) {
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!uo_tocode) {
|
||||
return nonIdenticalConv;
|
||||
}
|
||||
|
||||
uc_buf = ((iuconv_obj *)cd)->buf;
|
||||
uc_buf_len = ((iuconv_obj *)cd)->buf_len - uc_buf_len;
|
||||
uc_str = &uc_buf;
|
||||
uc_str_len = &uc_buf_len;
|
||||
} else {
|
||||
uc_str = (UniChar **)inbuf;
|
||||
uc_str_len = inbytesleft;
|
||||
}
|
||||
|
||||
*uc_str_len = *uc_str_len>>1;
|
||||
rc = UniUconvFromUcs(uo_tocode, uc_str, uc_str_len, (void **)outbuf,
|
||||
outbytesleft, &nonIdenticalConv);
|
||||
if (rc != ULS_SUCCESS) {
|
||||
switch (rc) {
|
||||
case ULS_BUFFERFULL:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case ULS_ILLEGALSEQUENCE:
|
||||
errno = EILSEQ;
|
||||
break;
|
||||
case ULS_INVALID:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
} else if (*uc_str_len && !*outbytesleft) {
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = nonIdenticalConv;
|
||||
|
||||
done:
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosReleaseMutexSem(((iuconv_obj *)cd)->hMtx);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _System os2_iconv_close(iconv_t cd)
|
||||
{
|
||||
if (!cd) return 0;
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCloseMutexSem(((iuconv_obj *)cd)->hMtx);
|
||||
#endif
|
||||
if (((iuconv_obj *)cd)->uo_tocode != NULL) {
|
||||
UniFreeUconvObject(((iuconv_obj *)cd)->uo_tocode);
|
||||
}
|
||||
if (((iuconv_obj *)cd)->uo_fromcode != NULL) {
|
||||
UniFreeUconvObject(((iuconv_obj *)cd)->uo_fromcode);
|
||||
}
|
||||
|
||||
if (((iuconv_obj *)cd)->buf != NULL) {
|
||||
SDL_free(((iuconv_obj *)cd)->buf);
|
||||
}
|
||||
SDL_free(cd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 "geniconv.h"
|
||||
|
||||
#ifndef GENICONV_STANDALONE
|
||||
#include "../../../SDL_internal.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define SDL_malloc malloc
|
||||
#define SDL_realloc realloc
|
||||
#define SDL_free free
|
||||
#endif
|
||||
|
||||
int StrUTF8(int to_utf8, char *dst, int c_dst, char *src, int c_src)
|
||||
{
|
||||
size_t rc;
|
||||
char *dststart = dst;
|
||||
iconv_t cd;
|
||||
char *tocp, *fromcp;
|
||||
int err = 0;
|
||||
|
||||
if (c_dst < 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (to_utf8) {
|
||||
tocp = "UTF-8";
|
||||
fromcp = "";
|
||||
} else {
|
||||
tocp = "";
|
||||
fromcp = "UTF-8";
|
||||
}
|
||||
|
||||
cd = iconv_open(tocp, fromcp);
|
||||
if (cd == (iconv_t)-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (c_src > 0) {
|
||||
rc = iconv(cd, &src, (size_t *)&c_src, &dst, (size_t *)&c_dst);
|
||||
if (rc == (size_t)-1) {
|
||||
if (errno == EILSEQ) {
|
||||
/* Try to skip invalid character */
|
||||
src++;
|
||||
c_src--;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_close(cd);
|
||||
|
||||
/* Write trailing ZERO (1 byte for UTF-8, 2 bytes for the system cp) */
|
||||
if (to_utf8) {
|
||||
if (c_dst < 1) {
|
||||
dst--;
|
||||
err = 1; /* The destination buffer overflow */
|
||||
}
|
||||
*dst = '\0';
|
||||
} else {
|
||||
if (c_dst < 2) {
|
||||
dst -= (c_dst == 0) ? 2 : 1;
|
||||
err = 1; /* The destination buffer overflow */
|
||||
}
|
||||
*((short *)dst) = '\0';
|
||||
}
|
||||
|
||||
return (err) ? -1 : (dst - dststart);
|
||||
}
|
||||
|
||||
char *StrUTF8New(int to_utf8, char *str, int c_str)
|
||||
{
|
||||
int c_newstr = (((c_str > 4) ? c_str : 4) + 1) * 2;
|
||||
char * newstr = (char *) SDL_malloc(c_newstr);
|
||||
|
||||
if (newstr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c_newstr = StrUTF8(to_utf8, newstr, c_newstr, str, c_str);
|
||||
if (c_newstr != -1) {
|
||||
str = (char *) SDL_realloc(newstr, c_newstr + ((to_utf8) ? 1 : sizeof(short)));
|
||||
if (str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(newstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StrUTF8Free(char *str)
|
||||
{
|
||||
SDL_free(str);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "geniconv.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char acBuf[128];
|
||||
char *inbuf = "ôÅÓÔ - ÐÒÏ×ÅÒËÁ"; /* KOI8-R string */
|
||||
size_t inbytesleft = strlen(inbuf);
|
||||
char *outbuf = acBuf;
|
||||
size_t outbytesleft = sizeof(acBuf);
|
||||
iconv_t ic;
|
||||
|
||||
/* KOI8 -> system cp */
|
||||
ic = iconv_open("", "KOI8-R");
|
||||
if (ic == (iconv_t)(-1)) {
|
||||
puts("iconv_open() fail");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iconv(ic, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
|
||||
printf("KOI8-R to system cp: %s\n", acBuf);
|
||||
|
||||
iconv_close(ic);
|
||||
|
||||
/* System cp -> UTF-8 -> system cp: */
|
||||
|
||||
/* System cp -> UTF-8 by StrUTF8New() */
|
||||
inbuf = StrUTF8New(1, acBuf, strlen(acBuf));
|
||||
|
||||
/* UTF-8 -> system cp. by StrUTF8() */
|
||||
if (StrUTF8(0, acBuf, sizeof(acBuf), inbuf, strlen(inbuf)) == -1) {
|
||||
puts("StrUTF8() failed");
|
||||
} else {
|
||||
printf("system cp. -> UTF-8 -> system cp.: %s\n", acBuf);
|
||||
}
|
||||
|
||||
free(inbuf);
|
||||
|
||||
/* Unload used DLL */
|
||||
iconv_clean();
|
||||
|
||||
puts("Done.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,4 @@
|
||||
# OpenWatcom exports file for libiconv
|
||||
++'libiconv'.'ICONV2'..'_libiconv'
|
||||
++'libiconv_close'.'ICONV2'..'_libiconv_close'
|
||||
++'libiconv_open'.'ICONV2'..'_libiconv_open'
|
||||
+17
-13
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_poll.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
@@ -35,10 +34,12 @@
|
||||
|
||||
|
||||
int
|
||||
SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
|
||||
SDL_IOReady(int fd, int flags, int timeoutMS)
|
||||
{
|
||||
int result;
|
||||
|
||||
SDL_assert(flags & (SDL_IOR_READ | SDL_IOR_WRITE));
|
||||
|
||||
/* Note: We don't bother to account for elapsed time if we get EINTR */
|
||||
do
|
||||
{
|
||||
@@ -46,10 +47,12 @@ SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
|
||||
struct pollfd info;
|
||||
|
||||
info.fd = fd;
|
||||
if (forWrite) {
|
||||
info.events = POLLOUT;
|
||||
} else {
|
||||
info.events = POLLIN | POLLPRI;
|
||||
info.events = 0;
|
||||
if (flags & SDL_IOR_READ) {
|
||||
info.events |= POLLIN | POLLPRI;
|
||||
}
|
||||
if (flags & SDL_IOR_WRITE) {
|
||||
info.events |= POLLOUT;
|
||||
}
|
||||
result = poll(&info, 1, timeoutMS);
|
||||
#else
|
||||
@@ -60,15 +63,16 @@ SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
|
||||
/* 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 {
|
||||
if (flags & SDL_IOR_READ) {
|
||||
FD_ZERO(&rfdset);
|
||||
FD_SET(fd, &rfdset);
|
||||
rfdp = &rfdset;
|
||||
}
|
||||
if (flags & SDL_IOR_WRITE) {
|
||||
FD_ZERO(&wfdset);
|
||||
FD_SET(fd, &wfdset);
|
||||
wfdp = &wfdset;
|
||||
}
|
||||
|
||||
if (timeoutMS >= 0) {
|
||||
tv.tv_sec = timeoutMS / 1000;
|
||||
@@ -79,7 +83,7 @@ SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
|
||||
result = select(fd + 1, rfdp, wfdp, NULL, tvp);
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
} while ( result < 0 && errno == EINTR );
|
||||
} while ( result < 0 && errno == EINTR && !(flags & SDL_IOR_NO_RETRY));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -26,8 +26,11 @@
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#define SDL_IOR_READ 0x1
|
||||
#define SDL_IOR_WRITE 0x2
|
||||
#define SDL_IOR_NO_RETRY 0x4
|
||||
|
||||
extern int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS);
|
||||
extern int SDL_IOReady(int fd, int flags, int timeoutMS);
|
||||
|
||||
#endif /* SDL_poll_h_ */
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 __WINRT__
|
||||
|
||||
#include "SDL_hid.h"
|
||||
|
||||
|
||||
HidD_GetString_t SDL_HidD_GetManufacturerString;
|
||||
HidD_GetString_t SDL_HidD_GetProductString;
|
||||
HidD_GetPreparsedData_t SDL_HidD_GetPreparsedData;
|
||||
HidD_FreePreparsedData_t SDL_HidD_FreePreparsedData;
|
||||
HidP_GetCaps_t SDL_HidP_GetCaps;
|
||||
HidP_GetButtonCaps_t SDL_HidP_GetButtonCaps;
|
||||
HidP_GetValueCaps_t SDL_HidP_GetValueCaps;
|
||||
HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength;
|
||||
HidP_GetData_t SDL_HidP_GetData;
|
||||
|
||||
static HMODULE s_pHIDDLL = 0;
|
||||
static int s_HIDDLLRefCount = 0;
|
||||
|
||||
|
||||
int
|
||||
WIN_LoadHIDDLL(void)
|
||||
{
|
||||
if (s_pHIDDLL) {
|
||||
SDL_assert(s_HIDDLLRefCount > 0);
|
||||
s_HIDDLLRefCount++;
|
||||
return 0; /* already loaded */
|
||||
}
|
||||
|
||||
s_pHIDDLL = LoadLibrary(TEXT("hid.dll"));
|
||||
if (!s_pHIDDLL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(s_HIDDLLRefCount == 0);
|
||||
s_HIDDLLRefCount = 1;
|
||||
|
||||
SDL_HidD_GetManufacturerString = (HidD_GetString_t)GetProcAddress(s_pHIDDLL, "HidD_GetManufacturerString");
|
||||
SDL_HidD_GetProductString = (HidD_GetString_t)GetProcAddress(s_pHIDDLL, "HidD_GetProductString");
|
||||
SDL_HidD_GetPreparsedData = (HidD_GetPreparsedData_t)GetProcAddress(s_pHIDDLL, "HidD_GetPreparsedData");
|
||||
SDL_HidD_FreePreparsedData = (HidD_FreePreparsedData_t)GetProcAddress(s_pHIDDLL, "HidD_FreePreparsedData");
|
||||
SDL_HidP_GetCaps = (HidP_GetCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetCaps");
|
||||
SDL_HidP_GetButtonCaps = (HidP_GetButtonCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetButtonCaps");
|
||||
SDL_HidP_GetValueCaps = (HidP_GetValueCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetValueCaps");
|
||||
SDL_HidP_MaxDataListLength = (HidP_MaxDataListLength_t)GetProcAddress(s_pHIDDLL, "HidP_MaxDataListLength");
|
||||
SDL_HidP_GetData = (HidP_GetData_t)GetProcAddress(s_pHIDDLL, "HidP_GetData");
|
||||
if (!SDL_HidD_GetManufacturerString || !SDL_HidD_GetProductString || !SDL_HidD_GetPreparsedData ||
|
||||
!SDL_HidD_FreePreparsedData || !SDL_HidP_GetCaps || !SDL_HidP_GetButtonCaps ||
|
||||
!SDL_HidP_GetValueCaps || !SDL_HidP_MaxDataListLength || !SDL_HidP_GetData) {
|
||||
WIN_UnloadHIDDLL();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_UnloadHIDDLL(void)
|
||||
{
|
||||
if (s_pHIDDLL) {
|
||||
SDL_assert(s_HIDDLLRefCount > 0);
|
||||
if (--s_HIDDLLRefCount == 0) {
|
||||
FreeLibrary(s_pHIDDLL);
|
||||
s_pHIDDLL = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_assert(s_HIDDLLRefCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !__WINRT__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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_hid_h_
|
||||
#define SDL_hid_h_
|
||||
|
||||
#include "SDL_windows.h"
|
||||
|
||||
#ifndef __WINRT__
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
typedef USHORT USAGE;
|
||||
typedef struct _HIDP_PREPARSED_DATA *PHIDP_PREPARSED_DATA;
|
||||
|
||||
typedef struct _HIDD_ATTRIBUTES
|
||||
{
|
||||
ULONG Size;
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
|
||||
typedef enum {
|
||||
HidP_Input = 0,
|
||||
HidP_Output = 1,
|
||||
HidP_Feature = 2
|
||||
} HIDP_REPORT_TYPE;
|
||||
|
||||
typedef struct {
|
||||
USAGE UsagePage;
|
||||
UCHAR ReportID;
|
||||
BOOLEAN IsAlias;
|
||||
USHORT BitField;
|
||||
USHORT LinkCollection;
|
||||
USAGE LinkUsage;
|
||||
USAGE LinkUsagePage;
|
||||
BOOLEAN IsRange;
|
||||
BOOLEAN IsStringRange;
|
||||
BOOLEAN IsDesignatorRange;
|
||||
BOOLEAN IsAbsolute;
|
||||
ULONG Reserved[ 10 ];
|
||||
union {
|
||||
struct {
|
||||
USAGE UsageMin;
|
||||
USAGE UsageMax;
|
||||
USHORT StringMin;
|
||||
USHORT StringMax;
|
||||
USHORT DesignatorMin;
|
||||
USHORT DesignatorMax;
|
||||
USHORT DataIndexMin;
|
||||
USHORT DataIndexMax;
|
||||
} Range;
|
||||
struct {
|
||||
USAGE Usage;
|
||||
USAGE Reserved1;
|
||||
USHORT StringIndex;
|
||||
USHORT Reserved2;
|
||||
USHORT DesignatorIndex;
|
||||
USHORT Reserved3;
|
||||
USHORT DataIndex;
|
||||
USHORT Reserved4;
|
||||
} NotRange;
|
||||
};
|
||||
} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS;
|
||||
|
||||
typedef struct {
|
||||
USAGE UsagePage;
|
||||
UCHAR ReportID;
|
||||
BOOLEAN IsAlias;
|
||||
USHORT BitField;
|
||||
USHORT LinkCollection;
|
||||
USAGE LinkUsage;
|
||||
USAGE LinkUsagePage;
|
||||
BOOLEAN IsRange;
|
||||
BOOLEAN IsStringRange;
|
||||
BOOLEAN IsDesignatorRange;
|
||||
BOOLEAN IsAbsolute;
|
||||
BOOLEAN HasNull;
|
||||
UCHAR Reserved;
|
||||
USHORT BitSize;
|
||||
USHORT ReportCount;
|
||||
USHORT Reserved2[ 5 ];
|
||||
ULONG UnitsExp;
|
||||
ULONG Units;
|
||||
LONG LogicalMin;
|
||||
LONG LogicalMax;
|
||||
LONG PhysicalMin;
|
||||
LONG PhysicalMax;
|
||||
union {
|
||||
struct {
|
||||
USAGE UsageMin;
|
||||
USAGE UsageMax;
|
||||
USHORT StringMin;
|
||||
USHORT StringMax;
|
||||
USHORT DesignatorMin;
|
||||
USHORT DesignatorMax;
|
||||
USHORT DataIndexMin;
|
||||
USHORT DataIndexMax;
|
||||
} Range;
|
||||
struct {
|
||||
USAGE Usage;
|
||||
USAGE Reserved1;
|
||||
USHORT StringIndex;
|
||||
USHORT Reserved2;
|
||||
USHORT DesignatorIndex;
|
||||
USHORT Reserved3;
|
||||
USHORT DataIndex;
|
||||
USHORT Reserved4;
|
||||
} NotRange;
|
||||
};
|
||||
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
|
||||
|
||||
typedef struct {
|
||||
USAGE Usage;
|
||||
USAGE UsagePage;
|
||||
USHORT InputReportByteLength;
|
||||
USHORT OutputReportByteLength;
|
||||
USHORT FeatureReportByteLength;
|
||||
USHORT Reserved[ 17 ];
|
||||
USHORT NumberLinkCollectionNodes;
|
||||
USHORT NumberInputButtonCaps;
|
||||
USHORT NumberInputValueCaps;
|
||||
USHORT NumberInputDataIndices;
|
||||
USHORT NumberOutputButtonCaps;
|
||||
USHORT NumberOutputValueCaps;
|
||||
USHORT NumberOutputDataIndices;
|
||||
USHORT NumberFeatureButtonCaps;
|
||||
USHORT NumberFeatureValueCaps;
|
||||
USHORT NumberFeatureDataIndices;
|
||||
} HIDP_CAPS, *PHIDP_CAPS;
|
||||
|
||||
typedef struct {
|
||||
USHORT DataIndex;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
ULONG RawValue;
|
||||
BOOLEAN On;
|
||||
};
|
||||
} HIDP_DATA, *PHIDP_DATA;
|
||||
|
||||
#define HIDP_ERROR_CODES( p1, p2 ) ((NTSTATUS)(((p1) << 28) | (0x11 << 16) | (p2)))
|
||||
#define HIDP_STATUS_SUCCESS HIDP_ERROR_CODES( 0x0, 0x0000 )
|
||||
#define HIDP_STATUS_NULL HIDP_ERROR_CODES( 0x8, 0x0001 )
|
||||
#define HIDP_STATUS_INVALID_PREPARSED_DATA HIDP_ERROR_CODES( 0xC, 0x0001 )
|
||||
#define HIDP_STATUS_INVALID_REPORT_TYPE HIDP_ERROR_CODES( 0xC, 0x0002 )
|
||||
#define HIDP_STATUS_INVALID_REPORT_LENGTH HIDP_ERROR_CODES( 0xC, 0x0003 )
|
||||
#define HIDP_STATUS_USAGE_NOT_FOUND HIDP_ERROR_CODES( 0xC, 0x0004 )
|
||||
#define HIDP_STATUS_VALUE_OUT_OF_RANGE HIDP_ERROR_CODES( 0xC, 0x0005 )
|
||||
#define HIDP_STATUS_BAD_LOG_PHY_VALUES HIDP_ERROR_CODES( 0xC, 0x0006 )
|
||||
#define HIDP_STATUS_BUFFER_TOO_SMALL HIDP_ERROR_CODES( 0xC, 0x0007 )
|
||||
#define HIDP_STATUS_INTERNAL_ERROR HIDP_ERROR_CODES( 0xC, 0x0008 )
|
||||
#define HIDP_STATUS_I8042_TRANS_UNKNOWN HIDP_ERROR_CODES( 0xC, 0x0009 )
|
||||
#define HIDP_STATUS_INCOMPATIBLE_REPORT_ID HIDP_ERROR_CODES( 0xC, 0x000A )
|
||||
#define HIDP_STATUS_NOT_VALUE_ARRAY HIDP_ERROR_CODES( 0xC, 0x000B )
|
||||
#define HIDP_STATUS_IS_VALUE_ARRAY HIDP_ERROR_CODES( 0xC, 0x000C )
|
||||
#define HIDP_STATUS_DATA_INDEX_NOT_FOUND HIDP_ERROR_CODES( 0xC, 0x000D )
|
||||
#define HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE HIDP_ERROR_CODES( 0xC, 0x000E )
|
||||
#define HIDP_STATUS_BUTTON_NOT_PRESSED HIDP_ERROR_CODES( 0xC, 0x000F )
|
||||
#define HIDP_STATUS_REPORT_DOES_NOT_EXIST HIDP_ERROR_CODES( 0xC, 0x0010 )
|
||||
#define HIDP_STATUS_NOT_IMPLEMENTED HIDP_ERROR_CODES( 0xC, 0x0020 )
|
||||
|
||||
|
||||
extern int WIN_LoadHIDDLL(void);
|
||||
extern void WIN_UnloadHIDDLL(void);
|
||||
|
||||
typedef BOOLEAN (WINAPI *HidD_GetString_t)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
|
||||
typedef BOOLEAN (WINAPI *HidD_GetPreparsedData_t)(HANDLE HidDeviceObject, PHIDP_PREPARSED_DATA *PreparsedData);
|
||||
typedef BOOLEAN (WINAPI *HidD_FreePreparsedData_t)(PHIDP_PREPARSED_DATA PreparsedData);
|
||||
typedef NTSTATUS (WINAPI *HidP_GetCaps_t)(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities);
|
||||
typedef NTSTATUS (WINAPI *HidP_GetButtonCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
|
||||
typedef NTSTATUS (WINAPI *HidP_GetValueCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
|
||||
typedef ULONG (WINAPI *HidP_MaxDataListLength_t)(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData);
|
||||
typedef NTSTATUS (WINAPI *HidP_GetData_t)(HIDP_REPORT_TYPE ReportType, PHIDP_DATA DataList, PULONG DataLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||
|
||||
extern HidD_GetString_t SDL_HidD_GetManufacturerString;
|
||||
extern HidD_GetString_t SDL_HidD_GetProductString;
|
||||
extern HidD_GetPreparsedData_t SDL_HidD_GetPreparsedData;
|
||||
extern HidD_FreePreparsedData_t SDL_HidD_FreePreparsedData;
|
||||
extern HidP_GetCaps_t SDL_HidP_GetCaps;
|
||||
extern HidP_GetButtonCaps_t SDL_HidP_GetButtonCaps;
|
||||
extern HidP_GetValueCaps_t SDL_HidP_GetValueCaps;
|
||||
extern HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength;
|
||||
extern HidP_GetData_t SDL_HidP_GetData;
|
||||
|
||||
#endif /* !__WINRT__ */
|
||||
|
||||
#endif /* SDL_hid_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+114
-4
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -24,9 +24,16 @@
|
||||
|
||||
#include "SDL_windows.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
|
||||
#if defined(HAVE_ROAPI_H)
|
||||
#include <roapi.h> /* For RoInitialize/RoUninitialize (Win32 only) */
|
||||
#else
|
||||
typedef enum RO_INIT_TYPE {
|
||||
RO_INIT_SINGLETHREADED = 0,
|
||||
RO_INIT_MULTITHREADED = 1
|
||||
} RO_INIT_TYPE;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT_VISTA
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
@@ -34,6 +41,13 @@
|
||||
#ifndef _WIN32_WINNT_WIN7
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WIN8
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
#endif
|
||||
|
||||
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
|
||||
#endif
|
||||
|
||||
|
||||
/* Sets an error message based on an HRESULT */
|
||||
@@ -42,8 +56,18 @@ WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
|
||||
{
|
||||
TCHAR buffer[1024];
|
||||
char *message;
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,
|
||||
TCHAR *p = buffer;
|
||||
DWORD c = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0,
|
||||
buffer, SDL_arraysize(buffer), NULL);
|
||||
buffer[c] = 0;
|
||||
/* kill CR/LF that FormatMessage() sticks at the end */
|
||||
while (*p) {
|
||||
if (*p == '\r') {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
message = WIN_StringToUTF8(buffer);
|
||||
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
|
||||
SDL_free(message);
|
||||
@@ -96,6 +120,65 @@ WIN_CoUninitialize(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __WINRT__
|
||||
void *
|
||||
WIN_LoadComBaseFunction(const char *name)
|
||||
{
|
||||
static SDL_bool s_bLoaded;
|
||||
static HMODULE s_hComBase;
|
||||
|
||||
if (!s_bLoaded) {
|
||||
s_hComBase = LoadLibraryEx(TEXT("combase.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
s_bLoaded = SDL_TRUE;
|
||||
}
|
||||
if (s_hComBase) {
|
||||
return GetProcAddress(s_hComBase, name);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT
|
||||
WIN_RoInitialize(void)
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
return S_OK;
|
||||
#else
|
||||
typedef HRESULT (WINAPI *RoInitialize_t)(RO_INIT_TYPE initType);
|
||||
RoInitialize_t RoInitializeFunc = (RoInitialize_t)WIN_LoadComBaseFunction("RoInitialize");
|
||||
if (RoInitializeFunc) {
|
||||
/* RO_INIT_SINGLETHREADED is equivalent to COINIT_APARTMENTTHREADED */
|
||||
HRESULT hr = RoInitializeFunc(RO_INIT_SINGLETHREADED);
|
||||
if (hr == RPC_E_CHANGED_MODE) {
|
||||
hr = RoInitializeFunc(RO_INIT_MULTITHREADED);
|
||||
}
|
||||
|
||||
/* S_FALSE means success, but someone else already initialized. */
|
||||
/* You still need to call RoUninitialize in this case! */
|
||||
if (hr == S_FALSE) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WIN_RoUninitialize(void)
|
||||
{
|
||||
#ifndef __WINRT__
|
||||
typedef void (WINAPI *RoUninitialize_t)(void);
|
||||
RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize");
|
||||
if (RoUninitializeFunc) {
|
||||
RoUninitializeFunc();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __WINRT__
|
||||
static BOOL
|
||||
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
@@ -136,6 +219,15 @@ BOOL WIN_IsWindows7OrGreater(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL WIN_IsWindows8OrGreater(void)
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
return TRUE;
|
||||
#else
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 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
|
||||
@@ -228,6 +320,24 @@ WIN_IsEqualIID(REFIID a, REFIID b)
|
||||
return (SDL_memcmp(a, b, sizeof (*a)) == 0);
|
||||
}
|
||||
|
||||
void
|
||||
WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect)
|
||||
{
|
||||
sdlrect->x = winrect->left;
|
||||
sdlrect->w = (winrect->right - winrect->left) + 1;
|
||||
sdlrect->y = winrect->top;
|
||||
sdlrect->h = (winrect->bottom - winrect->top) + 1;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect)
|
||||
{
|
||||
winrect->left = sdlrect->x;
|
||||
winrect->right = sdlrect->x + sdlrect->w - 1;
|
||||
winrect->top = sdlrect->y;
|
||||
winrect->bottom = sdlrect->y + sdlrect->h - 1;
|
||||
}
|
||||
|
||||
#endif /* __WIN32__ || __WINRT__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
+33
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -37,14 +37,24 @@
|
||||
#include <windows.h>
|
||||
#include <basetyps.h> /* for REFIID with broken mingw.org headers */
|
||||
|
||||
#include "SDL_rect.h"
|
||||
|
||||
/* 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
|
||||
#define WIN_StringToUTF8W(S) SDL_iconv_string("UTF-8", "UTF-16LE", (const char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR))
|
||||
#define WIN_UTF8ToStringW(S) (WCHAR *)SDL_iconv_string("UTF-16LE", "UTF-8", (const char *)(S), SDL_strlen(S)+1)
|
||||
/* !!! 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)
|
||||
#define WIN_StringToUTF8A(S) SDL_iconv_string("UTF-8", "ASCII", (const char *)(S), (SDL_strlen(S)+1))
|
||||
#define WIN_UTF8ToStringA(S) SDL_iconv_string("ASCII", "UTF-8", (const char *)(S), SDL_strlen(S)+1)
|
||||
#if UNICODE
|
||||
#define WIN_StringToUTF8 WIN_StringToUTF8W
|
||||
#define WIN_UTF8ToString WIN_UTF8ToStringW
|
||||
#define SDL_tcslen SDL_wcslen
|
||||
#define SDL_tcsstr SDL_wcsstr
|
||||
#else
|
||||
#define WIN_StringToUTF8 WIN_StringToUTF8A
|
||||
#define WIN_UTF8ToString WIN_UTF8ToStringA
|
||||
#define SDL_tcslen SDL_strlen
|
||||
#define SDL_tcsstr SDL_strstr
|
||||
#endif
|
||||
|
||||
/* Sets an error message based on a given HRESULT */
|
||||
@@ -53,16 +63,28 @@ 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);
|
||||
|
||||
#if !defined(__WINRT__)
|
||||
/* Load a function from combase.dll */
|
||||
void *WIN_LoadComBaseFunction(const char *name);
|
||||
#endif
|
||||
|
||||
/* Wrap up the oddities of CoInitialize() into a common function. */
|
||||
extern HRESULT WIN_CoInitialize(void);
|
||||
extern void WIN_CoUninitialize(void);
|
||||
|
||||
/* Wrap up the oddities of RoInitialize() into a common function. */
|
||||
extern HRESULT WIN_RoInitialize(void);
|
||||
extern void WIN_RoUninitialize(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);
|
||||
|
||||
/* Returns SDL_TRUE if we're running on Windows 8 and newer */
|
||||
extern BOOL WIN_IsWindows8OrGreater(void);
|
||||
|
||||
/* You need to SDL_free() the result of this call. */
|
||||
extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);
|
||||
|
||||
@@ -70,6 +92,10 @@ extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);
|
||||
extern BOOL WIN_IsEqualGUID(const GUID * a, const GUID * b);
|
||||
extern BOOL WIN_IsEqualIID(REFIID a, REFIID b);
|
||||
|
||||
/* Convert between SDL_rect and RECT */
|
||||
extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect);
|
||||
extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect);
|
||||
|
||||
#endif /* _INCLUDED_WINDOWS_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
+9
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_xinput.h"
|
||||
|
||||
|
||||
@@ -82,18 +81,22 @@ WIN_LoadXInputDLL(void)
|
||||
return 0; /* already loaded */
|
||||
}
|
||||
|
||||
/* NOTE: Don't load XinputUap.dll
|
||||
* This is XInput emulation over Windows.Gaming.Input, and has all the
|
||||
* limitations of that API (no devices at startup, no background input, etc.)
|
||||
*/
|
||||
version = (1 << 16) | 4;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_4.dll"); /* 1.4 Ships with Windows 8. */
|
||||
s_pXInputDLL = LoadLibrary(TEXT("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. */
|
||||
s_pXInputDLL = LoadLibrary(TEXT("XInput1_3.dll")); /* 1.3 can be installed as a redistributable component. */
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
|
||||
s_pXInputDLL = LoadLibrary(TEXT("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");
|
||||
s_pXInputDLL = LoadLibrary(TEXT("XInput9_1_0.dll"));
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
return -1;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_main.h"
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_winrtapp_direct3d.h"
|
||||
#include "SDL_winrtapp_xaml.h"
|
||||
@@ -29,7 +30,7 @@
|
||||
int (*WINRT_SDLAppEntryPoint)(int, char **) = NULL;
|
||||
|
||||
extern "C" DECLSPEC int
|
||||
SDL_WinRTRunApp(int (*mainFunction)(int, char **), void * xamlBackgroundPanel)
|
||||
SDL_WinRTRunApp(SDL_main_func mainFunction, void * xamlBackgroundPanel)
|
||||
{
|
||||
if (xamlBackgroundPanel) {
|
||||
return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel);
|
||||
@@ -63,4 +64,4 @@ SDL_WinRTGetDeviceFamily()
|
||||
#endif
|
||||
|
||||
return SDL_WINRT_DEVICEFAMILY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
+15
-73
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -47,10 +47,8 @@ using namespace Windows::Phone::UI::Input;
|
||||
|
||||
/* 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"
|
||||
@@ -121,68 +119,6 @@ int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **))
|
||||
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()
|
||||
{
|
||||
@@ -399,10 +335,6 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
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
|
||||
@@ -425,9 +357,16 @@ void SDL_WinRTApp::Run()
|
||||
{
|
||||
// TODO, WinRT: pass the C-style main() a reasonably realistic
|
||||
// representation of command line arguments.
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
int argc = 1;
|
||||
char **argv = (char **)SDL_malloc(2 * sizeof(*argv));
|
||||
if (!argv) {
|
||||
return;
|
||||
}
|
||||
argv[0] = SDL_strdup("WinRTApp");
|
||||
argv[1] = NULL;
|
||||
WINRT_SDLAppEntryPoint(argc, argv);
|
||||
SDL_free(argv[0]);
|
||||
SDL_free(argv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,15 +670,18 @@ void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
|
||||
static void
|
||||
WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
|
||||
{
|
||||
Uint8 button, pressed;
|
||||
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",
|
||||
WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed);
|
||||
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n",
|
||||
header,
|
||||
pt->Position.X, pt->Position.Y,
|
||||
transformedPoint.X, transformedPoint.Y,
|
||||
pt->Properties->MouseWheelDelta,
|
||||
pt->FrameId,
|
||||
pt->PointerId,
|
||||
WINRT_GetSDLButtonForPointerPoint(pt));
|
||||
button,
|
||||
pressed);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
@@ -115,7 +115,7 @@ SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void * backgroundPanelAs
|
||||
|
||||
// Make sure we have a valid XAML element (to draw onto):
|
||||
if ( ! backgroundPanelAsIInspectable) {
|
||||
return SDL_SetError("'backgroundPanelAsIInspectable' can't be NULL");
|
||||
return SDL_InvalidParamError("backgroundPanelAsIInspectable");
|
||||
}
|
||||
|
||||
Platform::Object ^ backgroundPanel = reinterpret_cast<Object ^>((IInspectable *) backgroundPanelAsIInspectable);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 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
|
||||
|
||||
Reference in New Issue
Block a user