|
@@ -189,6 +189,7 @@
|
|
|
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
|
|
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
|
|
#include <pthread.h> // POSIX threads management (mouse input)
|
|
|
+ #include <dirent.h> // POSIX directory browsing
|
|
|
|
|
|
#include <sys/ioctl.h> // UNIX System call for device-specific input/output operations - ioctl()
|
|
|
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
|
@@ -223,9 +224,8 @@
|
|
|
#if defined(PLATFORM_RPI)
|
|
|
// Old device inputs system
|
|
|
#define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input
|
|
|
- #define DEFAULT_MOUSE_DEV "/dev/input/mouse0" // Mouse input
|
|
|
- #define DEFAULT_TOUCH_DEV "/dev/input/event4" // Touch input virtual device (created by ts_uinput)
|
|
|
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
|
|
|
+ #define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
|
|
|
|
// New device input events (evdev) (must be detected)
|
|
|
//#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN"
|
|
@@ -329,11 +329,22 @@ static int currentMouseWheelY = 0; // Registers current mouse wheel
|
|
|
|
|
|
#if defined(PLATFORM_RPI)
|
|
|
static int mouseStream = -1; // Mouse device file descriptor
|
|
|
-static bool mouseReady = false; // Flag to know if mouse is ready
|
|
|
-static pthread_t mouseThreadId; // Mouse reading thread id
|
|
|
-static int touchStream = -1; // Touch device file descriptor
|
|
|
-static bool touchReady = false; // Flag to know if touch interface is ready
|
|
|
-static pthread_t touchThreadId; // Touch reading thread id
|
|
|
+static char currentMouseStateEvdev[3] = { 0 }; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update)
|
|
|
+typedef struct {
|
|
|
+ pthread_t threadId; // Event reading thread id
|
|
|
+ int fd; // File descriptor to the device it is assigned to
|
|
|
+ float sensitivity; // Sensitivitzy multiplier for relative mouse movements
|
|
|
+ Rectangle absRange; // Range of values for absolute pointing devices (touchscreens)
|
|
|
+ int touchSlot; // Hold the touch slot number of the currently being sent multitouch block
|
|
|
+ bool isMouse; // True if device supports relative X Y movements
|
|
|
+ bool isTouch; // True if device supports absolute X Y movements and has BTN_TOUCH
|
|
|
+ bool isMultitouch; // True if device supports multiple absolute movevents and has BTN_TOUCH
|
|
|
+ bool isKeyboard; // True if device has letter keycodes
|
|
|
+ bool isGamepad; // True if device has gamepad buttons
|
|
|
+}InputEventWorker;
|
|
|
+
|
|
|
+static InputEventWorker eventWorkers[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
|
|
+
|
|
|
#endif
|
|
|
#if defined(PLATFORM_WEB)
|
|
|
static bool toggleCursorLock = false; // Ask for cursor pointer lock on next click
|
|
@@ -447,9 +458,8 @@ static void InitKeyboard(void); // Init raw keyboard sys
|
|
|
static void ProcessKeyboard(void); // Process keyboard events
|
|
|
static void RestoreKeyboard(void); // Restore keyboard system
|
|
|
static void InitMouse(void); // Mouse initialization (including mouse thread)
|
|
|
-static void *MouseThread(void *arg); // Mouse reading thread
|
|
|
-static void InitTouch(void); // Touch device initialization (including touch thread)
|
|
|
-static void *TouchThread(void *arg); // Touch device reading thread
|
|
|
+static void EventThreadSpawn(char* device); // Indetifies a input device and spawns a thread to handle it if needed
|
|
|
+static void *EventThread(void *arg); // Input device event reading thread
|
|
|
static void InitGamepad(void); // Init raw gamepad input
|
|
|
static void *GamepadThread(void *arg); // Mouse reading thread
|
|
|
#endif
|
|
@@ -566,7 +576,6 @@ void InitWindow(int width, int height, const char *title)
|
|
|
#if defined(PLATFORM_RPI)
|
|
|
// Init raw input system
|
|
|
InitMouse(); // Mouse init
|
|
|
- InitTouch(); // Touch init
|
|
|
InitKeyboard(); // Keyboard init
|
|
|
InitGamepad(); // Gamepad init
|
|
|
#endif
|
|
@@ -661,8 +670,13 @@ void CloseWindow(void)
|
|
|
|
|
|
windowShouldClose = true; // Added to force threads to exit when the close window is called
|
|
|
|
|
|
- pthread_join(mouseThreadId, NULL);
|
|
|
- pthread_join(touchThreadId, NULL);
|
|
|
+ for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
|
|
|
+ {
|
|
|
+ if(eventWorkers[i].threadId == 0)
|
|
|
+ {
|
|
|
+ pthread_join(eventWorkers[i].threadId, NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
pthread_join(gamepadThreadId, NULL);
|
|
|
#endif
|
|
|
|
|
@@ -1984,7 +1998,7 @@ bool IsMouseButtonPressed(int button)
|
|
|
#else
|
|
|
if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 1)) pressed = true;
|
|
|
#endif
|
|
|
-
|
|
|
+
|
|
|
return pressed;
|
|
|
}
|
|
|
|
|
@@ -2128,7 +2142,9 @@ Vector2 GetTouchPosition(int index)
|
|
|
position.x = position.x*((float)renderWidth/(float)displayWidth) - renderOffsetX/2;
|
|
|
position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2;
|
|
|
}
|
|
|
-#else // PLATFORM_DESKTOP, PLATFORM_RPI
|
|
|
+#elif defined(PLATFORM_RPI)
|
|
|
+ position = touchPosition[index];
|
|
|
+#else // PLATFORM_DESKTOP
|
|
|
if (index == 0) position = GetMousePosition();
|
|
|
#endif
|
|
|
|
|
@@ -2895,6 +2911,21 @@ static void PollInputEvents(void)
|
|
|
gamepadAxisCount = 0;
|
|
|
#endif
|
|
|
|
|
|
+#if defined(PLATFORM_RPI)
|
|
|
+ // Register previous keys states
|
|
|
+ for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
|
|
|
+
|
|
|
+ // Register previous mouse states
|
|
|
+ previousMouseWheelY = currentMouseWheelY;
|
|
|
+ currentMouseWheelY = 0;
|
|
|
+ for (int i = 0; i < 3; i++)
|
|
|
+ {
|
|
|
+ previousMouseState[i] = currentMouseState[i];
|
|
|
+ currentMouseState[i] = currentMouseStateEvdev[i];
|
|
|
+ }
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
|
// Mouse input polling
|
|
|
double mouseX;
|
|
@@ -3829,182 +3860,351 @@ static void RestoreKeyboard(void)
|
|
|
// Mouse initialization (including mouse thread)
|
|
|
static void InitMouse(void)
|
|
|
{
|
|
|
- // NOTE: We can use /dev/input/mice to read from all available mice
|
|
|
- if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0)
|
|
|
+ char Path[256];
|
|
|
+ DIR *d;
|
|
|
+ struct dirent *dir;
|
|
|
+
|
|
|
+ // Reset variables
|
|
|
+ for (int i = 0; i < MAX_TOUCH_POINTS; ++i)
|
|
|
+ {
|
|
|
+ touchPosition[i].x = -1;
|
|
|
+ touchPosition[i].y = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Open the linux directory of "/dev/input"
|
|
|
+ d = opendir(DEFAULT_EVDEV_PATH);
|
|
|
+ if (d)
|
|
|
{
|
|
|
- TraceLog(LOG_WARNING, "Mouse device could not be opened, no mouse available");
|
|
|
+ while ((dir = readdir(d)) != NULL)
|
|
|
+ {
|
|
|
+ if(strncmp("event", dir->d_name, strlen("event")) == 0) // Search for devices named "event*"
|
|
|
+ {
|
|
|
+ sprintf(Path, "%s%s", DEFAULT_EVDEV_PATH, dir->d_name);
|
|
|
+ EventThreadSpawn(Path); // Identify the device and spawn a thread for it
|
|
|
+ }
|
|
|
+ }
|
|
|
+ closedir(d);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- mouseReady = true;
|
|
|
-
|
|
|
- int error = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL);
|
|
|
-
|
|
|
- if (error != 0) TraceLog(LOG_WARNING, "Error creating mouse input event thread");
|
|
|
- else TraceLog(LOG_INFO, "Mouse device initialized successfully");
|
|
|
+ TraceLog(LOG_WARNING, "Unable to open linux event directory %s", DEFAULT_EVDEV_PATH);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Mouse reading thread
|
|
|
-// NOTE: We need a separate thread to avoid loosing mouse events,
|
|
|
-// if too much time passes between reads, queue gets full and new events override older ones...
|
|
|
-static void *MouseThread(void *arg)
|
|
|
-{
|
|
|
- const unsigned char XSIGN = (1 << 4);
|
|
|
- const unsigned char YSIGN = (1 << 5);
|
|
|
-
|
|
|
- typedef struct {
|
|
|
- char buttons;
|
|
|
- char dx, dy;
|
|
|
- } MouseEvent;
|
|
|
-
|
|
|
- MouseEvent mouse;
|
|
|
+static void EventThreadSpawn(char* device)
|
|
|
+{
|
|
|
+ #define BITS_PER_LONG (sizeof(long) * 8)
|
|
|
+ #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
|
|
|
+ #define OFF(x) ((x)%BITS_PER_LONG)
|
|
|
+ #define BIT(x) (1UL<<OFF(x))
|
|
|
+ #define LONG(x) ((x)/BITS_PER_LONG)
|
|
|
+ #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
|
|
|
+ struct input_absinfo absinfo;
|
|
|
+ unsigned long ev_bits[NBITS(EV_MAX)];
|
|
|
+ unsigned long abs_bits[NBITS(ABS_MAX)];
|
|
|
+ unsigned long rel_bits[NBITS(REL_MAX)];
|
|
|
+ unsigned long key_bits[NBITS(KEY_MAX)];
|
|
|
+ bool hasAbs = false;
|
|
|
+ bool hasRel = false;
|
|
|
+ bool hasAbsMulti = false;
|
|
|
+ int FreeWorkerId = -1;
|
|
|
+ int fd = -1;
|
|
|
+ InputEventWorker* Worker;
|
|
|
+
|
|
|
+ /////////////////////////////////// Open the device and allocate worker /////////////////////////////////////////////
|
|
|
+
|
|
|
+ // Find a free spot in the workers array
|
|
|
+ for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
|
|
|
+ {
|
|
|
+ if(eventWorkers[i].threadId == 0)
|
|
|
+ {
|
|
|
+ FreeWorkerId = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- int mouseRelX = 0;
|
|
|
- int mouseRelY = 0;
|
|
|
+ // Select the free worker from array
|
|
|
+ if(FreeWorkerId >= 0)
|
|
|
+ {
|
|
|
+ Worker = &(eventWorkers[FreeWorkerId]); // Grab a pointer to the worker
|
|
|
+ memset(Worker, 0, sizeof(InputEventWorker)); // Clear the worker
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TraceLog(LOG_WARNING, "Error creating input device thread for '%s': Out of worker slots", device);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- while (!windowShouldClose)
|
|
|
+ // Open the device
|
|
|
+ fd = open(device, O_RDONLY | O_NONBLOCK);
|
|
|
+ if(fd < 0)
|
|
|
{
|
|
|
- if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent))
|
|
|
- {
|
|
|
- if ((mouse.buttons & 0x08) == 0) break; // This bit should always be set
|
|
|
+ TraceLog(LOG_WARNING, "Error creating input device thread for '%s': Can't open device (Err: %d)", device, Worker->fd);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Worker->fd = fd;
|
|
|
|
|
|
- // Check Left button pressed
|
|
|
- if ((mouse.buttons & 0x01) > 0) currentMouseState[0] = 1;
|
|
|
- else currentMouseState[0] = 0;
|
|
|
+ // At this point we have a connection to the device,
|
|
|
+ // but we don't yet know what the device is (Could be
|
|
|
+ // many things, even as simple as a power button)
|
|
|
|
|
|
- // Check Right button pressed
|
|
|
- if ((mouse.buttons & 0x02) > 0) currentMouseState[1] = 1;
|
|
|
- else currentMouseState[1] = 0;
|
|
|
+ /////////////////////////////////// Identify the device /////////////////////////////////////////////
|
|
|
|
|
|
- // Check Middle button pressed
|
|
|
- if ((mouse.buttons & 0x04) > 0) currentMouseState[2] = 1;
|
|
|
- else currentMouseState[2] = 0;
|
|
|
+ ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); // Read a bitfield of the avalable device properties
|
|
|
+
|
|
|
+ // Check for absolute input devices
|
|
|
+ if (TEST_BIT(ev_bits, EV_ABS))
|
|
|
+ {
|
|
|
+ ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)),abs_bits);
|
|
|
|
|
|
- mouseRelX = (int)mouse.dx;
|
|
|
- mouseRelY = (int)mouse.dy;
|
|
|
+ // Check for absolute movement support (usualy touchscreens, but also joysticks)
|
|
|
+ if (TEST_BIT(abs_bits, ABS_X) && TEST_BIT(abs_bits, ABS_Y))
|
|
|
+ {
|
|
|
+ hasAbs = true;
|
|
|
+ // Get the scaling values
|
|
|
+ ioctl(fd, EVIOCGABS(ABS_X), &absinfo);
|
|
|
+ Worker->absRange.x = absinfo.minimum;
|
|
|
+ Worker->absRange.width = absinfo.maximum - absinfo.minimum;
|
|
|
+ ioctl(fd, EVIOCGABS(ABS_Y), &absinfo);
|
|
|
+ Worker->absRange.y = absinfo.minimum;
|
|
|
+ Worker->absRange.height = absinfo.maximum - absinfo.minimum;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check for multiple absolute movement support (usualy multitouch touchscreens)
|
|
|
+ if (TEST_BIT(abs_bits, ABS_MT_POSITION_X) && TEST_BIT(abs_bits, ABS_MT_POSITION_Y))
|
|
|
+ {
|
|
|
+ hasAbsMulti = true;
|
|
|
+ // Get the scaling values
|
|
|
+ ioctl(fd, EVIOCGABS(ABS_X), &absinfo);
|
|
|
+ Worker->absRange.x = absinfo.minimum;
|
|
|
+ Worker->absRange.width = absinfo.maximum - absinfo.minimum;
|
|
|
+ ioctl(fd, EVIOCGABS(ABS_Y), &absinfo);
|
|
|
+ Worker->absRange.y = absinfo.minimum;
|
|
|
+ Worker->absRange.height = absinfo.maximum - absinfo.minimum;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX);
|
|
|
- if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY);
|
|
|
+ // Check for relative movement support (usualy mouse)
|
|
|
+ if (TEST_BIT(ev_bits, EV_REL))
|
|
|
+ {
|
|
|
+ ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)),rel_bits);
|
|
|
+ if (TEST_BIT(rel_bits, REL_X) && TEST_BIT(rel_bits, REL_Y))
|
|
|
+ {
|
|
|
+ hasRel = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // NOTE: Mouse movement is normalized to not be screen resolution dependant
|
|
|
- // We suppose 2*255 (max relative movement) is equivalent to screenWidth (max pixels width)
|
|
|
- // Result after normalization is multiplied by MOUSE_SENSITIVITY factor
|
|
|
+ // Check for button support to determine the device type(usualy on all input devices)
|
|
|
+ if (TEST_BIT(ev_bits, EV_KEY))
|
|
|
+ {
|
|
|
+ ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)),key_bits);
|
|
|
|
|
|
- mousePosition.x += (float)mouseRelX*((float)screenWidth/(2*255))*MOUSE_SENSITIVITY;
|
|
|
- mousePosition.y -= (float)mouseRelY*((float)screenHeight/(2*255))*MOUSE_SENSITIVITY;
|
|
|
+ if(hasAbs || hasAbsMulti)
|
|
|
+ {
|
|
|
+ if(TEST_BIT(key_bits, BTN_TOUCH))
|
|
|
+ Worker->isTouch = true; // This is a touchscreen
|
|
|
+ if(TEST_BIT(key_bits, BTN_TOOL_FINGER))
|
|
|
+ Worker->isTouch = true; // This is a drawing tablet
|
|
|
+ if(TEST_BIT(key_bits, BTN_TOOL_PEN))
|
|
|
+ Worker->isTouch = true; // This is a drawing tablet
|
|
|
+ if(TEST_BIT(key_bits, BTN_STYLUS))
|
|
|
+ Worker->isTouch = true; // This is a drawing tablet
|
|
|
+ if(Worker->isTouch || hasAbsMulti)
|
|
|
+ Worker->isMultitouch = true; // This is a multitouch capable device
|
|
|
+ }
|
|
|
|
|
|
- if (mousePosition.x < 0) mousePosition.x = 0;
|
|
|
- if (mousePosition.y < 0) mousePosition.y = 0;
|
|
|
+ if(hasRel)
|
|
|
+ {
|
|
|
+ if (TEST_BIT(key_bits, BTN_LEFT))
|
|
|
+ Worker->isMouse = true; // This is a mouse
|
|
|
+ if (TEST_BIT(key_bits, BTN_RIGHT))
|
|
|
+ Worker->isMouse = true; // This is a mouse
|
|
|
+ }
|
|
|
|
|
|
- if (mousePosition.x > screenWidth) mousePosition.x = screenWidth;
|
|
|
- if (mousePosition.y > screenHeight) mousePosition.y = screenHeight;
|
|
|
- }
|
|
|
- //else read(mouseStream, &mouse, 1); // Try to sync up again
|
|
|
+ if (TEST_BIT(key_bits, BTN_A))
|
|
|
+ Worker->isGamepad = true; // This is a gamepad
|
|
|
+ if (TEST_BIT(key_bits, BTN_TRIGGER))
|
|
|
+ Worker->isGamepad = true; // This is a gamepad
|
|
|
+ if (TEST_BIT(key_bits, BTN_START))
|
|
|
+ Worker->isGamepad = true; // This is a gamepad
|
|
|
+ if (TEST_BIT(key_bits, BTN_TL))
|
|
|
+ Worker->isGamepad = true; // This is a gamepad
|
|
|
+ if (TEST_BIT(key_bits, BTN_TL))
|
|
|
+ Worker->isGamepad = true; // This is a gamepad
|
|
|
+
|
|
|
+ if (TEST_BIT(key_bits, KEY_SPACE))
|
|
|
+ Worker->isKeyboard = true; // This is a keyboard
|
|
|
}
|
|
|
|
|
|
- return NULL;
|
|
|
-}
|
|
|
|
|
|
-// Touch initialization (including touch thread)
|
|
|
-static void InitTouch(void)
|
|
|
-{
|
|
|
- if ((touchStream = open(DEFAULT_TOUCH_DEV, O_RDONLY|O_NONBLOCK)) < 0)
|
|
|
+ /////////////////////////////////// Decide what to do with the device /////////////////////////////////////////////
|
|
|
+ if(Worker->isTouch || Worker->isMouse)
|
|
|
{
|
|
|
- TraceLog(LOG_WARNING, "Touch device could not be opened, no touchscreen available");
|
|
|
+ // Looks like a interesting device
|
|
|
+ TraceLog(LOG_INFO, "Opening input device '%s' (%s%s%s%s%s)", device,
|
|
|
+ Worker->isMouse ? "mouse " : "",
|
|
|
+ Worker->isMultitouch ? "multitouch " : "",
|
|
|
+ Worker->isTouch ? "touchscreen " : "",
|
|
|
+ Worker->isGamepad ? "gamepad " : "",
|
|
|
+ Worker->isKeyboard ? "keyboard " : ""
|
|
|
+ );
|
|
|
+ // Create a thread for this device
|
|
|
+ int error = pthread_create(&Worker->threadId, NULL, &EventThread, (void*)Worker);
|
|
|
+ if(error != 0)
|
|
|
+ {
|
|
|
+ TraceLog(LOG_WARNING, "Error creating input device thread for '%s': Can't create thread (Err: %d)", device, error);
|
|
|
+ Worker->threadId = 0;
|
|
|
+ close(fd);
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- touchReady = true;
|
|
|
-
|
|
|
- int error = pthread_create(&touchThreadId, NULL, &TouchThread, NULL);
|
|
|
-
|
|
|
- if (error != 0) TraceLog(LOG_WARNING, "Error creating touch input event thread");
|
|
|
- else TraceLog(LOG_INFO, "Touch device initialized successfully");
|
|
|
+ // We are not interested in this device
|
|
|
+ close(fd);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Touch reading thread.
|
|
|
-// This reads from a Virtual Input Event /dev/input/event4 which is
|
|
|
-// created by the ts_uinput daemon. This takes, filters and scales
|
|
|
-// raw input from the Touchscreen (which appears in /dev/input/event3)
|
|
|
-// based on the Calibration data referenced by tslib.
|
|
|
-static void *TouchThread(void *arg)
|
|
|
+static void *EventThread(void *arg)
|
|
|
{
|
|
|
struct input_event ev;
|
|
|
GestureEvent gestureEvent;
|
|
|
+ InputEventWorker* Worker = (InputEventWorker*)arg;
|
|
|
+ bool GestureNeedsUpdate = false;
|
|
|
|
|
|
while (!windowShouldClose)
|
|
|
{
|
|
|
- if (read(touchStream, &ev, sizeof(ev)) == (int)sizeof(ev))
|
|
|
+ if (read(Worker->fd, &ev, sizeof(ev)) == (int)sizeof(ev))
|
|
|
{
|
|
|
- // if pressure > 0 then simulate left mouse button click
|
|
|
- if (ev.type == EV_ABS && ev.code == 24 && ev.value == 0 && currentMouseState[0] == 1)
|
|
|
+ /////////////////////////////// Relative movement parsing ////////////////////////////////////
|
|
|
+ if(ev.type == EV_REL)
|
|
|
{
|
|
|
- currentMouseState[0] = 0;
|
|
|
- gestureEvent.touchAction = TOUCH_UP;
|
|
|
- gestureEvent.pointCount = 1;
|
|
|
- gestureEvent.pointerId[0] = 0;
|
|
|
- gestureEvent.pointerId[1] = 1;
|
|
|
- gestureEvent.position[0] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[1] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[0].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[0].y /= (float)GetScreenHeight();
|
|
|
- gestureEvent.position[1].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[1].y /= (float)GetScreenHeight();
|
|
|
- ProcessGestureEvent(gestureEvent);
|
|
|
+ if(ev.code == REL_X)
|
|
|
+ {
|
|
|
+ mousePosition.x += ev.value;
|
|
|
+ touchPosition[0].x = mousePosition.x;
|
|
|
+ gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
+ GestureNeedsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == REL_Y)
|
|
|
+ {
|
|
|
+ mousePosition.y += ev.value;
|
|
|
+ touchPosition[0].y = mousePosition.y;
|
|
|
+ gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
+ GestureNeedsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == REL_WHEEL)
|
|
|
+ {
|
|
|
+ currentMouseWheelY += ev.value;
|
|
|
+ }
|
|
|
}
|
|
|
- if (ev.type == EV_ABS && ev.code == 24 && ev.value > 0 && currentMouseState[0] == 0)
|
|
|
+
|
|
|
+ /////////////////////////////// Absolute movement parsing ////////////////////////////////////
|
|
|
+ if(ev.type == EV_ABS)
|
|
|
{
|
|
|
- currentMouseState[0] = 1;
|
|
|
- gestureEvent.touchAction = TOUCH_DOWN;
|
|
|
- gestureEvent.pointCount = 1;
|
|
|
- gestureEvent.pointerId[0] = 0;
|
|
|
- gestureEvent.pointerId[1] = 1;
|
|
|
- gestureEvent.position[0] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[1] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[0].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[0].y /= (float)GetScreenHeight();
|
|
|
- gestureEvent.position[1].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[1].y /= (float)GetScreenHeight();
|
|
|
- ProcessGestureEvent(gestureEvent);
|
|
|
+ // Basic movement
|
|
|
+ if(ev.code == ABS_X)
|
|
|
+ {
|
|
|
+ mousePosition.x = (ev.value - Worker->absRange.x) * screenWidth / Worker->absRange.width; //Scale acording to absRange
|
|
|
+ gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
+ GestureNeedsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == ABS_Y)
|
|
|
+ {
|
|
|
+ mousePosition.y = (ev.value - Worker->absRange.y) * screenHeight / Worker->absRange.height; //Scale acording to absRange
|
|
|
+ gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
+ GestureNeedsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ //Multitouch movement
|
|
|
+ if(ev.code == ABS_MT_SLOT)
|
|
|
+ {
|
|
|
+ Worker->touchSlot = ev.value; //Remeber the slot number for the folowing events
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == ABS_MT_POSITION_X)
|
|
|
+ {
|
|
|
+ if(Worker->touchSlot < MAX_TOUCH_POINTS)
|
|
|
+ touchPosition[Worker->touchSlot].x = (ev.value - Worker->absRange.x) * screenWidth / Worker->absRange.width; //Scale acording to absRange
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == ABS_MT_POSITION_Y)
|
|
|
+ {
|
|
|
+ if(Worker->touchSlot < MAX_TOUCH_POINTS)
|
|
|
+ touchPosition[Worker->touchSlot].y = (ev.value - Worker->absRange.y) * screenHeight / Worker->absRange.height; //Scale acording to absRange
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == ABS_MT_TRACKING_ID)
|
|
|
+ {
|
|
|
+ if( (ev.value < 0) && (Worker->touchSlot < MAX_TOUCH_POINTS) )
|
|
|
+ {
|
|
|
+ //Touch has ended for this point
|
|
|
+ touchPosition[Worker->touchSlot].x = -1;
|
|
|
+ touchPosition[Worker->touchSlot].y = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- // x & y values supplied by event4 have been scaled & de-jittered using tslib calibration data
|
|
|
- if (ev.type == EV_ABS && ev.code == 0)
|
|
|
+
|
|
|
+ /////////////////////////////// Button parsing ////////////////////////////////////
|
|
|
+ if(ev.type == EV_KEY)
|
|
|
{
|
|
|
- mousePosition.x = ev.value;
|
|
|
- if (mousePosition.x < 0) mousePosition.x = 0;
|
|
|
- if (mousePosition.x > screenWidth) mousePosition.x = screenWidth;
|
|
|
- gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
- gestureEvent.pointCount = 1;
|
|
|
- gestureEvent.pointerId[0] = 0;
|
|
|
- gestureEvent.pointerId[1] = 1;
|
|
|
- gestureEvent.position[0] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[1] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[0].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[0].y /= (float)GetScreenHeight();
|
|
|
- gestureEvent.position[1].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[1].y /= (float)GetScreenHeight();
|
|
|
- ProcessGestureEvent(gestureEvent);
|
|
|
+ if((ev.code == BTN_TOUCH) || (ev.code == BTN_LEFT))
|
|
|
+ {
|
|
|
+ currentMouseStateEvdev[MOUSE_LEFT_BUTTON] = ev.value;
|
|
|
+ if(ev.value > 0)
|
|
|
+ gestureEvent.touchAction = TOUCH_DOWN;
|
|
|
+ else
|
|
|
+ gestureEvent.touchAction = TOUCH_UP;
|
|
|
+ GestureNeedsUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == BTN_RIGHT)
|
|
|
+ {
|
|
|
+ currentMouseStateEvdev[MOUSE_RIGHT_BUTTON] = ev.value;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ev.code == BTN_MIDDLE)
|
|
|
+ {
|
|
|
+ currentMouseStateEvdev[MOUSE_MIDDLE_BUTTON] = ev.value;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
- if (ev.type == EV_ABS && ev.code == 1)
|
|
|
+
|
|
|
+ /////////////////////////////// Screen confinement ////////////////////////////////////
|
|
|
+ if(mousePosition.x < 0)
|
|
|
+ mousePosition.x = 0;
|
|
|
+ if(mousePosition.x > screenWidth / mouseScale)
|
|
|
+ mousePosition.x = screenWidth / mouseScale;
|
|
|
+
|
|
|
+ if(mousePosition.y < 0)
|
|
|
+ mousePosition.y = 0;
|
|
|
+ if(mousePosition.y > screenHeight / mouseScale)
|
|
|
+ mousePosition.y = screenHeight / mouseScale;
|
|
|
+
|
|
|
+ /////////////////////////////// Gesture update ////////////////////////////////////
|
|
|
+ if(GestureNeedsUpdate)
|
|
|
{
|
|
|
- mousePosition.y = ev.value;
|
|
|
- if (mousePosition.y < 0) mousePosition.y = 0;
|
|
|
- if (mousePosition.y > screenHeight) mousePosition.y = screenHeight;
|
|
|
- gestureEvent.touchAction = TOUCH_MOVE;
|
|
|
- gestureEvent.pointCount = 1;
|
|
|
+ gestureEvent.pointCount = 0;
|
|
|
+ if(touchPosition[0].x >= 0) gestureEvent.pointCount++;
|
|
|
+ if(touchPosition[1].x >= 0) gestureEvent.pointCount++;
|
|
|
+ if(touchPosition[2].x >= 0) gestureEvent.pointCount++;
|
|
|
+ if(touchPosition[3].x >= 0) gestureEvent.pointCount++;
|
|
|
gestureEvent.pointerId[0] = 0;
|
|
|
gestureEvent.pointerId[1] = 1;
|
|
|
- gestureEvent.position[0] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[1] = (Vector2){ mousePosition.x, mousePosition.y };
|
|
|
- gestureEvent.position[0].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[0].y /= (float)GetScreenHeight();
|
|
|
- gestureEvent.position[1].x /= (float)GetScreenWidth();
|
|
|
- gestureEvent.position[1].y /= (float)GetScreenHeight();
|
|
|
+ gestureEvent.pointerId[2] = 2;
|
|
|
+ gestureEvent.pointerId[3] = 3;
|
|
|
+ gestureEvent.position[0] = touchPosition[0];
|
|
|
+ gestureEvent.position[1] = touchPosition[1];
|
|
|
+ gestureEvent.position[2] = touchPosition[2];
|
|
|
+ gestureEvent.position[3] = touchPosition[3];
|
|
|
ProcessGestureEvent(gestureEvent);
|
|
|
}
|
|
|
-
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ usleep(5000); //Sleep for 5ms to avoid hogging CPU time
|
|
|
}
|
|
|
}
|
|
|
return NULL;
|
|
@@ -4090,6 +4290,10 @@ static void *GamepadThread(void *arg)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ usleep(1000); //Sleep for 1ms to avoid hogging CPU time
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|