Files
RetroArch/input/drivers/linuxraw_input.c
T
LibretroAdmin 87cfa110a1 input: an input driver's state call is not told the keyboard is held
Every input driver's state call took a flag, keyboard_mapping_blocked:
whether the keys are kept from the binds. It mattered when drivers
answered the binds themselves. The frontend answers them now, from the
keys it asks a driver for once a poll, and applies the flag itself; a
driver's state call answers the keyboard, the mouse and the pointer,
and none of the twenty-three read the flag. (udev passed it to its
touch code, which did not read it either.)

The parameter goes: from the interface, the twenty-three drivers, the
frontend's own stand-in driver and its nine calls. The frontend's own
functions keep theirs - that is where it is used.

Measured against this same master built without it, the frame's input
work over 300 frames (X11): 3,690,770 instructions to 3,690,476 with
no controller, 4,354,940 to 4,354,646 with one. An argument a call.

Checked: the frontend harness passes every lane; the X11 keyboard
session logs the same as before, and the hotkey and quit-combination
sessions what master's binary logged; the raw input keyboards test
and the plain Win32 input test, which call a driver's state function
themselves, pass under Wine. Built: Linux in full; DirectInput, raw
input and the plain Win32 driver with a mingw compiler; the Android
unity build with the NDK; Wayland; the Visual C++ 6 project and the
QNX driver on their stand-ins; a build with the optional features
off. Not compiled, there being no compiler for them here: Cocoa, UWP,
the web driver, SDL 1 and the console drivers (DOS, Wii, PS3, PS4,
PSP and Vita, Switch, Wii U); theirs is the same one line, taken out
by script.

The second of three pieces before steps 3 and 4 of the mapping
compiler (plan, section 21). The joypad, its info and the binds are
handed to the same call, and two drivers use any of it: the Wii's
reads one field of the info, the Wii U's asks the joypad for its
touch screen. With those two reworked the call would take the port
and what is asked, and nothing else.
2026-10-08 03:29:08 +02:00

240 lines
6.6 KiB
C

/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2019 - Daniel De Matteis
* Copyright (C) 2012-2015 - Michael Lelli
*
* 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/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <linux/kd.h>
#include <signal.h>
#include <boolean.h>
#include "../../verbosity.h"
#include "../common/linux_common.h"
#include "../input_keymaps.h"
#include "../input_driver.h"
typedef struct linuxraw_input
{
bool state[0x80];
linux_illuminance_sensor_t *illuminance_sensor;
} linuxraw_input_t;
static void *linuxraw_input_init(const char *joypad_driver)
{
linuxraw_input_t *linuxraw = NULL;
/* Only work on terminals. */
if (!isatty(0))
return NULL;
if (linux_terminal_grab_stdin(NULL))
{
RARCH_DBG("stdin is already used for content loading. Cannot use stdin for input.\n");
return NULL;
}
if (!(linuxraw = (linuxraw_input_t*)calloc(1, sizeof(*linuxraw))))
return NULL;
if (!linux_terminal_disable_input())
{
linux_terminal_restore_input();
free(linuxraw);
return NULL;
}
input_keymaps_init_keyboard_lut(rarch_key_map_linux);
linux_terminal_claim_stdin();
return linuxraw;
}
/* Which of @keys are down: bit n of @down for keys[n]. */
static void linuxraw_keys_down(void *data, unsigned port,
const uint16_t *keys, const uint8_t *bind, unsigned count,
uint32_t *down)
{
unsigned i;
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
(void)port;
(void)bind;
for (i = 0; i < count; i++)
if (linuxraw->state[rarch_keysym_lut[keys[i]] & 0x7F])
down[i >> 5] |= (1u << (i & 31));
}
static int16_t linuxraw_input_state(
void *data,
const input_device_driver_t *joypad,
rarch_joypad_info_t *joypad_info,
const retro_keybind_set *binds,
unsigned port,
unsigned device,
unsigned idx,
unsigned id)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
switch (device)
{
/* The RetroPad's buttons, the hotkeys and a stick's axes, where
* they are bound to keys, are the frontend's to answer: it asks
* linuxraw_keys_down() for the keys once a poll. */
case RETRO_DEVICE_KEYBOARD:
if (id && id < RETROK_LAST)
{
unsigned sym = rarch_keysym_lut[(enum retro_key)id] & 0X7F;
return linuxraw->state[sym];
}
break;
}
return 0;
}
static void linuxraw_input_free(void *data)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
if (!linuxraw)
return;
linux_terminal_restore_input();
linux_close_illuminance_sensor(linuxraw->illuminance_sensor);
free(data);
}
static bool linuxraw_input_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned rate)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
if (!linuxraw)
return false;
switch (action)
{
case RETRO_SENSOR_ILLUMINANCE_DISABLE:
/* If already disabled, then do nothing */
linux_close_illuminance_sensor(linuxraw->illuminance_sensor); /* noop if NULL */
linuxraw->illuminance_sensor = NULL;
case RETRO_SENSOR_GYROSCOPE_DISABLE:
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
/** Unimplemented sensor actions that probably shouldn't fail */
return true;
case RETRO_SENSOR_ILLUMINANCE_ENABLE:
if (linuxraw->illuminance_sensor)
/* If the light sensor is already open, just set the rate */
linux_set_illuminance_sensor_rate(linuxraw->illuminance_sensor, rate);
else
linuxraw->illuminance_sensor = linux_open_illuminance_sensor(rate);
return linuxraw->illuminance_sensor != NULL;
default:
break;
}
return false;
}
static float linuxraw_input_get_sensor_input(void *data, unsigned port, unsigned id)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
if (!linuxraw)
return 0.0f;
switch (id)
{
case RETRO_SENSOR_ILLUMINANCE:
if (linuxraw->illuminance_sensor)
return linux_get_illuminance_reading(linuxraw->illuminance_sensor);
default:
break;
}
return 0.0f;
}
static void linuxraw_input_poll(void *data)
{
uint8_t c;
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
while (read(STDIN_FILENO, &c, 1) > 0)
{
bool pressed;
uint16_t t;
if (c == KEY_C && (linuxraw->state[KEY_LEFTCTRL] || linuxraw->state[KEY_RIGHTCTRL]))
kill(getpid(), SIGINT);
pressed = !(c & 0x80);
c &= ~0x80;
/* ignore extended scancodes */
if (!c)
read(STDIN_FILENO, &t, 2);
else
{
unsigned keyboardcode = input_keymaps_translate_keysym_to_rk(c);
uint16_t mod = 0;
if (linuxraw->state[KEY_LEFTCTRL] || linuxraw->state[KEY_RIGHTCTRL])
mod |= RETROKMOD_CTRL;
if (linuxraw->state[KEY_LEFTALT] || linuxraw->state[KEY_RIGHTALT])
mod |= RETROKMOD_ALT;
if (linuxraw->state[KEY_LEFTSHIFT] || linuxraw->state[KEY_RIGHTSHIFT])
mod |= RETROKMOD_SHIFT;
if (linuxraw->state[KEY_LEFTMETA] || linuxraw->state[KEY_RIGHTMETA])
mod |= RETROKMOD_META;
linuxraw->state[c] = pressed;
input_keyboard_event(pressed, keyboardcode, keyboardcode, mod, RETRO_DEVICE_KEYBOARD);
}
}
}
static uint64_t linuxraw_get_capabilities(void *data)
{
return (1 << RETRO_DEVICE_JOYPAD)
| (1 << RETRO_DEVICE_ANALOG)
| (1 << RETRO_DEVICE_KEYBOARD);
}
input_driver_t input_linuxraw = {
linuxraw_input_init,
linuxraw_input_poll,
linuxraw_input_state,
linuxraw_input_free,
linuxraw_input_set_sensor_state,
linuxraw_input_get_sensor_input,
linuxraw_get_capabilities,
"linuxraw",
NULL, /* grab_mouse */
linux_terminal_grab_stdin,
NULL,
NULL, /* survives_video */
linuxraw_keys_down
};