mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
Wii U get_arguments() prints through the argc/argv pointers it was handed, and argv[1] only when there is one. The in-place URL decode passes the string's real size to string_percent_decode(), and Basic auth decodes its own buffer with the length it already has, so LTO no longer sees a SIZE_MAX bound wrapping around. Helpers only some configurations call are compiled for those only: the overlay-only input and menu helpers under HAVE_OVERLAY, the container-only audio_transfer time and movie-header helpers under their container, and the scalar xxh3 long path off NEON. hidraw hands autoconfig the stored vid/pid, rcheevos copies its operand by assignment, and the Qt companion asks QScreen from Qt 5.10 on.
570 lines
20 KiB
C
570 lines
20 KiB
C
/* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __INPUT_POINTER_FRAME_H
|
|
#define __INPUT_POINTER_FRAME_H
|
|
|
|
/* What the frontend keeps of the mice and touches an input driver
|
|
* publishes at its poll, and how it answers for the mouse, the pointer
|
|
* and the lightgun's aim from them. input_driver.c is its one user; it
|
|
* is a header so that a test can drive the same code
|
|
* (samples/input/pointer_frame). It needs input_driver.h,
|
|
* gfx/video_driver.h's viewport calls and <string.h> before it. */
|
|
|
|
#define INPUT_TOUCHES_MAX 16
|
|
|
|
/* The pointing devices an input driver published at this poll, and
|
|
* their places in the viewport, worked out the first time one is asked
|
|
* for after the poll and kept until the next. */
|
|
static struct
|
|
{
|
|
input_pointer_frame_t frame[MAX_USERS];
|
|
uint32_t confined_pos[MAX_USERS]; /* in the viewport, held to its edges */
|
|
uint32_t viewport_pos[MAX_USERS]; /* in the viewport, -0x8000 outside it */
|
|
uint32_t screen_pos[MAX_USERS];
|
|
uint32_t read_as[MAX_USERS]; /* the device kind last read as */
|
|
uint32_t touch_pos[INPUT_TOUCHES_MAX]; /* in the window; 0: none */
|
|
uint32_t touch_confined_pos[INPUT_TOUCHES_MAX];
|
|
uint32_t touch_screen_pos[INPUT_TOUCHES_MAX];
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
input_video_window_t window[MAX_USERS]; /* where in_window says */
|
|
input_video_window_t touch_window[INPUT_TOUCHES_MAX];
|
|
#endif
|
|
struct video_viewport vp;
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
uint16_t in_window; /* a bit a device: in a screen's own */
|
|
uint16_t touch_in_window;
|
|
#endif
|
|
uint16_t have_confined; /* a bit a device: done this poll */
|
|
uint16_t have_viewport;
|
|
uint32_t touch_viewport_pos[INPUT_TOUCHES_MAX]; /* -0x8000 outside */
|
|
uint16_t have_touch; /* a bit a touch: done this poll */
|
|
uint16_t have_touch_viewport;
|
|
uint16_t touch_present; /* a bit a touch: a contact is there */
|
|
uint16_t touch_down; /* ... and is pressed */
|
|
uint8_t count;
|
|
uint8_t touch_count;
|
|
uint8_t flags; /* enum input_pointers_flags */
|
|
bool vp_asked;
|
|
bool vp_ok;
|
|
} input_pointers;
|
|
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
/* @count windows kept, and a bit for each in a screen's own; NULL is
|
|
* the main window's. */
|
|
static uint16_t input_pointer_windows_set(input_video_window_t *kept,
|
|
const input_video_window_t *windows, unsigned count)
|
|
{
|
|
unsigned i;
|
|
uint16_t in_window = 0;
|
|
if (!windows)
|
|
return 0;
|
|
memcpy(kept, windows, count * sizeof(*windows));
|
|
for (i = 0; i < count; i++)
|
|
if (windows[i].window)
|
|
in_window |= (uint16_t)(1 << i);
|
|
return in_window;
|
|
}
|
|
#endif
|
|
|
|
static void input_pointer_frames_set(const input_pointer_frame_t *frames,
|
|
const input_video_window_t *windows, unsigned count, unsigned flags)
|
|
{
|
|
if (count > MAX_USERS)
|
|
count = MAX_USERS;
|
|
memcpy(input_pointers.frame, frames, count * sizeof(*frames));
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
input_pointers.in_window = input_pointer_windows_set(
|
|
input_pointers.window, windows, count);
|
|
#else
|
|
(void)windows;
|
|
#endif
|
|
input_pointers.count = (uint8_t)count;
|
|
input_pointers.flags = (uint8_t)flags;
|
|
input_pointers.have_confined = 0;
|
|
input_pointers.have_viewport = 0;
|
|
input_pointers.vp_asked = false;
|
|
}
|
|
|
|
/* Where a touch is, whether there is one, and whether it is down are
|
|
* three things. A place can hold a contact that has lifted - the last
|
|
* place of a finger, a pen in the air - and a contact can be at 0,0,
|
|
* the window's corner: neither is told by the position. */
|
|
static void input_pointer_touches_set(const uint32_t *pos,
|
|
const input_video_window_t *windows, unsigned count,
|
|
unsigned present, unsigned down)
|
|
{
|
|
unsigned all;
|
|
if (count > INPUT_TOUCHES_MAX)
|
|
count = INPUT_TOUCHES_MAX;
|
|
all = (1u << count) - 1;
|
|
memcpy(input_pointers.touch_pos, pos, count * sizeof(*pos));
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
input_pointers.touch_in_window = input_pointer_windows_set(
|
|
input_pointers.touch_window, windows, count);
|
|
#else
|
|
(void)windows;
|
|
#endif
|
|
input_pointers.touch_count = (uint8_t)count;
|
|
input_pointers.touch_present = (uint16_t)(present & all);
|
|
input_pointers.touch_down = (uint16_t)(down & present & all);
|
|
input_pointers.have_touch = 0;
|
|
input_pointers.have_touch_viewport = 0;
|
|
}
|
|
|
|
static bool input_pointer_viewport(void)
|
|
{
|
|
if (!input_pointers.vp_asked)
|
|
{
|
|
memset(&input_pointers.vp, 0, sizeof(input_pointers.vp));
|
|
input_pointers.vp_ok = video_driver_get_viewport_info(&input_pointers.vp);
|
|
input_pointers.vp_asked = true;
|
|
}
|
|
return input_pointers.vp_ok;
|
|
}
|
|
|
|
/* The published device a port reads as @device. */
|
|
static unsigned input_pointer_of_port(unsigned port, unsigned device)
|
|
{
|
|
if (input_pointers.flags & INPUT_POINTERS_BY_MOUSE_INDEX)
|
|
{
|
|
if ( (input_pointers.flags & INPUT_POINTERS_AIM_EVERY_PORT)
|
|
&& device != RETRO_DEVICE_MOUSE
|
|
&& device != RARCH_DEVICE_MOUSE_SCREEN)
|
|
return 0;
|
|
return input_mouse_port_index(port);
|
|
}
|
|
return (input_pointers.count == 1) ? 0 : port;
|
|
}
|
|
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
/* @pos in a screen's own window, through the layout it last published:
|
|
* off-screen once the window is gone, and nowhere on the main window's
|
|
* screen. */
|
|
static void input_pointer_window_place(const input_video_window_t *w,
|
|
uint32_t pos, bool confined, uint32_t *place, uint32_t *screen_pos)
|
|
{
|
|
*screen_pos = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
if (!video_driver_translate_window_point(w->window, w->generation,
|
|
VIDEO_POS_X(pos), VIDEO_POS_Y(pos), !confined, place))
|
|
*place = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
}
|
|
#endif
|
|
|
|
/* Device @i's place in the viewport, or its own window's, and on the
|
|
* screen; false when there is no viewport to place it in. */
|
|
static bool input_pointer_place(unsigned i, bool confined,
|
|
uint32_t *pos, uint32_t *screen_pos)
|
|
{
|
|
uint16_t bit = (uint16_t)(1 << i);
|
|
uint16_t *have = confined
|
|
? &input_pointers.have_confined : &input_pointers.have_viewport;
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
bool in_window = (input_pointers.in_window & bit) != 0;
|
|
#else
|
|
bool in_window = false;
|
|
#endif
|
|
|
|
if (!in_window && !input_pointer_viewport())
|
|
return false;
|
|
if (!(*have & bit))
|
|
{
|
|
uint32_t place = 0;
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
if (in_window)
|
|
input_pointer_window_place(&input_pointers.window[i],
|
|
input_pointers.frame[i].pos, confined,
|
|
&place, &input_pointers.screen_pos[i]);
|
|
else
|
|
#endif
|
|
if (!video_driver_translate_coord_viewport(&input_pointers.vp,
|
|
VIDEO_POS_X(input_pointers.frame[i].pos),
|
|
VIDEO_POS_Y(input_pointers.frame[i].pos),
|
|
&place, &input_pointers.screen_pos[i], !confined))
|
|
{
|
|
input_pointers.vp_ok = false;
|
|
return false;
|
|
}
|
|
if (confined)
|
|
input_pointers.confined_pos[i] = place;
|
|
else
|
|
input_pointers.viewport_pos[i] = place;
|
|
*have |= bit;
|
|
}
|
|
*pos = confined
|
|
? input_pointers.confined_pos[i] : input_pointers.viewport_pos[i];
|
|
*screen_pos = input_pointers.screen_pos[i];
|
|
return true;
|
|
}
|
|
|
|
/* Touch @t's place in the viewport, or its own window's - held to its
|
|
* edges, or -0x8000 outside it - and on the screen; false when there is
|
|
* no viewport. */
|
|
static bool input_touch_place(unsigned t, bool confined,
|
|
uint32_t *pos, uint32_t *screen_pos)
|
|
{
|
|
uint16_t bit = (uint16_t)(1 << t);
|
|
uint16_t *have = confined
|
|
? &input_pointers.have_touch : &input_pointers.have_touch_viewport;
|
|
uint32_t *kept = confined
|
|
? &input_pointers.touch_confined_pos[t]
|
|
: &input_pointers.touch_viewport_pos[t];
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
bool in_window = (input_pointers.touch_in_window & bit) != 0;
|
|
#else
|
|
bool in_window = false;
|
|
#endif
|
|
|
|
if (!in_window && !input_pointer_viewport())
|
|
return false;
|
|
if (!(*have & bit))
|
|
{
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
if (in_window)
|
|
input_pointer_window_place(&input_pointers.touch_window[t],
|
|
input_pointers.touch_pos[t], confined,
|
|
kept, &input_pointers.touch_screen_pos[t]);
|
|
else
|
|
#endif
|
|
if (!video_driver_translate_coord_viewport(&input_pointers.vp,
|
|
VIDEO_POS_X(input_pointers.touch_pos[t]),
|
|
VIDEO_POS_Y(input_pointers.touch_pos[t]),
|
|
kept, &input_pointers.touch_screen_pos[t], !confined))
|
|
{
|
|
input_pointers.vp_ok = false;
|
|
return false;
|
|
}
|
|
*have |= bit;
|
|
}
|
|
*pos = *kept;
|
|
*screen_pos = input_pointers.touch_screen_pos[t];
|
|
return true;
|
|
}
|
|
|
|
/* Device @i's place in the main window, as published; none for one in
|
|
* a screen's own window. */
|
|
static uint32_t input_pointer_screen_place(unsigned i)
|
|
{
|
|
#ifdef HAVE_VIDEO_WINDOWS
|
|
if (input_pointers.in_window & (1 << i))
|
|
return VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
#endif
|
|
return input_pointers.frame[i].pos;
|
|
}
|
|
|
|
/* Whether mouse @f, standing for touch @idx, is down. */
|
|
static bool input_pointer_mouse_down(const input_pointer_frame_t *f,
|
|
unsigned idx)
|
|
{
|
|
if (!(input_pointers.flags & INPUT_POINTERS_MOUSE_3_TOUCHES))
|
|
return (f->buttons & INPUT_POINTER_LEFT) != 0;
|
|
if (idx == 0)
|
|
return (f->buttons & (INPUT_POINTER_LEFT
|
|
| INPUT_POINTER_RIGHT | INPUT_POINTER_MIDDLE)) != 0;
|
|
if (idx == 1)
|
|
return (f->buttons & (INPUT_POINTER_RIGHT
|
|
| INPUT_POINTER_MIDDLE)) != 0;
|
|
return (f->buttons & INPUT_POINTER_MIDDLE) != 0;
|
|
}
|
|
|
|
/* Pointer @idx of mouse @i: a real touch in that place if there is one,
|
|
* else the mouse standing for it - if the port has a mouse. False if
|
|
* there is neither, or no viewport to place it in. */
|
|
static bool input_pointer_touch(unsigned i, unsigned idx,
|
|
uint32_t *pos, uint32_t *screen_pos, bool *down)
|
|
{
|
|
const input_pointer_frame_t *f = &input_pointers.frame[
|
|
i < input_pointers.count ? i : 0];
|
|
bool real = idx < input_pointers.touch_count
|
|
&& (input_pointers.touch_present & (1 << idx));
|
|
bool three = (input_pointers.flags & INPUT_POINTERS_MOUSE_3_TOUCHES) != 0;
|
|
bool mouse = i < input_pointers.count && idx < (three ? 3u : 1u);
|
|
bool confined = !(input_pointers.flags & INPUT_POINTERS_POINTER_OFFSCREEN);
|
|
|
|
if (!real && !mouse)
|
|
return false;
|
|
if (real
|
|
? !input_touch_place(idx, confined, pos, screen_pos)
|
|
: !input_pointer_place(i, confined, pos, screen_pos))
|
|
return false;
|
|
*down = real && (input_pointers.touch_down & (1 << idx));
|
|
if ( !*down && mouse
|
|
&& !(real && (input_pointers.flags & INPUT_POINTERS_TOUCH_ALONE)))
|
|
*down = input_pointer_mouse_down(f, idx);
|
|
return true;
|
|
}
|
|
|
|
/* How many pointers are down: the touches that are, or the mouse
|
|
* standing for one. */
|
|
static unsigned input_pointer_count(unsigned i)
|
|
{
|
|
unsigned n = 0;
|
|
unsigned t;
|
|
for (t = 0; t < input_pointers.touch_count; t++)
|
|
if (input_pointers.touch_down & (1 << t))
|
|
n++;
|
|
if (n)
|
|
return n;
|
|
if ( (input_pointers.flags & INPUT_POINTERS_TOUCH_ALONE)
|
|
&& (input_pointers.touch_present & 1))
|
|
return 0;
|
|
if (i < input_pointers.count)
|
|
return input_pointer_mouse_down(&input_pointers.frame[i], 0) ? 1 : 0;
|
|
return 0;
|
|
}
|
|
|
|
/* Where the lightgun of device @i aims: at the first touch, for a
|
|
* driver that has it so and while there is one, else at the mouse. */
|
|
static bool input_gun_place(unsigned i, uint32_t *pos)
|
|
{
|
|
uint32_t screen_pos;
|
|
if ( (input_pointers.flags & INPUT_POINTERS_GUN_AT_TOUCH)
|
|
&& (input_pointers.touch_present & 1))
|
|
return input_touch_place(0, false, pos, &screen_pos);
|
|
if (i >= input_pointers.count)
|
|
return false;
|
|
return input_pointer_place(i, false, pos, &screen_pos);
|
|
}
|
|
|
|
/* A mouse's, a pointer's or a lightgun aim's position, packed. False if
|
|
* the frontend does not hold it and the driver is to be asked. */
|
|
static bool input_pointer_frame_pos(unsigned port, unsigned device,
|
|
unsigned idx, uint32_t *pos)
|
|
{
|
|
unsigned i;
|
|
uint32_t screen_pos;
|
|
|
|
if (!input_pointers.count)
|
|
return false;
|
|
*pos = 0;
|
|
i = input_pointer_of_port(port, device);
|
|
/* count never exceeds MAX_USERS (input_pointer_frames_set clamps
|
|
* it); the second test says so to the compiler. */
|
|
if (i < input_pointers.count && i < MAX_USERS)
|
|
input_pointers.read_as[i] = device;
|
|
else if ( device != RETRO_DEVICE_POINTER
|
|
&& device != RARCH_DEVICE_POINTER_SCREEN)
|
|
return true; /* no mouse here; a pointer may still be a touch */
|
|
switch (device)
|
|
{
|
|
case RETRO_DEVICE_MOUSE:
|
|
*pos = input_pointers.frame[i].rel;
|
|
return true;
|
|
case RARCH_DEVICE_MOUSE_SCREEN:
|
|
*pos = input_pointer_screen_place(i);
|
|
return true;
|
|
case RETRO_DEVICE_POINTER:
|
|
case RARCH_DEVICE_POINTER_SCREEN:
|
|
{
|
|
uint32_t vp_pos = 0;
|
|
bool down;
|
|
screen_pos = 0;
|
|
input_pointer_touch(i, idx, &vp_pos, &screen_pos, &down);
|
|
*pos = (device == RETRO_DEVICE_POINTER) ? vp_pos : screen_pos;
|
|
}
|
|
return true;
|
|
case RETRO_DEVICE_LIGHTGUN:
|
|
input_gun_place(i, pos);
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#ifdef HAVE_OVERLAY
|
|
/* Finger @idx of the pointer @port reads as @device (RETRO_DEVICE_POINTER
|
|
* or RARCH_DEVICE_POINTER_SCREEN), down or not and where, packed, at one
|
|
* look: what reading PRESSED, X and Y in turn gives. 1 down, 0 not; -1
|
|
* if the frontend does not hold it and the driver is to be asked. */
|
|
static int input_pointer_frame_finger(unsigned port, unsigned device,
|
|
unsigned idx, uint32_t *pos)
|
|
{
|
|
unsigned i;
|
|
uint32_t vp_pos = 0;
|
|
uint32_t screen_pos = 0;
|
|
bool down;
|
|
|
|
if (!input_pointers.count)
|
|
return -1;
|
|
*pos = 0;
|
|
i = input_pointer_of_port(port, device);
|
|
if (i < input_pointers.count && i < MAX_USERS)
|
|
input_pointers.read_as[i] = device;
|
|
if (!input_pointer_touch(i, idx, &vp_pos, &screen_pos, &down))
|
|
return 0;
|
|
*pos = (device == RARCH_DEVICE_POINTER_SCREEN) ? screen_pos : vp_pos;
|
|
return down ? 1 : 0;
|
|
}
|
|
#endif
|
|
|
|
/* One value of a mouse, a pointer or a lightgun's aim. False if the
|
|
* frontend does not hold it and the driver is to be asked. */
|
|
static bool input_pointer_frame_read(unsigned port, unsigned device,
|
|
unsigned idx, unsigned id, int16_t *out)
|
|
{
|
|
const input_pointer_frame_t *f;
|
|
unsigned i;
|
|
uint32_t pos;
|
|
|
|
if (!input_pointers.count)
|
|
return false;
|
|
switch (device)
|
|
{
|
|
case RETRO_DEVICE_MOUSE:
|
|
case RARCH_DEVICE_MOUSE_SCREEN:
|
|
case RETRO_DEVICE_POINTER:
|
|
case RARCH_DEVICE_POINTER_SCREEN:
|
|
break;
|
|
case RETRO_DEVICE_LIGHTGUN:
|
|
/* its aim; its buttons are binds, and the driver's */
|
|
if ( id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X
|
|
|| id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y
|
|
|| id == RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN
|
|
|| id == RETRO_DEVICE_ID_LIGHTGUN_X
|
|
|| id == RETRO_DEVICE_ID_LIGHTGUN_Y)
|
|
break;
|
|
return false;
|
|
default:
|
|
return false;
|
|
}
|
|
*out = 0;
|
|
i = input_pointer_of_port(port, device);
|
|
/* count never exceeds MAX_USERS (input_pointer_frames_set clamps
|
|
* it); the second test says so to the compiler. */
|
|
if (i < input_pointers.count && i < MAX_USERS)
|
|
input_pointers.read_as[i] = device;
|
|
else if ( device != RETRO_DEVICE_POINTER
|
|
&& device != RARCH_DEVICE_POINTER_SCREEN)
|
|
return true; /* no mouse here; a pointer may still be a touch */
|
|
f = &input_pointers.frame[i < input_pointers.count ? i : 0];
|
|
|
|
switch (device)
|
|
{
|
|
case RETRO_DEVICE_MOUSE:
|
|
case RARCH_DEVICE_MOUSE_SCREEN:
|
|
pos = (device == RETRO_DEVICE_MOUSE)
|
|
? f->rel : input_pointer_screen_place(i);
|
|
switch (id)
|
|
{
|
|
case RETRO_DEVICE_ID_MOUSE_X:
|
|
*out = VIDEO_POS_X(pos);
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_Y:
|
|
*out = VIDEO_POS_Y(pos);
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_LEFT:
|
|
*out = (f->buttons & INPUT_POINTER_LEFT) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_RIGHT:
|
|
*out = (f->buttons & INPUT_POINTER_RIGHT) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
|
|
*out = (f->buttons & INPUT_POINTER_MIDDLE) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
|
|
*out = (f->buttons & INPUT_POINTER_BUTTON_4) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
|
|
*out = (f->buttons & INPUT_POINTER_BUTTON_5) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
|
|
*out = (f->buttons & INPUT_POINTER_WHEEL_UP) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
|
|
*out = (f->buttons & INPUT_POINTER_WHEEL_DOWN) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
|
|
*out = (f->buttons & INPUT_POINTER_HWHEEL_UP) != 0;
|
|
break;
|
|
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
|
|
*out = (f->buttons & INPUT_POINTER_HWHEEL_DOWN) != 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case RETRO_DEVICE_POINTER:
|
|
case RARCH_DEVICE_POINTER_SCREEN:
|
|
{
|
|
uint32_t screen_pos;
|
|
bool down;
|
|
/* how many are down needs no place for them */
|
|
if (id == RETRO_DEVICE_ID_POINTER_COUNT)
|
|
{
|
|
*out = (int16_t)input_pointer_count(i);
|
|
break;
|
|
}
|
|
if (!input_pointer_touch(i, idx, &pos, &screen_pos, &down))
|
|
break;
|
|
if (device == RARCH_DEVICE_POINTER_SCREEN)
|
|
pos = screen_pos;
|
|
switch (id)
|
|
{
|
|
case RETRO_DEVICE_ID_POINTER_X:
|
|
*out = VIDEO_POS_X(pos);
|
|
break;
|
|
case RETRO_DEVICE_ID_POINTER_Y:
|
|
*out = VIDEO_POS_Y(pos);
|
|
break;
|
|
case RETRO_DEVICE_ID_POINTER_PRESSED:
|
|
*out = down;
|
|
break;
|
|
case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN:
|
|
*out = input_driver_pointer_is_offscreen(
|
|
VIDEO_POS_X(pos), VIDEO_POS_Y(pos));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case RETRO_DEVICE_LIGHTGUN:
|
|
if ( id == RETRO_DEVICE_ID_LIGHTGUN_X
|
|
|| id == RETRO_DEVICE_ID_LIGHTGUN_Y)
|
|
{
|
|
/* deprecated: the mouse's motion */
|
|
*out = (id == RETRO_DEVICE_ID_LIGHTGUN_X)
|
|
? VIDEO_POS_X(f->rel) : VIDEO_POS_Y(f->rel);
|
|
}
|
|
else
|
|
{
|
|
if (!input_gun_place(i, &pos))
|
|
break;
|
|
if (id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X)
|
|
*out = VIDEO_POS_X(pos);
|
|
else if (id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y)
|
|
*out = VIDEO_POS_Y(pos);
|
|
else
|
|
*out = input_driver_pointer_is_offscreen(
|
|
VIDEO_POS_X(pos), VIDEO_POS_Y(pos));
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* Before a driver's poll: one that publishes nothing is asked itself. */
|
|
static void input_pointer_frames_clear(void)
|
|
{
|
|
input_pointers.count = 0;
|
|
input_pointers.touch_count = 0;
|
|
/* and the viewport is asked for afresh, by whoever wants it first */
|
|
input_pointers.vp_asked = false;
|
|
}
|
|
|
|
#endif
|