/* RetroArch - A frontend for libretro.
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see .
*/
#ifndef _ANDROID_POINTERS_H
#define _ANDROID_POINTERS_H
#include
#include
#include
/* Android's touches and mouse as the input driver keeps them
* (input/drivers/android_input.c), and what it publishes of them to the
* frontend each poll. No NDK types, so that
* samples/input/pointer_frame can drive it; it needs
* input/input_driver.h, with HAVE_VIDEO_WINDOWS, and
* gfx/video_driver.h before it. */
/* The main window's 16 slots and the second display's 16 fingers */
#define ANDROID_POINTERS_MAX 32
/* A touch slot: index n is the n-th finger down. The slots above a
* lifted finger's shift down onto it and the top one keeps its place,
* so an index that is not down still reads a place. */
struct input_pointer
{
uint32_t pos; /* in its window, VIDEO_POS_PACK */
bool placed; /* a place was ever written here */
};
typedef struct android_pointers
{
const struct input_pointer *main_slots;
const struct input_pointer *second;
unsigned slots; /* main_slots */
unsigned main_count; /* fingers down on the main window */
unsigned second_count; /* on the second display, all down */
input_video_window_t second_window;
uint32_t mouse_pos; /* in the window, VIDEO_POS_PACK */
uint16_t mouse_buttons; /* enum input_pointer_buttons */
bool mouse_used; /* a mouse has moved: it aims the lightgun */
} android_pointers_t;
/* The publication's flags that keep Android's answers */
static INLINE unsigned android_pointers_flags(bool mouse_used)
{
unsigned flags = INPUT_POINTERS_PRESSED_INSIDE
| INPUT_POINTERS_WINDOWS_SECOND
| INPUT_POINTERS_MOUSE_BY_DRIVER
| INPUT_POINTERS_TOUCH_SLOTS
| INPUT_POINTERS_POINTER_IDS_BY_DRIVER;
if (!mouse_used)
flags |= INPUT_POINTERS_GUN_AT_TOUCH;
return flags;
}
/* The fingers the driver's own lightgun buttons count (TRIGGER one,
* START two, RELOAD three): none on a main window whose views layout
* @layout shows no screen, where a tap is on nothing. A tap in the
* letterbox still counts. */
static INLINE unsigned android_pointers_gun_fingers(unsigned main_count,
const video_views_layout_t *layout)
{
if (layout && !layout->num_placements)
return 0;
return main_count;
}
/* One poll's mouse and touches to the frontend; app thread */
static INLINE void android_pointers_publish(const android_pointers_t *p)
{
input_pointer_frame_t *frame = input_driver_pointers_lend();
input_video_window_t windows[ANDROID_POINTERS_MAX];
uint32_t *pos = input_driver_touches_lend();
unsigned present = 0;
unsigned down = 0;
unsigned count = 0;
unsigned i;
frame->pos = p->mouse_pos;
frame->rel = 0; /* the driver's own (MOUSE_BY_DRIVER) */
frame->buttons = p->mouse_buttons;
input_driver_publish_window_pointers(frame, NULL, 1,
android_pointers_flags(p->mouse_used));
for (i = 0; i < p->slots && count < ANDROID_POINTERS_MAX; i++, count++)
{
pos[count] = p->main_slots[i].pos;
windows[count].window = 0;
windows[count].generation = 0;
if (p->main_slots[i].placed)
present |= 1u << count;
if (i < p->main_count)
down |= 1u << count;
}
for (i = 0; i < p->second_count && count < ANDROID_POINTERS_MAX;
i++, count++)
{
pos[count] = p->second[i].pos;
windows[count] = p->second_window;
present |= 1u << count;
down |= 1u << count;
}
input_driver_publish_window_touches(pos, windows, count, present, down);
}
#endif