mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-13 04:51:38 -10:00
* rgui: upload the menu again to the video driver a reinit makes Closing content with RGUI up left the screen black until a key press. The staged content load presents frames between its stages, so RGUI can upload its framebuffer to the old video driver and clear FB_DIRTY just before the driver stage replaces that driver. The new one has no menu texture, nothing in the menu changes, and RGUI never uploads again. command_event_reinit sets FB_DIRTY after its reinit, but the staged load and video-only resets reach the menu only through context_reset, so RGUI marks its framebuffer dirty there. The menu_icon_ownership harness gets an rgui lane that reinits the video driver and checks the next upload reaches the new one. * video: draw a frame queued before a view count shrink with its views Under threaded video the wrapper ran SET_VIEW_COUNT ahead of the frame it had already claimed, so a closing core's last queued frame drew after its view chains were gone: whole, both screens stacked, until the menu's first frame replaced it. The wrapper still answers at once, but a smaller count reaches the driver only once the frames queued before it have drawn. A grow applies at once as before, with the main thread waiting for the preset parse. Vulkan and glcore therefore build view chains only when the count grows, so a deferred shrink never parses a preset. They also keep the headset's whole-frame chain across a count change: it does not depend on the count, and with chains built only on a grow nothing would rebuild it after a shrink to 0. * android: don't make a second screen's EGL surface once Java took it back Java can take the second screen's surface back between the poll that hands it over and the frame that makes its EGL surface. Skip making one then; the screens go back to the main window as they do when a make fails. Java can still take the surface back during the make itself; the node's own ANativeWindow reference keeps the window alive through that. * android: ask a display move by display id and number it A move named its display by its place in the list, and Java looked that up later on the UI thread against whatever list was newest, so a display coming or going in between could send RetroArch elsewhere. Java now gets the display id and fails the move when that display is gone. Native code now counts the ids when it compares display lists, so a display unplugged and plugged back is a new list and its failures clear. A failure was a bare flag, so one move's failure could end the next move and mark its display unable. Each move now carries a number and a failure counts only for the move it names. The move code also loses two stores that were always overwritten. * android: end the refocus hold after a move only when it is done A move onto a display that is no longer valid now fails at once instead of waiting out its timeout. The hold that keeps RetroArch's window unfocusable after a move ends only on the focus loss Android answers it with, not on a gain that was already queued; an earlier hold ends only once the new move has started; and onStop() ends a running hold rather than leaving it to its timer. * video_windows: tell an external monitor by its display type Android lists the AYN Thor's two panels and a DP monitor with the same unknown connection type, so Auto took the monitor for a second panel: on a one-screen phone Game Screen 2 went to it. Java now reads the hidden Display.getType() by reflection where it can and passes internal or external with each display. A display typed internal is never a monitor; where the type is unknown, a non-default display with an unknown connection and a product name now counts as one. * video: give a Presentation on another display its own UI wait The menu waits up to a second for the Presentation it is laid out for to show, but the wait was only counted from the first one. Once a Presentation had shown, one made on another display had no wait left and the menu fell back to the main window at once. * input: keep the menu's mouse where it was while the menu is in a window With Mouse Support on, the menu moving into the Presentation read as a mouse move to (0,0) for a frame, which marks the pointer active there. The view keeps the main window's last mouse position instead. * input: match a window's touches only from a windowed publication A publication without windows after one with them left the old window ids in place, so a window's touch lookup could still match them. Only touches published in a window match now. No Android path publishes that way today. * vulkan: copy a waiting window's views on a new frame A screen window that was up but had no free image on a new frame did not get its views copied, so a later repeat that drew it, as a pause with the menu there does, left black areas where those views go. They are copied on every new frame now. * video: load the idle logo from the assets directory without widgets The idle logo's path came from the widgets, which only start with On-Screen Notifications on, so with them off the idle window stayed black. Without the widgets' path it is built from the assets directory the way the widgets build it. * android: hold the focus when Android moves RetroArch between displays When the display RetroArch is on, or moving to, goes away, Android moves the Activity to the default display and can send that display's focus gain before the removed display's loss. A task moved to another display and straight back gets no configuration change, and can read the old display's loss last too. With the loss last, RetroArch pauses while Android keeps it focused, and no later focus event wakes it. Count these as moves, as RetroArch's own moves are: a removal, and any change of RetroArch's display it did not ask for. From Android 10, with more than one display, so is losing and regaining the top-resumed place while focused, or regaining it unfocused within a second of losing it after a loss no hold asked for. The refocus hold that covers a move's late loss then covers these too: the window is made unfocusable until Android has taken the focus, then gets the gain again. A gain already on its way skips the hold, and a move marked while RetroArch is focused ends after a second with no focus event. * samples: close test gaps in video_windows and android_focus The is_default check set the flag and read it back, so it could not fail; Auto's fallback to the default display now shows the flag at work. Cover a display listed without an ordinal, and display keys at sizes 0 to 3, two unnamed displays and a 63-character name. Drop a stale note from android_focus_test's header. * video: fix wording left over from the display rows The Screen Display sublabel still named the Separate mode, a setting the display rows removed; it now says "when it has a window of its own". The warnings for a screen window that can't be drawn, or whose surface is gone, said its screens go back to the main window, but a window that shows only the menu reaches them too. They now read like the one for a window that can't be made: what it shows stays in the main window. Comments that no longer matched the code are reworded. pointer_frame's model of the driver before the publication is named was_* rather than today_*, and a wrong commit hash and a plan tag go from the tests. video_driver_free_internal() uses VIDEO_ANDROID_RELEASE_KEPT_WINDOWS() rather than open-coding it, with no change in behaviour.
1233 lines
60 KiB
C
1233 lines
60 KiB
C
/* Oracle for input/input_pointer_frame.h: the frontend's answers for the
|
|
* mouse, the pointer and the lightgun's aim, from what an input driver
|
|
* published at its poll.
|
|
*
|
|
* The header is included as input_driver.c includes it, with a viewport
|
|
* and a translation of this test's own that count how often they are
|
|
* asked - which is the point of the store: a device is placed in the
|
|
* viewport once a poll, however many values are read.
|
|
*
|
|
* 1. the mouse: motion, place in the window, buttons, the second port's
|
|
* device, a port with none;
|
|
* 2. a wheel notch reads the same every time in its frame;
|
|
* 3. the pointer from a mouse standing for three touches, and for one;
|
|
* 4. real touches: a place with a touch reads the touch, one that is
|
|
* down is pressed, a lifted one keeps its place and is pressed only
|
|
* as the mouse says; a place with none reads the mouse;
|
|
* 5. the lightgun's aim reports off-screen where the pointer holds to
|
|
* the edge;
|
|
* 6. one viewport fetch a poll, one translation a device and kind;
|
|
* 7. a poll in which nothing is published: the driver is to be asked;
|
|
* 8. ports reading by Mouse Index, a port with no mouse still reading a
|
|
* real touch, and the kind of device each mouse was last read as;
|
|
* 9. only the mouse by index with the pointer and the lightgun every
|
|
* port's, and the lightgun aiming at the first touch;
|
|
* 10. how many pointers are down;
|
|
* 11. the pointer placed off-screen as the lightgun is;
|
|
* 12. a touch read alone: a pen in the air;
|
|
* 13. the poll's viewport, asked for once a poll;
|
|
* 14. a touch's place, its presence and whether it is down are three
|
|
* things: a touch at 0,0, one lifted there, a place with none,
|
|
* the viewport's edges, sparse places, the lightgun;
|
|
* 15. devices and touches in a screen's own window: placed through
|
|
* that window, nowhere on the main window's screen, off-screen
|
|
* once the window is gone; motion, buttons and ports as on the
|
|
* main window;
|
|
* 16. the flags that keep a driver's own answers (Android's), each off
|
|
* and on: pressed only inside, the second list, the mouse and
|
|
* the ids left to the driver, touch slots; and a touch read over
|
|
* its own window's client area;
|
|
* 17. Android's publication against the driver's own answers before
|
|
* it published, finger by finger;
|
|
* 18. the driver's own lightgun buttons: a tap on a main window that
|
|
* shows no screen counts no finger, one in the letterbox does. */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <boolean.h>
|
|
#include <libretro.h>
|
|
|
|
#include "input/input_driver.h"
|
|
#include "gfx/video_driver.h"
|
|
|
|
static unsigned failures, vp_asked, translations;
|
|
#define CHECK(cond, msg) do { if (!(cond)) { failures++; \
|
|
printf("FAIL %s\n", msg); } } while (0)
|
|
|
|
/* A 200x100 viewport at 0,0 of a 200x100 screen. In it a position is
|
|
* itself; outside, held to the edge or -0x8000 as asked. The screen
|
|
* position is the position plus 1000, to tell the two apart, and
|
|
* -0x8000 left of or above -100, off the screen. */
|
|
bool video_driver_get_viewport_info(struct video_viewport *vp)
|
|
{
|
|
vp_asked++;
|
|
vp->pos = VIDEO_POS_PACK(0, 0);
|
|
vp->dims = VIDEO_SCALE_PACK(200, 100);
|
|
vp->full_dims = VIDEO_SCALE_PACK(200, 100);
|
|
return true;
|
|
}
|
|
|
|
bool video_driver_translate_coord_viewport(struct video_viewport *vp,
|
|
int x, int y, uint32_t *res_pos, uint32_t *res_screen_pos,
|
|
bool report_oob)
|
|
{
|
|
int vx = x, vy = y;
|
|
translations++;
|
|
(void)vp;
|
|
if (x < 0 || x >= 200)
|
|
vx = report_oob ? -0x8000 : (x < 0 ? 0 : 199);
|
|
if (y < 0 || y >= 100)
|
|
vy = report_oob ? -0x8000 : (y < 0 ? 0 : 99);
|
|
*res_pos = VIDEO_POS_PACK(vx, vy);
|
|
*res_screen_pos = VIDEO_POS_PACK(x < -100 ? -0x8000 : x + 1000,
|
|
y < -100 ? -0x8000 : y + 1000);
|
|
return true;
|
|
}
|
|
|
|
/* Window 1, generation 5, has a 100x100 layout: a place in it is
|
|
* itself plus 2000, held to its edges or -0x8000 outside as asked.
|
|
* Any other window or generation has none. */
|
|
static unsigned window_translations;
|
|
bool video_driver_translate_window_point(unsigned window,
|
|
unsigned generation, int x, int y, bool report_oob,
|
|
uint32_t *result)
|
|
{
|
|
window_translations++;
|
|
if (window != 1 || generation != 5)
|
|
return false;
|
|
if (report_oob && (x < 0 || x >= 100 || y < 0 || y >= 100))
|
|
{
|
|
*result = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
return true;
|
|
}
|
|
x = x < 0 ? 0 : (x > 99 ? 99 : x);
|
|
y = y < 0 ? 0 : (y > 99 ? 99 : y);
|
|
*result = VIDEO_POS_PACK(x + 2000, y + 2000);
|
|
return true;
|
|
}
|
|
|
|
/* Window shown_window has drawn, shown_dims big, on display 4 */
|
|
static unsigned shown_window, shown_dims;
|
|
unsigned video_driver_window_shown(unsigned window, unsigned *dims)
|
|
{
|
|
if (!window || window != shown_window)
|
|
return 0;
|
|
if (dims)
|
|
*dims = shown_dims;
|
|
return 4;
|
|
}
|
|
|
|
bool input_driver_pointer_is_offscreen(int16_t x, int16_t y)
|
|
{ return x == -0x8000 || y == -0x8000; }
|
|
|
|
/* Port 0's Mouse Index is 1, port 1's is 0, port 2's is a mouse that is
|
|
* not there. */
|
|
unsigned input_mouse_port_index(unsigned port)
|
|
{ return port == 0 ? 1 : (port == 1 ? 0 : 7); }
|
|
|
|
#include "input/input_pointer_frame.h"
|
|
|
|
/* @count places, each with a contact; @down says which are pressed. */
|
|
static void touches_set(const uint32_t *pos, unsigned count, unsigned down)
|
|
{
|
|
input_pointer_touches_set(pos, NULL, count, (1u << count) - 1, down);
|
|
}
|
|
|
|
static int16_t rd(unsigned port, unsigned device, unsigned idx, unsigned id)
|
|
{
|
|
int16_t v = -1;
|
|
if (!input_pointer_frame_read(port, device, idx, id, &v))
|
|
return -2; /* the driver is to be asked */
|
|
return v;
|
|
}
|
|
|
|
/* 16 */
|
|
static void test_flags(void)
|
|
{
|
|
input_pointer_frame_t f;
|
|
input_video_window_t tw[3];
|
|
uint32_t touch[3];
|
|
uint32_t pos = 0;
|
|
bool down = false;
|
|
|
|
input_pointer_frames_clear();
|
|
memset(&f, 0, sizeof(f));
|
|
memset(tw, 0, sizeof(tw));
|
|
f.pos = VIDEO_POS_PACK(10, 10);
|
|
f.buttons = INPUT_POINTER_LEFT;
|
|
|
|
/* PRESSED_INSIDE: right of the viewport, left of the screen, in */
|
|
touch[0] = VIDEO_POS_PACK(250, 40);
|
|
touch[1] = VIDEO_POS_PACK(-150, 40);
|
|
touch[2] = VIDEO_POS_PACK(30, 20);
|
|
input_pointer_frames_set(&f, NULL, 1, 0);
|
|
touches_set(touch, 3, 7);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"without PRESSED_INSIDE a touch that is down is pressed anywhere");
|
|
input_pointer_frames_set(&f, NULL, 1, INPUT_POINTERS_PRESSED_INSIDE);
|
|
touches_set(touch, 3, 7);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 199
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 3,
|
|
"with it, pressed only inside the viewport, or the screen read as SCREEN, and still counted");
|
|
|
|
/* POINTER_IDS_BY_DRIVER */
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RARCH_DEVICE_ID_POINTER_BACK) == 0
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RARCH_DEVICE_ID_POINTER_BACK) == 0,
|
|
"without POINTER_IDS_BY_DRIVER an id the frontend does not hold reads 0");
|
|
input_pointer_frames_set(&f, NULL, 1, INPUT_POINTERS_POINTER_IDS_BY_DRIVER);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RARCH_DEVICE_ID_POINTER_BACK) == -2
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RARCH_DEVICE_ID_POINTER_BACK) == -2
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 199,
|
|
"with it the driver answers that id, and the frontend the rest");
|
|
|
|
/* WINDOWS_SECOND: touches 0 and 2 in window 1, 1 in the main one */
|
|
tw[0].window = 1;
|
|
tw[0].generation = 5;
|
|
tw[2] = tw[0];
|
|
touch[0] = VIDEO_POS_PACK(10, 20);
|
|
touch[1] = VIDEO_POS_PACK(50, 60);
|
|
touch[2] = VIDEO_POS_PACK(30, 40);
|
|
input_pointer_frames_set(&f, NULL, 1, 0);
|
|
input_pointer_touches_set(touch, tw, 3, 7, 7);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 2010
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 3
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 0, RETRO_DEVICE_ID_POINTER_X) == -2,
|
|
"without WINDOWS_SECOND every touch is the pointer's, and there is no second list");
|
|
input_pointer_frames_set(&f, NULL, 1,
|
|
INPUT_POINTERS_WINDOWS_SECOND | INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, tw, 3, 7, 7);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 50
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X) == 1050
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 50
|
|
&& input_pointer_frame_pos(0, RETRO_DEVICE_POINTER, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(50, 60),
|
|
"with it the pointer and the lightgun have the main window's touches");
|
|
CHECK( rd(0, RARCH_DEVICE_POINTER_SECOND, 0, RETRO_DEVICE_ID_POINTER_X) == 2010
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 1, RETRO_DEVICE_ID_POINTER_X) == 2030
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 1, RETRO_DEVICE_ID_POINTER_Y) == 2040
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 2
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 2, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 0,
|
|
"and the others are a second list, in the order published");
|
|
input_pointer_touches_set(touch, tw, 0, 0, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RARCH_DEVICE_POINTER_SECOND, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 0,
|
|
"no mouse stands for a touch of the second list");
|
|
|
|
/* MOUSE_BY_DRIVER */
|
|
f.rel = VIDEO_POS_PACK(3, 4);
|
|
f.buttons = INPUT_POINTER_RIGHT | INPUT_POINTER_WHEEL_DOWN;
|
|
input_pointer_frames_set(&f, NULL, 1, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == 3
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == 3,
|
|
"without MOUSE_BY_DRIVER the frontend answers the mouse");
|
|
input_pointer_frames_set(&f, NULL, 1, INPUT_POINTERS_MOUSE_BY_DRIVER);
|
|
CHECK( rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == -2
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == -2
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN) == -2
|
|
&& rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == -2
|
|
&& rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_WHEELUP) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_Y) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == -2
|
|
&& !input_pointer_frame_pos(0, RETRO_DEVICE_MOUSE, 0, &pos)
|
|
&& !input_pointer_frame_pos(0, RARCH_DEVICE_MOUSE_SCREEN, 0, &pos),
|
|
"with it the mouse, the lightgun's motion and its mouse aim are the driver's");
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
input_pointer_frames_set(&f, NULL, 1,
|
|
INPUT_POINTERS_MOUSE_BY_DRIVER | INPUT_POINTERS_GUN_AT_TOUCH);
|
|
touches_set(touch, 1, 1);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 60
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == -2
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60,
|
|
"a lightgun aimed at a touch is the frontend's, its motion still the driver's");
|
|
|
|
/* TOUCH_SLOTS: slot 0 never placed, 1 lifted off the viewport, 2 down */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
touch[1] = VIDEO_POS_PACK(250, 40);
|
|
touch[2] = VIDEO_POS_PACK(30, 40);
|
|
f.buttons = INPUT_POINTER_LEFT;
|
|
input_pointer_frames_set(&f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, NULL, 3, 6, 4);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 10
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 1, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 2, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 10,
|
|
"without TOUCH_SLOTS the mouse stands for an index with no touch");
|
|
input_pointer_frames_set(&f, NULL, 1,
|
|
INPUT_POINTERS_GUN_AT_TOUCH | INPUT_POINTERS_TOUCH_SLOTS);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 199
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 1, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_X) == 30
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"with it an index is a slot: none reads 0, a lifted one keeps its place");
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 1, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 1, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 2, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) == 40
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 3, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 0,
|
|
"and the lightgun aims at the touch at its index, never the mouse");
|
|
input_pointer_frames_set(&f, NULL, 1, INPUT_POINTERS_TOUCH_SLOTS);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 1, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 2, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 0,
|
|
"its IS_OFFSCREEN is that touch's while the mouse aims it");
|
|
|
|
/* A touch over its own window's whole client area */
|
|
memset(tw, 0, sizeof(tw));
|
|
tw[0].window = 1;
|
|
tw[0].generation = 5;
|
|
tw[2] = tw[0];
|
|
touch[0] = VIDEO_POS_PACK(0, 50);
|
|
touch[1] = VIDEO_POS_PACK(5, 5);
|
|
touch[2] = VIDEO_POS_PACK(100, 25);
|
|
shown_window = 1;
|
|
shown_dims = VIDEO_SCALE_PACK(101, 51);
|
|
input_pointer_touches_set(touch, tw, 3, 7, 5);
|
|
CHECK( input_pointer_window_touch(1, 0, &pos, &down)
|
|
&& pos == VIDEO_POS_PACK(-0x7fff, 0x7fff) && down
|
|
&& input_pointer_window_touch(1, 1, &pos, &down)
|
|
&& pos == VIDEO_POS_PACK(0x7fff, -1) && down
|
|
&& !input_pointer_window_touch(1, 2, &pos, &down)
|
|
&& !input_pointer_window_touch(2, 0, &pos, &down),
|
|
"a window's touches over its whole client area, in order; none past them or elsewhere");
|
|
touch[2] = VIDEO_POS_PACK(150, -3);
|
|
input_pointer_touches_set(touch, tw, 3, 7, 1);
|
|
CHECK( input_pointer_window_touch(1, 1, &pos, &down)
|
|
&& pos == VIDEO_POS_PACK(-0x8000, -0x8000) && !down,
|
|
"outside its window: -0x8000; a lifted touch is not down");
|
|
input_pointer_touches_set(touch, NULL, 3, 7, 1);
|
|
CHECK(!input_pointer_window_touch(1, 0, &pos, &down),
|
|
"a publication without windows has no window touches");
|
|
shown_window = 0;
|
|
CHECK(!input_pointer_window_touch(1, 0, &pos, &down),
|
|
"a window that has not shown has no touches");
|
|
input_pointer_frames_clear();
|
|
}
|
|
|
|
/* 17. Android's publication against the driver as it was. The publish
|
|
* calls are input_driver.c's. */
|
|
#include "input/drivers/android_pointers.h"
|
|
|
|
input_pointer_frame_t *input_driver_pointers_lend(void)
|
|
{
|
|
return input_pointers.frame;
|
|
}
|
|
|
|
uint32_t *input_driver_touches_lend(void)
|
|
{
|
|
return input_pointers.touch_pos;
|
|
}
|
|
|
|
void input_driver_publish_window_pointers(
|
|
const input_pointer_frame_t *frames,
|
|
const input_video_window_t *windows,
|
|
unsigned count, unsigned flags)
|
|
{
|
|
input_pointer_frames_set(frames, windows, count, flags);
|
|
}
|
|
|
|
void input_driver_publish_window_touches(const uint32_t *pos,
|
|
const input_video_window_t *windows, unsigned count,
|
|
unsigned present, unsigned down)
|
|
{
|
|
input_pointer_touches_set(pos, windows, count, present, down);
|
|
}
|
|
|
|
/* Before the publication the driver kept each touch placed
|
|
* three ways, as its event came. The same fingers go to both. */
|
|
struct was_pointer
|
|
{
|
|
uint32_t pos;
|
|
uint32_t confined_pos;
|
|
uint32_t full_pos;
|
|
};
|
|
|
|
static struct was_pointer was_main[16], was_second[16];
|
|
static unsigned was_count, was_second_count;
|
|
static struct input_pointer now_main[16], now_second[16];
|
|
static unsigned now_count, now_second_count;
|
|
static input_video_window_t now_window;
|
|
static bool mouse_used;
|
|
|
|
/* android_pointer_set(), before the publication and with it */
|
|
static void finger_place(unsigned i, int x, int y)
|
|
{
|
|
struct video_viewport vp;
|
|
memset(&vp, 0, sizeof(vp));
|
|
if (video_driver_get_viewport_info(&vp))
|
|
{
|
|
video_driver_translate_coord_viewport(&vp, x, y,
|
|
&was_main[i].confined_pos, &was_main[i].full_pos, false);
|
|
video_driver_translate_coord_viewport(&vp, x, y,
|
|
&was_main[i].pos, &was_main[i].full_pos, true);
|
|
}
|
|
now_main[i].pos = VIDEO_POS_PACK(x, y);
|
|
now_main[i].placed = true;
|
|
}
|
|
|
|
/* A touch event with @n fingers at @xy: each placed, as the driver's
|
|
* motion handler does */
|
|
static void fingers_move(unsigned n, const int *xy)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
finger_place(i, xy[2 * i], xy[2 * i + 1]);
|
|
if (was_count < i + 1)
|
|
was_count = i + 1;
|
|
if (now_count < i + 1)
|
|
now_count = i + 1;
|
|
}
|
|
}
|
|
|
|
/* Finger @i up: the slots above shift down */
|
|
static void finger_up(unsigned i)
|
|
{
|
|
memmove(&was_main[i], &was_main[i + 1],
|
|
(16 - i - 1) * sizeof(was_main[0]));
|
|
memmove(&now_main[i], &now_main[i + 1],
|
|
(16 - i - 1) * sizeof(now_main[0]));
|
|
if (was_count)
|
|
was_count--;
|
|
if (now_count)
|
|
now_count--;
|
|
}
|
|
|
|
/* The second display's finger @i, in down order, at @x, @y of window
|
|
* 1, generation 5; a new one when @i is the count.
|
|
* android_input_poll_second_touches(), then and now. */
|
|
static void second_place(unsigned i, int x, int y)
|
|
{
|
|
if (!video_driver_translate_window_point(1, 5, x, y, false,
|
|
&was_second[i].confined_pos))
|
|
was_second[i].confined_pos = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
if (!video_driver_translate_window_point(1, 5, x, y, true,
|
|
&was_second[i].pos))
|
|
was_second[i].pos = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
was_second[i].full_pos = VIDEO_POS_PACK(-0x8000, -0x8000);
|
|
now_second[i].pos = VIDEO_POS_PACK(x, y);
|
|
now_second[i].placed = true;
|
|
now_window.window = 1;
|
|
now_window.generation = 5;
|
|
if (i == was_second_count)
|
|
{
|
|
was_second_count++;
|
|
now_second_count++;
|
|
}
|
|
}
|
|
|
|
static void second_up(unsigned i)
|
|
{
|
|
memmove(&was_second[i], &was_second[i + 1],
|
|
(was_second_count - i - 1) * sizeof(was_second[0]));
|
|
memmove(&now_second[i], &now_second[i + 1],
|
|
(now_second_count - i - 1) * sizeof(now_second[0]));
|
|
was_second_count--;
|
|
now_second_count--;
|
|
}
|
|
|
|
/* android_input_state() before the publication, for what
|
|
* the publication answers: the pointer, the screen pointer, the second
|
|
* display's and a touch's lightgun aim */
|
|
static int16_t was_state(unsigned device, unsigned idx, unsigned id)
|
|
{
|
|
const struct was_pointer *p = (idx < 16) ? &was_main[idx] : NULL;
|
|
switch (device)
|
|
{
|
|
case RETRO_DEVICE_LIGHTGUN:
|
|
if (!p)
|
|
return 0;
|
|
if (id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X)
|
|
return VIDEO_POS_X(p->pos);
|
|
if (id == RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y)
|
|
return VIDEO_POS_Y(p->pos);
|
|
return input_driver_pointer_is_offscreen(
|
|
VIDEO_POS_X(p->pos), VIDEO_POS_Y(p->pos));
|
|
case RETRO_DEVICE_POINTER:
|
|
case RARCH_DEVICE_POINTER_SCREEN:
|
|
if (id == RETRO_DEVICE_ID_POINTER_COUNT)
|
|
return (int16_t)was_count;
|
|
if (!p)
|
|
return 0;
|
|
switch (id)
|
|
{
|
|
case RETRO_DEVICE_ID_POINTER_X:
|
|
return VIDEO_POS_X((device == RARCH_DEVICE_POINTER_SCREEN)
|
|
? p->full_pos : p->confined_pos);
|
|
case RETRO_DEVICE_ID_POINTER_Y:
|
|
return VIDEO_POS_Y((device == RARCH_DEVICE_POINTER_SCREEN)
|
|
? p->full_pos : p->confined_pos);
|
|
case RETRO_DEVICE_ID_POINTER_PRESSED:
|
|
{
|
|
uint32_t at = (device == RARCH_DEVICE_POINTER_SCREEN)
|
|
? p->full_pos : p->pos;
|
|
return idx < was_count
|
|
&& VIDEO_POS_X(at) != -0x8000
|
|
&& VIDEO_POS_Y(at) != -0x8000;
|
|
}
|
|
case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN:
|
|
return input_driver_pointer_is_offscreen(
|
|
VIDEO_POS_X(p->pos), VIDEO_POS_Y(p->pos));
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
case RARCH_DEVICE_POINTER_SECOND:
|
|
if (id == RETRO_DEVICE_ID_POINTER_COUNT)
|
|
return (int16_t)was_second_count;
|
|
if (idx >= was_second_count)
|
|
return 0;
|
|
p = &was_second[idx];
|
|
switch (id)
|
|
{
|
|
case RETRO_DEVICE_ID_POINTER_X:
|
|
return VIDEO_POS_X(p->confined_pos);
|
|
case RETRO_DEVICE_ID_POINTER_Y:
|
|
return VIDEO_POS_Y(p->confined_pos);
|
|
case RETRO_DEVICE_ID_POINTER_PRESSED:
|
|
return VIDEO_POS_X(p->pos) != -0x8000
|
|
&& VIDEO_POS_Y(p->pos) != -0x8000;
|
|
case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN:
|
|
return input_driver_pointer_is_offscreen(
|
|
VIDEO_POS_X(p->pos), VIDEO_POS_Y(p->pos));
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Publishes the fingers as android_input_publish() does, then reads,
|
|
* at two ports, every answer the publication gives Android and
|
|
* compares it with the driver's; the number that differ. */
|
|
static unsigned android_compare(const char *what)
|
|
{
|
|
static const unsigned devices[3] = { RETRO_DEVICE_POINTER,
|
|
RARCH_DEVICE_POINTER_SCREEN, RARCH_DEVICE_POINTER_SECOND };
|
|
static const unsigned ids[5] = { RETRO_DEVICE_ID_POINTER_X,
|
|
RETRO_DEVICE_ID_POINTER_Y, RETRO_DEVICE_ID_POINTER_PRESSED,
|
|
RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN, RETRO_DEVICE_ID_POINTER_COUNT };
|
|
static const unsigned gun[3] = { RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X,
|
|
RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y,
|
|
RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN };
|
|
android_pointers_t p;
|
|
unsigned port, d, idx, i;
|
|
unsigned bad = 0;
|
|
|
|
memset(&p, 0, sizeof(p));
|
|
p.main_slots = now_main;
|
|
p.slots = 16;
|
|
p.main_count = now_count;
|
|
p.second = now_second;
|
|
p.second_count = now_second_count;
|
|
p.second_window = now_window;
|
|
p.mouse_pos = VIDEO_POS_PACK(5, 5);
|
|
p.mouse_buttons = INPUT_POINTER_LEFT;
|
|
p.mouse_used = mouse_used;
|
|
input_pointer_frames_clear();
|
|
android_pointers_publish(&p);
|
|
|
|
for (port = 0; port < 2; port++)
|
|
{
|
|
for (d = 0; d < 3; d++)
|
|
for (idx = 0; idx < 18; idx++)
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
int16_t got = rd(port, devices[d], idx, ids[i]);
|
|
int16_t want = was_state(devices[d], idx, ids[i]);
|
|
if (got != want && !bad++)
|
|
printf(" %s: device %x idx %u id %u reads %d, was %d\n",
|
|
what, devices[d], idx, ids[i], got, want);
|
|
}
|
|
for (idx = 0; idx < 18; idx++)
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
int16_t got = rd(port, RETRO_DEVICE_LIGHTGUN, idx, gun[i]);
|
|
int16_t want = (mouse_used
|
|
&& gun[i] != RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN)
|
|
? -2 : was_state(RETRO_DEVICE_LIGHTGUN, idx, gun[i]);
|
|
if (got != want && !bad++)
|
|
printf(" %s: lightgun idx %u id %u reads %d, was %d\n",
|
|
what, idx, gun[i], got, want);
|
|
}
|
|
/* the menu's pointer, read as a place */
|
|
for (idx = 0; idx < 18; idx++)
|
|
{
|
|
uint32_t pos = 1;
|
|
uint32_t want = VIDEO_POS_PACK(
|
|
was_state(RETRO_DEVICE_POINTER, idx,
|
|
RETRO_DEVICE_ID_POINTER_X),
|
|
was_state(RETRO_DEVICE_POINTER, idx,
|
|
RETRO_DEVICE_ID_POINTER_Y));
|
|
if ( ( !input_pointer_frame_pos(port, RETRO_DEVICE_POINTER,
|
|
idx, &pos)
|
|
|| pos != want)
|
|
&& !bad++)
|
|
printf(" %s: pointer %u placed at %08x, was %08x\n",
|
|
what, idx, (unsigned)pos, (unsigned)want);
|
|
}
|
|
/* the overlay's fingers, each read at one look */
|
|
for (d = 0; d < 2; d++)
|
|
for (idx = 0; idx < 18; idx++)
|
|
{
|
|
uint32_t pos = 1;
|
|
int down = input_pointer_frame_finger(port, devices[d],
|
|
idx, &pos);
|
|
int16_t want = was_state(devices[d], idx,
|
|
RETRO_DEVICE_ID_POINTER_PRESSED);
|
|
uint32_t at = VIDEO_POS_PACK(
|
|
was_state(devices[d], idx, RETRO_DEVICE_ID_POINTER_X),
|
|
was_state(devices[d], idx, RETRO_DEVICE_ID_POINTER_Y));
|
|
if ( (down != want || (want && pos != at))
|
|
&& !bad++)
|
|
printf(" %s: device %x finger %u reads %d at %08x, was %d"
|
|
" at %08x\n", what, devices[d], idx, down,
|
|
(unsigned)pos, want, (unsigned)at);
|
|
}
|
|
}
|
|
return bad;
|
|
}
|
|
|
|
/* 17 */
|
|
static void test_android_answers(void)
|
|
{
|
|
static const int one[2] = { 40, 30 };
|
|
static const int three[6] = { 10, 10, 250, 40, 60, 90 };
|
|
int many[32];
|
|
unsigned i;
|
|
uint32_t pos = 0;
|
|
|
|
memset(was_main, 0, sizeof(was_main));
|
|
memset(was_second, 0, sizeof(was_second));
|
|
memset(now_main, 0, sizeof(now_main));
|
|
memset(now_second, 0, sizeof(now_second));
|
|
memset(&now_window, 0, sizeof(now_window));
|
|
was_count = was_second_count = 0;
|
|
now_count = now_second_count = 0;
|
|
mouse_used = false;
|
|
|
|
CHECK(!android_compare("no touch yet"),
|
|
"Android, no touch yet: every answer as before");
|
|
fingers_move(1, one);
|
|
CHECK(!android_compare("one finger"),
|
|
"Android, one finger: every answer as before");
|
|
finger_up(0);
|
|
CHECK(!android_compare("lifted"),
|
|
"Android, the finger up: its index reads what its slot holds, as before");
|
|
finger_place(0, 30, 40);
|
|
CHECK(!android_compare("pen hovering"),
|
|
"Android, a pen hovering: placed, not down, as before");
|
|
fingers_move(3, three);
|
|
CHECK(!android_compare("three fingers"),
|
|
"Android, three fingers, one off the viewport: every answer as before");
|
|
finger_up(1);
|
|
CHECK(!android_compare("the middle one up"),
|
|
"Android, the middle finger up: the slots above shift down, as before");
|
|
finger_place(0, -150, 120);
|
|
CHECK(!android_compare("the pen off the screen"),
|
|
"Android, the pen off the screen: every answer as before");
|
|
second_place(0, 20, 30);
|
|
second_place(1, 150, 40);
|
|
CHECK(!android_compare("two on the second display"),
|
|
"Android, two fingers on the second display, one off its screen: every answer as before");
|
|
second_up(0);
|
|
CHECK(!android_compare("one up on the second display"),
|
|
"Android, one up on the second display: every answer as before");
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
many[2 * i] = 12 * i;
|
|
many[2 * i + 1] = 6 * i;
|
|
}
|
|
fingers_move(16, many);
|
|
for (i = 0; i < 16; i++)
|
|
second_place(i, 6 * i, 6 * i);
|
|
CHECK(!android_compare("sixteen on each display"),
|
|
"Android, sixteen fingers on each display: none dropped, every answer as before");
|
|
finger_up(3);
|
|
CHECK(!android_compare("one of sixteen up"),
|
|
"Android, one of sixteen up: the top slot keeps its place, as before");
|
|
mouse_used = true;
|
|
CHECK(!android_compare("a mouse in use"),
|
|
"Android, a mouse in use: its lightgun aim is the driver's, the rest as before");
|
|
|
|
/* What the driver keeps, with today's code: every read reaches it */
|
|
{
|
|
bool driver = true;
|
|
for (i = RETRO_DEVICE_ID_MOUSE_X; i <= RETRO_DEVICE_ID_MOUSE_BUTTON_5; i++)
|
|
if ( rd(0, RETRO_DEVICE_MOUSE, 0, i) != -2
|
|
|| rd(1, RARCH_DEVICE_MOUSE_SCREEN, 0, i) != -2)
|
|
driver = false;
|
|
CHECK( driver
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_Y) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_TRIGGER) == -2
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RARCH_DEVICE_ID_POINTER_BACK) == -2
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RARCH_DEVICE_ID_POINTER_BACK) == -2
|
|
&& !input_pointer_frame_pos(0, RARCH_DEVICE_MOUSE_SCREEN, 0, &pos),
|
|
"Android: the mouse, the lightgun's motion and buttons, and BACK are the driver's");
|
|
}
|
|
CHECK( input_pointers.count == 1
|
|
&& input_pointers.frame[0].buttons == INPUT_POINTER_LEFT
|
|
&& input_pointers.frame[0].rel == 0,
|
|
"Android's mouse is published, for binds to its buttons");
|
|
input_pointer_frames_clear();
|
|
}
|
|
|
|
/* 18 */
|
|
static void test_android_gun_fingers(void)
|
|
{
|
|
video_views_layout_t layout;
|
|
memset(&layout, 0, sizeof(layout));
|
|
CHECK( android_pointers_gun_fingers(1, NULL) == 1
|
|
&& android_pointers_gun_fingers(3, NULL) == 3,
|
|
"Android, no views: every finger counts for the lightgun's buttons");
|
|
layout.num_placements = 1;
|
|
CHECK( android_pointers_gun_fingers(1, &layout) == 1
|
|
&& android_pointers_gun_fingers(2, &layout) == 2,
|
|
"Android, a main window that shows a screen: a tap counts, in its letterbox too");
|
|
layout.num_placements = 0;
|
|
CHECK( android_pointers_gun_fingers(1, &layout) == 0
|
|
&& android_pointers_gun_fingers(3, &layout) == 0,
|
|
"Android, a main window that shows no screen: a tap there is on nothing");
|
|
}
|
|
|
|
/* Frames a driver wrote in place are published as they are. */
|
|
static void test_lent_frames(void)
|
|
{
|
|
input_pointer_frame_t *lent = input_pointers.frame;
|
|
memset(lent, 0, 2 * sizeof(*lent));
|
|
lent[1].buttons = INPUT_POINTER_RIGHT;
|
|
input_pointer_frames_set(lent, NULL, 2, 0);
|
|
CHECK(input_pointers.count == 2
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 0,
|
|
"frames written in place are read as published");
|
|
|
|
input_pointers.touch_pos[0] = VIDEO_POS_PACK(12, 34);
|
|
input_pointer_touches_set(input_pointers.touch_pos, NULL, 1, 1, 1);
|
|
CHECK(input_pointers.touch_count == 1
|
|
&& input_pointers.touch_pos[0] == VIDEO_POS_PACK(12, 34)
|
|
&& input_pointers.touch_down == 1,
|
|
"places written in place are read as published");
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
input_pointer_frame_t f[2];
|
|
uint32_t touch[3];
|
|
uint32_t pos = 0;
|
|
|
|
memset(f, 0, sizeof(f));
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
f[0].rel = VIDEO_POS_PACK(-3, 7);
|
|
f[0].buttons = INPUT_POINTER_RIGHT | INPUT_POINTER_WHEEL_DOWN;
|
|
f[1].pos = VIDEO_POS_PACK(5, 6);
|
|
f[1].buttons = INPUT_POINTER_LEFT;
|
|
|
|
/* 7 (before anything is published) */
|
|
input_pointer_frames_clear();
|
|
CHECK(rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == -2
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == -2
|
|
&& !input_pointer_frame_pos(0, RETRO_DEVICE_MOUSE, 0, &pos),
|
|
"nothing published: the driver is to be asked");
|
|
|
|
/* 1 */
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
CHECK(rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == -3
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y) == 7,
|
|
"the mouse's motion");
|
|
CHECK(rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 40
|
|
&& rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_Y) == 30,
|
|
"the mouse's place in the window");
|
|
CHECK(input_pointer_frame_pos(0, RARCH_DEVICE_MOUSE_SCREEN, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(40, 30)
|
|
&& input_pointer_frame_pos(0, RETRO_DEVICE_MOUSE, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(-3, 7),
|
|
"the packed position is the published word");
|
|
CHECK( rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 0
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE) == 0
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_4) == 0,
|
|
"the mouse's buttons");
|
|
CHECK( rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 1
|
|
&& rd(1, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 5,
|
|
"the second port reads the second device");
|
|
CHECK( rd(2, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 0
|
|
&& rd(2, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 0,
|
|
"a port with no device reads nothing, and not the driver");
|
|
CHECK( rd(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B) == -2
|
|
&& rd(0, RETRO_DEVICE_KEYBOARD, 0, RETROK_a) == -2
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_TRIGGER) == -2,
|
|
"pads, keys and the lightgun's buttons are still the driver's");
|
|
|
|
/* 2 */
|
|
CHECK( rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELUP) == 0,
|
|
"a wheel notch reads the same every time in its frame");
|
|
|
|
/* 3: a mouse for three touches - any button; right or middle; middle */
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 30
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X) == 1040,
|
|
"the pointer is where the translation puts the mouse");
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 3, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(1, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0,
|
|
"a mouse standing for three touches");
|
|
/* ...and for one: the left button */
|
|
input_pointer_frames_set(f, NULL, 2, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(1, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(1, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 0,
|
|
"a mouse standing for one touch");
|
|
|
|
/* 6 */
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
vp_asked = translations = 0;
|
|
rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
|
|
rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
|
|
rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED);
|
|
rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED);
|
|
rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN);
|
|
rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
input_pointer_frame_pos(0, RETRO_DEVICE_POINTER, 0, &pos);
|
|
CHECK(vp_asked == 1 && translations == 1,
|
|
"eight pointer reads: one viewport fetch, one translation");
|
|
rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X);
|
|
rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y);
|
|
rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN);
|
|
CHECK(vp_asked == 1 && translations == 2,
|
|
"the lightgun's aim after them: no fetch, one translation more");
|
|
rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
CHECK(vp_asked == 1 && translations == 3,
|
|
"a second device: no fetch, one translation more");
|
|
rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
|
|
rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X);
|
|
CHECK(vp_asked == 1 && translations == 3, "the mouse needs neither");
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
CHECK(vp_asked == 2 && translations == 4, "the next poll places it afresh");
|
|
|
|
/* 5: out of the viewport the pointer holds to the edge, the gun says so */
|
|
f[0].pos = VIDEO_POS_PACK(250, 30);
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 199
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) == 30
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == -3,
|
|
"out of the viewport: the pointer holds to the edge, the lightgun is off-screen");
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
|
|
/* 4: touch 0 down at 60,70; touch 1 lifted, last at 80,90; no touch 2 */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
touch[1] = VIDEO_POS_PACK(80, 90);
|
|
touch[2] = 0;
|
|
f[0].buttons = INPUT_POINTER_MIDDLE;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
/* places 0 and 1 hold a contact; place 2 holds none */
|
|
input_pointer_touches_set(touch, NULL, 3, 3, 1 << 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 70
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_Y) == 1070
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"a touch that is down: its place, pressed");
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 80
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"a lifted touch keeps its place, and is pressed as the mouse says");
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"a place with no touch reads the mouse");
|
|
CHECK(input_pointer_frame_pos(3, RETRO_DEVICE_POINTER, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(60, 70)
|
|
&& input_pointer_frame_pos(0, RARCH_DEVICE_POINTER_SCREEN, 1, &pos)
|
|
&& pos == VIDEO_POS_PACK(1080, 1090),
|
|
"the packed pointer position, and one mouse is every port's");
|
|
f[0].buttons = 0;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
/* places 0 and 1 hold a contact; place 2 holds none */
|
|
input_pointer_touches_set(touch, NULL, 3, 3, 1 << 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"with no button held only the touch that is down is pressed");
|
|
|
|
/* 8: by Mouse Index - port 0 reads device 1, port 1 device 0 */
|
|
f[0].buttons = INPUT_POINTER_RIGHT;
|
|
f[1].buttons = INPUT_POINTER_LEFT;
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_BY_MOUSE_INDEX);
|
|
touches_set(touch, 1, 1 << 0);
|
|
CHECK( rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 1
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 0
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == 1
|
|
&& rd(1, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 40,
|
|
"by Mouse Index: a port reads the device at its index");
|
|
CHECK( rd(2, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 0
|
|
&& rd(2, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 0
|
|
&& rd(2, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 0,
|
|
"by Mouse Index: a port whose mouse is not there reads nothing");
|
|
CHECK( rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60
|
|
&& rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(2, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& input_pointer_frame_pos(2, RETRO_DEVICE_POINTER, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(60, 70),
|
|
"a port with no mouse still reads a real touch, and only that");
|
|
touches_set(touch, 0, 0);
|
|
CHECK( rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0,
|
|
"with no mouse and no touch a pointer reads nothing");
|
|
/* the kind each device was last read as: port 0 is device 1 */
|
|
rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X);
|
|
rd(1, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
CHECK(input_pointers.read_as[1] == RETRO_DEVICE_LIGHTGUN
|
|
&& input_pointers.read_as[0] == RARCH_DEVICE_POINTER_SCREEN,
|
|
"each device records the kind it was last read as");
|
|
input_pointer_frame_pos(0, RETRO_DEVICE_MOUSE, 0, &pos);
|
|
input_pointer_frames_set(f, NULL, 2, INPUT_POINTERS_BY_MOUSE_INDEX);
|
|
CHECK(input_pointers.read_as[1] == RETRO_DEVICE_MOUSE
|
|
&& input_pointers.read_as[0] == RARCH_DEVICE_POINTER_SCREEN,
|
|
"and keeps it over the next poll");
|
|
|
|
/* 9: only the mouse by index; the pointer and the gun every port's.
|
|
* Port 2's mouse is not there, port 1's index is 0. */
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
f[0].buttons = INPUT_POINTER_LEFT;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_BY_MOUSE_INDEX
|
|
| INPUT_POINTERS_AIM_EVERY_PORT | INPUT_POINTERS_GUN_AT_TOUCH);
|
|
touches_set(touch, 0, 0);
|
|
CHECK( rd(2, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 0
|
|
&& rd(2, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 0
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 1,
|
|
"aim every port's: the mouse still goes by the port's index");
|
|
CHECK( rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(2, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(2, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 40
|
|
&& rd(2, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) == 30,
|
|
"aim every port's: the pointer and the lightgun read the mouse on any port");
|
|
/* the gun at the first touch while there is one; out of the viewport
|
|
* it is off-screen */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
touches_set(touch, 1, 1 << 0);
|
|
vp_asked = translations = 0;
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 60
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) == 70
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 0
|
|
&& input_pointer_frame_pos(0, RETRO_DEVICE_LIGHTGUN, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(60, 70)
|
|
&& vp_asked == 0 && translations == 1,
|
|
"the lightgun aims at the first touch: one translation, the poll's viewport");
|
|
touch[0] = VIDEO_POS_PACK(260, 70);
|
|
touches_set(touch, 1, 1 << 0);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 199,
|
|
"a touch out of the viewport: the gun is off-screen, the pointer at the edge");
|
|
touches_set(touch, 0, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 40,
|
|
"with no touch the lightgun aims at the mouse");
|
|
/* without the flag a touch does not move the gun */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
touches_set(touch, 1, 1 << 0);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 40,
|
|
"a driver that does not say so: the lightgun stays on the mouse");
|
|
|
|
/* 10: how many pointers are down - the touches that are, else the
|
|
* mouse standing for one */
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
f[0].buttons = INPUT_POINTER_LEFT;
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
touch[1] = VIDEO_POS_PACK(80, 90);
|
|
input_pointer_frames_set(f, NULL, 1, 0);
|
|
touches_set(touch, 2, 3);
|
|
CHECK(rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 2,
|
|
"the count is the touches that are down");
|
|
touches_set(touch, 0, 0);
|
|
CHECK(rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1,
|
|
"with no touch the count is the mouse's, its button held");
|
|
f[0].buttons = 0;
|
|
input_pointer_frames_set(f, NULL, 1, 0);
|
|
vp_asked = translations = 0;
|
|
CHECK(rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 0
|
|
&& vp_asked == 0 && translations == 0,
|
|
"nothing down counts none, and the count places nothing");
|
|
|
|
/* 11: the pointer placed as the lightgun is - off-screen outside */
|
|
f[0].pos = VIDEO_POS_PACK(250, 30);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_POINTER_OFFSCREEN);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 30
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 1,
|
|
"an off-screen pointer says so where the driver has it so");
|
|
touch[0] = VIDEO_POS_PACK(60, 170);
|
|
touches_set(touch, 1, 1);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_Y) == 1170,
|
|
"and so does a touch");
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
|
|
/* 12: a touch read alone - a pen in the air is not pressed by the
|
|
* mouse's button, and counts none */
|
|
f[0].buttons = INPUT_POINTER_LEFT;
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_TOUCH_ALONE);
|
|
touches_set(touch, 1, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 0,
|
|
"a touch read alone: lifted, the mouse's button does not press it");
|
|
touches_set(touch, 1, 1);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1,
|
|
"a touch read alone: down, it is pressed");
|
|
touches_set(touch, 0, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 0,
|
|
"a touch read alone: with none, the mouse stands for the first");
|
|
/* without the flag a lifted touch is pressed as the mouse says */
|
|
input_pointer_frames_set(f, NULL, 1, 0);
|
|
touches_set(touch, 1, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1,
|
|
"a driver that does not say so: a lifted touch is pressed as the mouse says");
|
|
|
|
/* 7 */
|
|
input_pointer_frames_clear();
|
|
CHECK(rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) == -2
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == -2,
|
|
"a poll in which nothing is published: the driver is to be asked");
|
|
|
|
/* 14: where a touch is, whether it is there, and whether it is down
|
|
* are three things. The mouse is at 40,30 with no button held. */
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
f[0].buttons = 0;
|
|
/* a touch down at the window's origin is a touch */
|
|
touch[0] = VIDEO_POS_PACK(0, 0);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, NULL, 1, 1, 1);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1
|
|
&& input_pointer_frame_pos(0, RETRO_DEVICE_POINTER, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(0, 0),
|
|
"a touch down at 0,0 is pressed and at 0,0, not the mouse's");
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y) == 0,
|
|
"the lightgun aims at a touch at 0,0, not at the mouse");
|
|
/* lifted at the origin, its place kept: there, not pressed */
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, NULL, 1, 1, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 0,
|
|
"a touch lifted at 0,0 keeps its place and is not pressed");
|
|
/* not there at all: the mouse answers, whatever the place holds */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, NULL, 1, 0, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 40,
|
|
"a place with no contact reads the mouse, whatever position it holds");
|
|
/* down said without there: not a touch */
|
|
input_pointer_frames_set(f, NULL, 1, 0);
|
|
input_pointer_touches_set(touch, NULL, 1, 0, 1);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 0,
|
|
"a place that is down but not there is not a touch");
|
|
/* at the viewport's edges: its first and last pixel, both down */
|
|
touch[0] = VIDEO_POS_PACK(0, 99);
|
|
touch[1] = VIDEO_POS_PACK(199, 0);
|
|
input_pointer_frames_set(f, NULL, 1, 0);
|
|
input_pointer_touches_set(touch, NULL, 2, 3, 3);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 99
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 199
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_Y) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 2,
|
|
"touches on the viewport's edges, an axis at 0 each");
|
|
/* sparse places: 0 empty, 1 down at the origin, 2 empty. The mouse
|
|
* stands for three touches and its middle button is held. */
|
|
touch[0] = VIDEO_POS_PACK(0, 0);
|
|
touch[1] = VIDEO_POS_PACK(0, 0);
|
|
touch[2] = VIDEO_POS_PACK(0, 0);
|
|
f[0].buttons = INPUT_POINTER_MIDDLE;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
input_pointer_touches_set(touch, NULL, 3, 1 << 1, 1 << 1);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RETRO_DEVICE_POINTER, 2, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 1,
|
|
"sparse places: the one with a contact reads it, the others the mouse");
|
|
/* the lightgun goes by the first place only */
|
|
f[0].buttons = 0;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
input_pointer_touches_set(touch, NULL, 3, 1 << 1, 1 << 1);
|
|
CHECK( rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 40,
|
|
"the lightgun aims at the first place's touch, and with none there at the mouse");
|
|
/* a pen in the air at the origin, read alone */
|
|
f[0].buttons = INPUT_POINTER_LEFT;
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_TOUCH_ALONE);
|
|
input_pointer_touches_set(touch, NULL, 1, 1, 0);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 0
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_COUNT) == 0,
|
|
"a pen in the air at 0,0 is there, at 0,0, and not pressed by the mouse");
|
|
f[0].buttons = 0;
|
|
|
|
/* 15: device 1 and touch 0 in window 1; device 0 and touch 1 in
|
|
* the main window */
|
|
{
|
|
input_video_window_t w[2];
|
|
memset(w, 0, sizeof(w));
|
|
w[1].window = 1;
|
|
w[1].generation = 5;
|
|
f[0].pos = VIDEO_POS_PACK(40, 30);
|
|
f[0].rel = VIDEO_POS_PACK(-3, 7);
|
|
f[0].buttons = 0;
|
|
f[1].pos = VIDEO_POS_PACK(10, 20);
|
|
f[1].rel = VIDEO_POS_PACK(4, -2);
|
|
f[1].buttons = INPUT_POINTER_LEFT;
|
|
input_pointer_frames_set(f, w, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
touches_set(touch, 0, 0);
|
|
vp_asked = translations = window_translations = 0;
|
|
CHECK( rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 2010
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) == 2020
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 0
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 2010
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 0,
|
|
"a device in a screen's window is placed through that window");
|
|
CHECK(vp_asked == 0 && translations == 0 && window_translations == 2,
|
|
"placed once a kind, with no main viewport asked for");
|
|
CHECK( rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == 4
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y) == -2
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) == 1
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X) == 4,
|
|
"its motion and buttons are its own, untranslated");
|
|
CHECK( rd(1, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == -0x8000
|
|
&& rd(1, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000
|
|
&& input_pointer_frame_pos(1, RARCH_DEVICE_MOUSE_SCREEN, 0, &pos)
|
|
&& pos == VIDEO_POS_PACK(-0x8000, -0x8000),
|
|
"and no place on the main window's screen");
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X) == 1040
|
|
&& rd(0, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == 40
|
|
&& vp_asked == 1 && translations == 1,
|
|
"the main window's device as before");
|
|
/* held to the window's edges, or off-screen as the lightgun is */
|
|
f[1].pos = VIDEO_POS_PACK(150, 20);
|
|
input_pointer_frames_set(f, w, 2, 0);
|
|
CHECK( rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 2099
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == -0x8000
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1,
|
|
"out of the window: the pointer at its edge, the lightgun off-screen");
|
|
input_pointer_frames_set(f, w, 2, INPUT_POINTERS_POINTER_OFFSCREEN);
|
|
CHECK( rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000,
|
|
"and the pointer off-screen where the driver has it so");
|
|
f[1].pos = VIDEO_POS_PACK(10, 20);
|
|
/* by Mouse Index: port 0 reads device 1, in the window */
|
|
input_pointer_frames_set(f, w, 2, INPUT_POINTERS_BY_MOUSE_INDEX);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 2010
|
|
&& rd(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == 4
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 40
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == -3,
|
|
"by Mouse Index: a port reads its device, in that device's window");
|
|
/* a window that is gone: off-screen, not the main window's place */
|
|
w[1].generation = 4;
|
|
input_pointer_frames_set(f, w, 2, INPUT_POINTERS_MOUSE_3_TOUCHES);
|
|
CHECK( rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000
|
|
&& rd(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 1
|
|
&& rd(1, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(1, RARCH_DEVICE_MOUSE_SCREEN, 0, RETRO_DEVICE_ID_MOUSE_X) == -0x8000
|
|
&& rd(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X) == 4,
|
|
"a gone window's device is off-screen, its motion still its own");
|
|
w[1].generation = 5;
|
|
/* touches: 0 in window 1, 1 in the main window */
|
|
touch[0] = VIDEO_POS_PACK(60, 70);
|
|
touch[1] = VIDEO_POS_PACK(80, 90);
|
|
input_pointer_frames_set(f, NULL, 1, INPUT_POINTERS_GUN_AT_TOUCH);
|
|
{
|
|
input_video_window_t tw[2];
|
|
tw[0] = w[1];
|
|
tw[1] = w[0];
|
|
input_pointer_touches_set(touch, tw, 2, 3, 3);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 2060
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED) == 1
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 80
|
|
&& rd(0, RARCH_DEVICE_POINTER_SCREEN, 1, RETRO_DEVICE_ID_POINTER_X) == 1080
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X) == 2060,
|
|
"a touch in a screen's window is placed through it, one in the main window as before");
|
|
tw[0].generation = 9;
|
|
input_pointer_touches_set(touch, tw, 2, 3, 3);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == -0x8000
|
|
&& rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN) == 1
|
|
&& rd(0, RETRO_DEVICE_POINTER, 1, RETRO_DEVICE_ID_POINTER_X) == 80,
|
|
"a touch in a gone window is off-screen");
|
|
input_pointer_touches_set(touch, NULL, 2, 3, 3);
|
|
CHECK( rd(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) == 60,
|
|
"touches published with no windows are the main window's");
|
|
}
|
|
touches_set(touch, 0, 0);
|
|
f[1].buttons = 0;
|
|
}
|
|
|
|
/* 13: the poll's viewport, for a driver that places its own touches:
|
|
* asked for once however often it is wanted, and afresh each poll */
|
|
input_pointer_frames_clear();
|
|
vp_asked = 0;
|
|
CHECK(input_pointer_viewport() && input_pointer_viewport()
|
|
&& input_pointer_viewport() && vp_asked == 1,
|
|
"the poll's viewport is asked for once");
|
|
input_pointer_frames_clear();
|
|
CHECK(input_pointer_viewport() && vp_asked == 2,
|
|
"and afresh after the next poll");
|
|
|
|
test_flags();
|
|
test_android_answers();
|
|
test_android_gun_fingers();
|
|
test_lent_frames();
|
|
if (failures)
|
|
{
|
|
printf("FAIL pointer_frame_test: %u failure(s)\n", failures);
|
|
return 1;
|
|
}
|
|
printf("PASS pointer_frame_test\n");
|
|
return 0;
|
|
}
|