Files
xserver_xsdl/hw/kdrive/sdl/sdl_input.c
2020-01-09 20:59:34 +02:00

283 lines
8.0 KiB
C

/*
* Copyright © 2004 PillowElephantBadgerBankPond
* Copyright © 2014-2019 Sergii Pylypenko
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of PillowElephantBadgerBankPond not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. PillowElephantBadgerBankPond makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* PillowElephantBadgerBankPond DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL PillowElephantBadgerBankPond BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* It's really not my fault - see it was the elephants!!
* - jaymz
*
*/
#include "sdl_send_text.h"
#include "sdl_kdrive.h"
#include "sdl_input.h"
#include "sdl_screen_buttons.h"
#include <xorg-config.h>
#include "kdrive.h"
#include "dix.h"
#include <SDL/SDL.h>
#include <X11/keysym.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pthread.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#ifdef __ANDROID__
#include <SDL/SDL_screenkeyboard.h>
#include <android/log.h>
// DEBUG
#define printf(...) __android_log_print(ANDROID_LOG_INFO, "XSDL", __VA_ARGS__)
#endif
static int sdlInputNotifyFd[2] = { -1, -1 };
static int mouseState = 0;
enum sdlKeyboardType_t { KB_NATIVE = 0, KB_BUILTIN = 1, KB_BOTH = 2 };
enum sdlKeyboardType_t sdlKeyboardType = KB_NATIVE;
void sdlInitInput(void)
{
if (getenv("XSDL_BUILTIN_KEYBOARD") != NULL)
{
sdlKeyboardType = atoi(getenv("XSDL_BUILTIN_KEYBOARD")) == KB_NATIVE ? KB_NATIVE :
atoi(getenv("XSDL_BUILTIN_KEYBOARD")) == KB_BUILTIN ? KB_BUILTIN : KB_BOTH;
}
unsetenv("XSDL_BUILTIN_KEYBOARD");
printf("sdlKeyboardType %d\n", sdlKeyboardType);
}
void sdlPollInput(void)
{
static int buttonState=0;
static int pressure = 0;
SDL_Event event;
//printf("sdlPollInput() %d thread %d fd %d\n", SDL_GetTicks(), (int) pthread_self(), sdlInputNotifyFd[0]);
while ( SDL_PollEvent(&event) ) {
switch (event.type) {
case SDL_MOUSEMOTION:
//printf("SDL_MOUSEMOTION pressure %d\n", pressure);
KdEnqueuePointerEvent(sdlPointer, mouseState, event.motion.x, event.motion.y, pressure);
setScreenButtons(event.motion.x);
break;
case SDL_MOUSEBUTTONDOWN:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
buttonState = KD_BUTTON_1;
break;
case SDL_BUTTON_MIDDLE:
buttonState = KD_BUTTON_2;
break;
case SDL_BUTTON_RIGHT:
buttonState = KD_BUTTON_3;
break;
case SDL_BUTTON_WHEELUP:
buttonState = KD_BUTTON_4;
break;
case SDL_BUTTON_WHEELDOWN:
buttonState = KD_BUTTON_5;
break;
/*
case SDL_BUTTON_X1:
buttonState = KD_BUTTON_6;
break;
case SDL_BUTTON_X2:
buttonState = KD_BUTTON_7;
break;
*/
default:
buttonState = 1 << (event.button.button - 1);
break;
}
mouseState |= buttonState;
KdEnqueuePointerEvent(sdlPointer, mouseState|KD_MOUSE_DELTA, 0, 0, pressure);
break;
case SDL_MOUSEBUTTONUP:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
buttonState = KD_BUTTON_1;
pressure = 0;
break;
case SDL_BUTTON_MIDDLE:
buttonState = KD_BUTTON_2;
break;
case SDL_BUTTON_RIGHT:
buttonState = KD_BUTTON_3;
break;
case SDL_BUTTON_WHEELUP:
buttonState = KD_BUTTON_4;
break;
case SDL_BUTTON_WHEELDOWN:
buttonState = KD_BUTTON_5;
break;
/*
case SDL_BUTTON_X1:
buttonState = KD_BUTTON_6;
break;
case SDL_BUTTON_X2:
buttonState = KD_BUTTON_7;
break;
*/
default:
buttonState = 1 << (event.button.button - 1);
break;
}
mouseState &= ~buttonState;
KdEnqueuePointerEvent(sdlPointer, mouseState|KD_MOUSE_DELTA, 0, 0, pressure);
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
//printf("Key sym %d scancode %d unicode %d", event.key.keysym.sym, event.key.keysym.scancode, event.key.keysym.unicode);
#ifdef __ANDROID__
if (event.key.keysym.sym == SDLK_HELP)
{
if(event.type == SDL_KEYUP)
{
// SDL_ANDROID_ToggleScreenKeyboardWithoutTextInput();
static int keyboard = -1;
keyboard++;
//SDL_Delay(150);
if (keyboard >= 2 || (sdlKeyboardType != KB_BOTH && keyboard >= 1))
{
if (SDL_IsScreenKeyboardShown(NULL))
{
SDL_HideScreenKeyboard(NULL);
SDL_Flip(SDL_GetVideoSurface());
}
else
{
keyboard = 0;
}
}
if (keyboard == 0)
{
//SDL_Delay(100);
if (sdlKeyboardType == KB_NATIVE || sdlKeyboardType == KB_BOTH)
SDL_ANDROID_ToggleScreenKeyboardWithoutTextInput();
if (sdlKeyboardType == KB_BUILTIN)
SDL_ANDROID_ToggleInternalScreenKeyboard(SDL_KEYBOARD_QWERTY);
SDL_Flip(SDL_GetVideoSurface());
}
if (keyboard == 1 && sdlKeyboardType == KB_BOTH)
{
//SDL_Delay(100);
SDL_ANDROID_ToggleInternalScreenKeyboard(SDL_KEYBOARD_QWERTY);
SDL_Flip(SDL_GetVideoSurface());
}
}
setScreenButtons(10000);
}
else
#endif
if (event.key.keysym.sym == SDLK_UNDO)
{
if(event.type == SDL_KEYUP)
{
// Send Ctrl-Z
KdEnqueueKeyboardEvent (sdlKeyboard, 37, 0); // LCTRL
KdEnqueueKeyboardEvent (sdlKeyboard, 52, 0); // Z
KdEnqueueKeyboardEvent (sdlKeyboard, 52, 1); // Z
KdEnqueueKeyboardEvent (sdlKeyboard, 37, 1); // LCTRL
}
}
else if((event.key.keysym.unicode & 0xFF80) != 0)
{
send_unicode (event.key.keysym.unicode);
}
else
KdEnqueueKeyboardEvent (sdlKeyboard, event.key.keysym.scancode, event.type==SDL_KEYUP);
// Force SDL screen update, so SDL virtual on-screen buttons will change their images
{
SDL_Rect r = {0, 0, 1, 1};
SDL_UpdateRects(SDL_GetVideoSurface(), 1, &r);
}
break;
case SDL_JOYAXISMOTION:
if (event.jaxis.which == 0 && event.jaxis.axis == 4 && pressure != event.jaxis.value)
{
pressure = event.jaxis.value;
if (mouseState & KD_BUTTON_1)
KdEnqueuePointerEvent(sdlPointer, mouseState|KD_MOUSE_DELTA, 0, 0, pressure);
}
break;
case SDL_ACTIVEEVENT:
// We need this to re-init OpenGL and redraw screen
// And we need to also call this when OpenGL context was destroyed
// Oherwise SDL will stuck and we will get a permanent black screen
SDL_Flip(SDL_GetVideoSurface());
break;
case SDL_SYSWMEVENT:
process_clipboard_event(&event.syswm);
break;
//case SDL_QUIT:
/* this should never happen */
//SDL_Quit(); // SDL_Quit() on Android is buggy
}
}
/*
if ( nextFullScreenRefresh && nextFullScreenRefresh < SDL_GetTicks() )
{
//printf("SDL_Flip from sdlPollInput");
SDL_Flip(SDL_GetVideoSurface());
nextFullScreenRefresh = 0;
}
*/
}
static int sdlEventNotifyCbk(const SDL_Event *event)
{
// Called from random thread, not from main thread
//printf("==> sdlEventNotifyCbk() event %d thread %d\n", event->type, (int) pthread_self());
write(sdlInputNotifyFd[1], "1", 1);
return 1;
}
int sdlGetInputNotifyFd(void)
{
if ( sdlInputNotifyFd[0] != -1 )
return sdlInputNotifyFd[0];
if ( pipe2(sdlInputNotifyFd, O_NONBLOCK) != 0 )
{
printf("Error calling pipe()!");
exit(1);
}
SDL_SetEventFilter(&sdlEventNotifyCbk);
return sdlInputNotifyFd[0];
}