diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp
index da1fd25e..a6144243 100644
--- a/emulator/emulator.hpp
+++ b/emulator/emulator.hpp
@@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "higan";
- static const char Version[] = "093.11";
+ static const char Version[] = "093.12";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
static const char Website[] = "http://byuu.org/";
diff --git a/emulator/interface.hpp b/emulator/interface.hpp
index cb2be617..26ad8906 100644
--- a/emulator/interface.hpp
+++ b/emulator/interface.hpp
@@ -31,7 +31,7 @@ struct Interface {
string name;
struct Input {
unsigned id;
- unsigned type; //0 = digital, 1 = analog (relative), 2 = analog (absolute), 3 = rumble
+ unsigned type; //0 = digital, 1 = analog (relative), 2 = rumble
string name;
unsigned guid;
};
diff --git a/gba/interface/interface.cpp b/gba/interface/interface.cpp
index 54b2b0a3..e5618a5c 100644
--- a/gba/interface/interface.cpp
+++ b/gba/interface/interface.cpp
@@ -139,7 +139,7 @@ Interface::Interface() {
device.input.append({ 7, 0, "Down" });
device.input.append({ 8, 0, "R" });
device.input.append({ 9, 0, "L" });
- device.input.append({10, 3, "Rumble"});
+ device.input.append({10, 2, "Rumble"});
device.order = {6, 7, 5, 4, 1, 0, 9, 8, 2, 3, 10};
this->device.append(device);
}
diff --git a/nall/hid.hpp b/nall/hid.hpp
new file mode 100644
index 00000000..d8d865c2
--- /dev/null
+++ b/nall/hid.hpp
@@ -0,0 +1,117 @@
+#ifndef NALL_HID_HPP
+#define NALL_HID_HPP
+
+namespace nall {
+
+namespace HID {
+ struct Input {
+ string name;
+ int16_t value = 0;
+
+ Input() {}
+ Input(const string& name) : name(name) {}
+ };
+
+ struct Group {
+ string name;
+ vector input;
+
+ Group() {}
+ Group(const string& name) : name(name) {}
+
+ void append(const string& name) {
+ input.append({name});
+ }
+
+ optional find(const string& name) {
+ for(unsigned id = 0; id < input.size(); id++) {
+ if(input[id].name == name) return {true, id};
+ }
+ return false;
+ }
+ };
+
+ struct Device {
+ uint64_t id = 0;
+ string name;
+ vector group;
+
+ Device() {
+ group.resize(4);
+ }
+
+ uint32_t pathID() const { return (uint32_t)(id >> 32); }
+ uint32_t deviceID() const { return (uint32_t)(id >> 0); }
+ uint16_t vendorID() const { return (uint16_t)(id >> 16); }
+ uint16_t productID() const { return (uint16_t)(id >> 0); }
+
+ virtual bool isNull() const { return false; }
+ virtual bool isKeyboard() const { return false; }
+ virtual bool isMouse() const { return false; }
+ virtual bool isJoypad() const { return false; }
+
+ optional find(const string& name) {
+ for(unsigned id = 0; id < group.size(); id++) {
+ if(group[id].name == name) return {true, id};
+ }
+ return false;
+ }
+ };
+
+ struct Null : Device {
+ Null() {
+ name = "Null";
+ }
+
+ bool isNull() const { return true; }
+ };
+
+ struct Keyboard : Device {
+ enum GroupID : unsigned { Button };
+ Group& button = group[0];
+
+ Keyboard() {
+ name = "Keyboard";
+ button.name = "Button";
+ }
+
+ bool isKeyboard() const { return true; }
+ };
+
+ struct Mouse : Device {
+ enum GroupID : unsigned { Axis, Button };
+ Group& axis = group[0];
+ Group& button = group[1];
+
+ Mouse() {
+ name = "Mouse";
+ axis.name = "Axis";
+ button.name = "Button";
+ }
+
+ bool isMouse() const { return true; }
+ };
+
+ struct Joypad : Device {
+ enum GroupID : unsigned { Axis, Hat, Trigger, Button };
+ Group& axis = group[0];
+ Group& hat = group[1];
+ Group& trigger = group[2];
+ Group& button = group[3];
+ bool rumble = false;
+
+ Joypad() {
+ name = "Joypad";
+ axis.name = "Axis";
+ hat.name = "Hat";
+ trigger.name = "Trigger";
+ button.name = "Button";
+ }
+
+ bool isJoypad() const { return true; }
+ };
+}
+
+}
+
+#endif
diff --git a/nall/nall.hpp b/nall/nall.hpp
index 3895c916..f021e134 100644
--- a/nall/nall.hpp
+++ b/nall/nall.hpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/nall/platform.hpp b/nall/platform.hpp
index 7273076c..469ec5bc 100644
--- a/nall/platform.hpp
+++ b/nall/platform.hpp
@@ -21,6 +21,7 @@ namespace Math {
#include
#include
+#include
#include
#include
#include
diff --git a/ruby/implementation.cpp b/ruby/implementation.cpp
index 7b187fc1..991eeb3e 100644
--- a/ruby/implementation.cpp
+++ b/ruby/implementation.cpp
@@ -19,8 +19,7 @@ using namespace nall;
/* Video */
#define DeclareVideo(Name) \
- class Video##Name : public Video { \
- public: \
+ struct Video##Name : Video { \
bool cap(const string& name) { return p.cap(name); } \
any get(const string& name) { return p.get(name); } \
bool set(const string& name, const any& value) { return p.set(name, value); } \
@@ -79,8 +78,7 @@ using namespace nall;
/* Audio */
#define DeclareAudio(Name) \
- class Audio##Name : public Audio { \
- public: \
+ struct Audio##Name : Audio { \
bool cap(const string& name) { return p.cap(name); } \
any get(const string& name) { return p.get(name); } \
bool set(const string& name, const any& value) { return p.set(name, value); } \
@@ -132,8 +130,7 @@ using namespace nall;
/* Input */
#define DeclareInput(Name) \
- class Input##Name : public Input { \
- public: \
+ struct Input##Name : Input { \
bool cap(const string& name) { return p.cap(name); } \
any get(const string& name) { return p.get(name); } \
bool set(const string& name, const any& value) { return p.set(name, value); } \
@@ -142,8 +139,9 @@ using namespace nall;
bool unacquire() { return p.unacquire(); } \
bool acquired() { return p.acquired(); } \
\
+ vector poll() { return p.poll(); } \
bool poll(int16_t* table) { return p.poll(table); } \
- void rumble(unsigned id, bool enable) { return p.rumble(id, enable); } \
+ void rumble(uint64_t id, bool enable) { return p.rumble(id, enable); } \
bool init() { return p.init(); } \
void term() { p.term(); } \
\
@@ -174,6 +172,6 @@ using namespace nall;
#include
#endif
-#ifdef INPUT_X
- #include
+#ifdef INPUT_XLIB
+ #include
#endif
diff --git a/ruby/input.hpp b/ruby/input.hpp
index 8da70de2..b4d6d5ca 100644
--- a/ruby/input.hpp
+++ b/ruby/input.hpp
@@ -13,8 +13,9 @@ struct Input {
virtual bool unacquire() { return false; }
virtual bool acquired() { return false; }
+ virtual nall::vector poll() { return {}; }
virtual bool poll(int16_t* table) { return false; }
- virtual void rumble(unsigned id, bool enable) {}
+ virtual void rumble(uint64_t id, bool enable) {}
virtual bool init() { return true; }
virtual void term() {}
diff --git a/ruby/input/joypad/sdl.cpp b/ruby/input/joypad/sdl.cpp
new file mode 100644
index 00000000..f28f6806
--- /dev/null
+++ b/ruby/input/joypad/sdl.cpp
@@ -0,0 +1,66 @@
+#ifndef RUBY_INPUT_JOYPAD_SDL
+#define RUBY_INPUT_JOYPAD_SDL
+
+namespace ruby {
+
+struct InputJoypadSDL {
+ struct Joystick {
+ unsigned id = 0;
+ SDL_Joystick* handle = nullptr;
+ };
+ vector joysticks;
+
+ bool poll(int16_t* table) {
+ SDL_JoystickUpdate();
+ for(auto& js : joysticks) {
+ unsigned axes = min((unsigned)Joypad::Axes, SDL_JoystickNumAxes(js.handle));
+ for(unsigned axis = 0; axis < axes; axis++) {
+ table[joypad(js.id).axis(axis)] = (int16_t)SDL_JoystickGetAxis(js.handle, axis);
+ }
+
+ unsigned hats = min((unsigned)Joypad::Hats, SDL_JoystickNumHats(js.handle));
+ for(unsigned hat = 0; hat < hats; hat++) {
+ uint8_t state = SDL_JoystickGetHat(js.handle, hat);
+ int16_t value = 0;
+ if(state & SDL_HAT_UP ) value |= Joypad::HatUp;
+ if(state & SDL_HAT_DOWN ) value |= Joypad::HatDown;
+ if(state & SDL_HAT_LEFT ) value |= Joypad::HatLeft;
+ if(state & SDL_HAT_RIGHT) value |= Joypad::HatRight;
+ table[joypad(js.id).hat(hat)] = value;
+ }
+
+ //there is no SDL_JoystickNumButtons function
+ for(unsigned button = 0; button < Joypad::Buttons; button++) {
+ table[joypad(js.id).button(button)] = (bool)SDL_JoystickGetButton(js.handle, button);
+ }
+ }
+
+ return true;
+ }
+
+ bool init() {
+ SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+ SDL_JoystickEventState(SDL_IGNORE);
+
+ unsigned joystickCount = SDL_NumJoysticks();
+ for(unsigned id = 0; id < joystickCount; id++) {
+ Joystick joystick;
+ joystick.id = id;
+ joystick.handle = SDL_JoystickOpen(id);
+ }
+
+ return true;
+ }
+
+ void term() {
+ for(auto& js : joysticks) {
+ SDL_JoystickClose(js.handle);
+ }
+ joysticks.reset();
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ }
+};
+
+}
+
+#endif
diff --git a/ruby/input/joypad/udev.cpp b/ruby/input/joypad/udev.cpp
index 51126fb1..fc1b23b9 100644
--- a/ruby/input/joypad/udev.cpp
+++ b/ruby/input/joypad/udev.cpp
@@ -1,3 +1,6 @@
+#ifndef RUBY_INPUT_JOYPAD_UDEV
+#define RUBY_INPUT_JOYPAD_UDEV
+
namespace ruby {
struct InputJoypadUdev {
@@ -21,9 +24,13 @@ struct InputJoypadUdev {
};
struct Joystick {
- string path;
- dev_t device = 0;
+ HID::Joypad hid;
+
int fd = -1;
+ dev_t device = 0;
+ string deviceName;
+ string devicePath;
+
uint8_t evbit[(EV_MAX + 7) / 8] = {0};
uint8_t keybit[(KEY_MAX + 7) / 8] = {0};
uint8_t absbit[(ABS_MAX + 7) / 8] = {0};
@@ -45,6 +52,48 @@ struct InputJoypadUdev {
};
vector joysticks;
+ void assign(HID::Joypad& hid, unsigned groupID, unsigned inputID, int16_t value) {
+ auto& group = hid.group[groupID];
+ if(group.input[inputID].value == value) return;
+ if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value);
+ group.input[inputID].value = value;
+ }
+
+ void poll(vector& devices) {
+ for(auto& js : joysticks) {
+ input_event events[32];
+ signed length = 0;
+ while((length = read(js.fd, events, sizeof(events))) > 0) {
+ length /= sizeof(input_event);
+ for(unsigned i = 0; i < length; i++) {
+ signed code = events[i].code;
+ signed type = events[i].type;
+ signed value = events[i].value;
+
+ if(type == EV_ABS) {
+ if(auto input = js.axes.find({code})) {
+ signed range = input().info.maximum - input().info.minimum;
+ value = (value - input().info.minimum) * 65535ll / range - 32767;
+ assign(js.hid, HID::Joypad::GroupID::Axis, input().id, sclamp<16>(value));
+ } else if(auto input = js.hats.find({code})) {
+ signed range = input().info.maximum - input().info.minimum;
+ value = (value - input().info.minimum) * 65535ll / range - 32767;
+ assign(js.hid, HID::Joypad::GroupID::Hat, input().id, sclamp<16>(value));
+ }
+ } else if(type == EV_KEY) {
+ if(code >= BTN_MISC) {
+ if(auto input = js.buttons.find({code})) {
+ assign(js.hid, HID::Joypad::GroupID::Button, input().id, (bool)value);
+ }
+ }
+ }
+ }
+ }
+
+ devices.append(&js.hid);
+ }
+ }
+
bool poll(int16_t* table) {
unsigned i = 0;
for(auto& js : joysticks) {
@@ -121,18 +170,18 @@ struct InputJoypadUdev {
return true;
}
- void rumble(unsigned id, bool enable) {
- if(id >= joysticks.size()) return;
+ void rumble(uint64_t id, bool enable) {
+ for(auto& js : joysticks) {
+ if(js.hid.id != id) continue;
+ if(js.hid.rumble == false) continue;
- Joystick& js = joysticks[id];
- if(js.rumble == false) return;
-
- input_event play;
- memset(&play, 0, sizeof(input_event));
- play.type = EV_FF;
- play.code = js.effectID;
- play.value = enable;
- write(js.fd, &play, sizeof(input_event));
+ input_event play;
+ memset(&play, 0, sizeof(input_event));
+ play.type = EV_FF;
+ play.code = js.effectID;
+ play.value = enable;
+ write(js.fd, &play, sizeof(input_event));
+ }
}
bool init() {
@@ -167,15 +216,15 @@ struct InputJoypadUdev {
}
private:
- void createJoystick(udev_device* device, const char* path) {
+ void createJoystick(udev_device* device, const char* devicePath) {
Joystick js;
- js.path = path;
+ js.devicePath = devicePath;
struct stat st;
- if(stat(path, &st) < 0) return;
+ if(stat(devicePath, &st) < 0) return;
js.device = st.st_rdev;
- js.fd = open(path, O_RDWR | O_NONBLOCK);
+ js.fd = open(devicePath, O_RDWR | O_NONBLOCK);
if(js.fd < 0) return;
uint8_t evbit[(EV_MAX + 7) / 8] = {0};
@@ -199,6 +248,7 @@ private:
if(js.vendorID == udev_device_get_sysattr_value(root, "idVendor")
&& js.productID == udev_device_get_sysattr_value(root, "idProduct")
) {
+ js.deviceName = udev_device_get_devpath(root);
js.manufacturer = udev_device_get_sysattr_value(root, "manufacturer");
js.product = udev_device_get_sysattr_value(root, "product");
js.serial = udev_device_get_sysattr_value(root, "serial");
@@ -244,11 +294,24 @@ private:
js.effectID = effect.id;
}
+ createJoystickHID(js);
joysticks.append(js);
}
#undef testBit
}
+
+ void createJoystickHID(Joystick& js) {
+ uint64_t pathID = crc32_calculate((const uint8_t*)js.deviceName.data(), js.deviceName.size());
+ js.hid.id = pathID << 32 | hex(js.vendorID) << 16 | hex(js.productID) << 0;
+
+ for(unsigned n = 0; n < js.axes.size(); n++) js.hid.axis.append({n});
+ for(unsigned n = 0; n < js.hats.size(); n++) js.hid.hat.append({n});
+ for(unsigned n = 0; n < js.buttons.size(); n++) js.hid.button.append({n});
+ js.hid.rumble = js.rumble;
+ }
};
}
+
+#endif
diff --git a/ruby/input/joypad/xinput.cpp b/ruby/input/joypad/xinput.cpp
index e9dbbe37..dc4755a9 100644
--- a/ruby/input/joypad/xinput.cpp
+++ b/ruby/input/joypad/xinput.cpp
@@ -1,3 +1,6 @@
+#ifndef RUBY_INPUT_JOYPAD_XINPUT
+#define RUBY_INPUT_JOYPAD_XINPUT
+
#include
namespace ruby {
@@ -99,3 +102,5 @@ struct InputJoypadXInput {
};
}
+
+#endif
diff --git a/ruby/input/keyboard/xlib.cpp b/ruby/input/keyboard/xlib.cpp
index b5f3ef5d..c57335e1 100644
--- a/ruby/input/keyboard/xlib.cpp
+++ b/ruby/input/keyboard/xlib.cpp
@@ -1,9 +1,21 @@
+#ifndef RUBY_INPUT_KEYBOARD_XLIB
+#define RUBY_INPUT_KEYBOARD_XLIB
+
namespace ruby {
struct InputKeyboardXlib {
+ HID::Keyboard hid;
+
Display* display = nullptr;
uint8_t scancode[256] = {0};
+ struct Key {
+ string name;
+ unsigned keysym;
+ unsigned keycode;
+ };
+ vector keys;
+
enum XScancode : unsigned {
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
ScrollLock, Pause, Tilde,
@@ -18,8 +30,28 @@ struct InputKeyboardXlib {
Up, Down, Left, Right,
Tab, Return, Spacebar, Menu,
LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, LeftSuper, RightSuper,
+ Limit,
};
+ void assign(unsigned inputID, bool value) {
+ auto& group = hid.group[HID::Keyboard::GroupID::Button];
+ if(group.input[inputID].value == value) return;
+ if(input.onChange) input.onChange(hid, HID::Keyboard::GroupID::Button, inputID, group.input[inputID].value, value);
+ group.input[inputID].value = value;
+ }
+
+ void poll(vector& devices) {
+ char state[32];
+ XQueryKeymap(display, state);
+
+ for(unsigned n = 0; n < keys.size(); n++) {
+ bool value = state[keys[n].keycode >> 3] & (1 << (keys[n].keycode & 7));
+ assign(n, value);
+ }
+
+ devices.append(&hid);
+ }
+
bool poll(int16_t* table) {
char state[32];
XQueryKeymap(display, state);
@@ -146,6 +178,127 @@ struct InputKeyboardXlib {
bool init() {
display = XOpenDisplay(0);
+ keys.append({"Escape", XK_Escape});
+
+ keys.append({"F1", XK_F1});
+ keys.append({"F2", XK_F2});
+ keys.append({"F3", XK_F3});
+ keys.append({"F4", XK_F4});
+ keys.append({"F5", XK_F5});
+ keys.append({"F6", XK_F6});
+ keys.append({"F7", XK_F7});
+ keys.append({"F8", XK_F8});
+ keys.append({"F9", XK_F9});
+ keys.append({"F10", XK_F10});
+ keys.append({"F11", XK_F11});
+ keys.append({"F12", XK_F12});
+
+ keys.append({"ScrollLock", XK_Scroll_Lock});
+ keys.append({"Pause", XK_Pause});
+
+ keys.append({"Tilde", XK_asciitilde});
+
+ keys.append({"Num0", XK_0});
+ keys.append({"Num1", XK_1});
+ keys.append({"Num2", XK_2});
+ keys.append({"Num3", XK_3});
+ keys.append({"Num4", XK_4});
+ keys.append({"Num5", XK_5});
+ keys.append({"Num6", XK_6});
+ keys.append({"Num7", XK_7});
+ keys.append({"Num8", XK_8});
+ keys.append({"Num9", XK_9});
+
+ keys.append({"Dash", XK_minus});
+ keys.append({"Equal", XK_equal});
+ keys.append({"Backspace", XK_BackSpace});
+
+ keys.append({"Insert", XK_Insert});
+ keys.append({"Delete", XK_Delete});
+ keys.append({"Home", XK_Home});
+ keys.append({"End", XK_End});
+ keys.append({"PageUp", XK_Prior});
+ keys.append({"PageDown", XK_Next});
+
+ keys.append({"A", XK_A});
+ keys.append({"B", XK_B});
+ keys.append({"C", XK_C});
+ keys.append({"D", XK_D});
+ keys.append({"E", XK_E});
+ keys.append({"F", XK_F});
+ keys.append({"G", XK_G});
+ keys.append({"H", XK_H});
+ keys.append({"I", XK_I});
+ keys.append({"J", XK_J});
+ keys.append({"K", XK_K});
+ keys.append({"L", XK_L});
+ keys.append({"M", XK_M});
+ keys.append({"N", XK_N});
+ keys.append({"O", XK_O});
+ keys.append({"P", XK_P});
+ keys.append({"Q", XK_Q});
+ keys.append({"R", XK_R});
+ keys.append({"S", XK_S});
+ keys.append({"T", XK_T});
+ keys.append({"U", XK_U});
+ keys.append({"V", XK_V});
+ keys.append({"W", XK_W});
+ keys.append({"X", XK_X});
+ keys.append({"Y", XK_Y});
+ keys.append({"Z", XK_Z});
+
+ keys.append({"LeftBracket", XK_bracketleft});
+ keys.append({"RightBracket", XK_bracketright});
+ keys.append({"Backslash", XK_backslash});
+ keys.append({"Semicolon", XK_semicolon});
+ keys.append({"Apostrophe", XK_apostrophe});
+ keys.append({"Comma", XK_comma});
+ keys.append({"Period", XK_period});
+ keys.append({"Slash", XK_slash});
+
+ keys.append({"Keypad0", XK_KP_0});
+ keys.append({"Keypad1", XK_KP_1});
+ keys.append({"Keypad2", XK_KP_2});
+ keys.append({"Keypad3", XK_KP_3});
+ keys.append({"Keypad4", XK_KP_4});
+ keys.append({"Keypad5", XK_KP_5});
+ keys.append({"Keypad6", XK_KP_6});
+ keys.append({"Keypad7", XK_KP_7});
+ keys.append({"Keypad8", XK_KP_8});
+ keys.append({"Keypad9", XK_KP_9});
+
+ keys.append({"Add", XK_KP_Add});
+ keys.append({"Subtract", XK_KP_Subtract});
+ keys.append({"Multiply", XK_KP_Multiply});
+ keys.append({"Divide", XK_KP_Divide});
+ keys.append({"Enter", XK_KP_Enter});
+
+ keys.append({"Up", XK_Up});
+ keys.append({"Down", XK_Down});
+ keys.append({"Left", XK_Left});
+ keys.append({"Right", XK_Right});
+
+ keys.append({"Tab", XK_Tab});
+ keys.append({"Return", XK_Return});
+ keys.append({"Spacebar", XK_space});
+
+ keys.append({"LeftControl", XK_Control_L});
+ keys.append({"RightControl", XK_Control_R});
+ keys.append({"LeftAlt", XK_Alt_L});
+ keys.append({"RightAlt", XK_Alt_R});
+ keys.append({"LeftShift", XK_Shift_L});
+ keys.append({"RightShift", XK_Shift_R});
+ keys.append({"LeftSuper", XK_Super_L});
+ keys.append({"RightSuper", XK_Super_R});
+ keys.append({"Menu", XK_Menu});
+
+ hid.id = 1;
+
+ for(unsigned n = 0; n < keys.size(); n++) {
+ hid.button.append(keys[n].name);
+ keys[n].keycode = XKeysymToKeycode(display, keys[n].keysym);
+ }
+
#define assign(x, y) scancode[x] = XKeysymToKeycode(display, y)
assign(Escape, XK_Escape);
@@ -275,3 +428,5 @@ struct InputKeyboardXlib {
};
}
+
+#endif
diff --git a/ruby/input/mouse/xlib.cpp b/ruby/input/mouse/xlib.cpp
index 52f77970..6748c876 100644
--- a/ruby/input/mouse/xlib.cpp
+++ b/ruby/input/mouse/xlib.cpp
@@ -1,6 +1,11 @@
+#ifndef RUBY_INPUT_MOUSE_XLIB
+#define RUBY_INPUT_MOUSE_XLIB
+
namespace ruby {
struct InputMouseXlib {
+ HID::Mouse hid;
+
uintptr_t handle = 0;
Display* display = nullptr;
@@ -51,6 +56,52 @@ struct InputMouseXlib {
return ms.acquired;
}
+ void assign(unsigned groupID, unsigned inputID, int16_t value) {
+ auto& group = hid.group[groupID];
+ if(group.input[inputID].value == value) return;
+ if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value);
+ group.input[inputID].value = value;
+ }
+
+ void poll(vector& devices) {
+ Window rootReturn;
+ Window childReturn;
+ signed rootXReturn = 0;
+ signed rootYReturn = 0;
+ signed windowXReturn = 0;
+ signed windowYReturn = 0;
+ unsigned maskReturn = 0;
+ XQueryPointer(display, handle, &rootReturn, &childReturn, &rootXReturn, &rootYReturn, &windowXReturn, &windowYReturn, &maskReturn);
+
+ if(acquired()) {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(display, handle, &attributes);
+
+ //absolute -> relative conversion
+ assign(HID::Mouse::GroupID::Axis, 0, (int16_t)(rootXReturn - screenWidth / 2));
+ assign(HID::Mouse::GroupID::Axis, 1, (int16_t)(rootYReturn - screenHeight / 2));
+
+ if(hid.axis.input[0].value != 0 || hid.axis.input[1].value != 0) {
+ //if mouse moved, re-center mouse for next poll
+ XWarpPointer(display, None, rootWindow, 0, 0, 0, 0, screenWidth / 2, screenHeight / 2);
+ }
+ } else {
+ assign(HID::Mouse::GroupID::Axis, 0, (int16_t)(rootXReturn - ms.relativeX));
+ assign(HID::Mouse::GroupID::Axis, 1, (int16_t)(rootYReturn - ms.relativeY));
+
+ ms.relativeX = rootXReturn;
+ ms.relativeY = rootYReturn;
+ }
+
+ assign(HID::Mouse::GroupID::Button, 0, (bool)(maskReturn & Button1Mask));
+ assign(HID::Mouse::GroupID::Button, 1, (bool)(maskReturn & Button2Mask));
+ assign(HID::Mouse::GroupID::Button, 2, (bool)(maskReturn & Button3Mask));
+ assign(HID::Mouse::GroupID::Button, 3, (bool)(maskReturn & Button4Mask));
+ assign(HID::Mouse::GroupID::Button, 4, (bool)(maskReturn & Button5Mask));
+
+ devices.append(&hid);
+ }
+
bool poll(int16_t* table) {
Window rootReturn;
Window childReturn;
@@ -115,6 +166,17 @@ struct InputMouseXlib {
ms.relativeX = 0;
ms.relativeY = 0;
+ hid.id = 2;
+
+ hid.axis.append({"X"});
+ hid.axis.append({"Y"});
+
+ hid.button.append({"Left"});
+ hid.button.append({"Middle"});
+ hid.button.append({"Right"});
+ hid.button.append({"Up"});
+ hid.button.append({"Down"});
+
return true;
}
@@ -126,3 +188,5 @@ struct InputMouseXlib {
};
}
+
+#endif
diff --git a/ruby/input/sdl.cpp b/ruby/input/sdl.cpp
index 05fbaa8e..2f52b85a 100644
--- a/ruby/input/sdl.cpp
+++ b/ruby/input/sdl.cpp
@@ -1,37 +1,20 @@
-//================
-//SDL input driver
-//================
-//Keyboard and mouse are controlled directly via Xlib,
-//as SDL cannot capture input from windows it does not create itself.
-//SDL is used only to handle joysticks / gamepads.
-
#include
#include
#include
+#include "keyboard/xlib.cpp"
+#include "mouse/xlib.cpp"
+#include "joypad/sdl.cpp"
+
namespace ruby {
struct pInputSDL {
- #include "xlibkeys.hpp"
+ InputKeyboardXlib xlibKeyboard;
+ InputMouseXlib xlibMouse;
+ InputJoypadSDL sdl;
- struct {
- Display* display;
- Window rootwindow;
- Cursor InvisibleCursor;
- SDL_Joystick* gamepad[Joypad::Count];
-
- unsigned screenwidth, screenheight;
- unsigned relativex, relativey;
- bool mouseacquired;
-
- //mouse device settings
- int accel_numerator;
- int accel_denominator;
- int threshold;
- } device;
-
- struct {
- uintptr_t handle;
+ struct Settings {
+ uintptr_t handle = 0;
} settings;
bool cap(const string& name) {
@@ -57,117 +40,21 @@ struct pInputSDL {
}
bool acquire() {
- if(acquired()) return true;
-
- if(XGrabPointer(device.display, settings.handle, True, 0, GrabModeAsync, GrabModeAsync,
- device.rootwindow, device.InvisibleCursor, CurrentTime) == GrabSuccess) {
- //backup existing cursor acceleration settings
- XGetPointerControl(device.display, &device.accel_numerator, &device.accel_denominator, &device.threshold);
-
- //disable cursor acceleration
- XChangePointerControl(device.display, True, False, 1, 1, 0);
-
- //center cursor (so that first relative poll returns 0, 0 if mouse has not moved)
- XWarpPointer(device.display, None, device.rootwindow, 0, 0, 0, 0, device.screenwidth / 2, device.screenheight / 2);
-
- return device.mouseacquired = true;
- } else {
- return device.mouseacquired = false;
- }
+ return xlibMouse.acquire();
}
bool unacquire() {
- if(acquired()) {
- //restore cursor acceleration and release cursor
- XChangePointerControl(device.display, True, True, device.accel_numerator, device.accel_denominator, device.threshold);
- XUngrabPointer(device.display, CurrentTime);
- device.mouseacquired = false;
- }
- return true;
+ return xlibMouse.unacquire();
}
bool acquired() {
- return device.mouseacquired;
+ return xlibMouse.acquired();
}
bool poll(int16_t* table) {
- memset(table, 0, Scancode::Limit * sizeof(int16_t));
-
- //========
- //Keyboard
- //========
-
- x_poll(device.display, table);
-
- //=====
- //Mouse
- //=====
-
- Window root_return, child_return;
- int root_x_return = 0, root_y_return = 0;
- int win_x_return = 0, win_y_return = 0;
- unsigned int mask_return = 0;
- XQueryPointer(device.display, settings.handle,
- &root_return, &child_return, &root_x_return, &root_y_return,
- &win_x_return, &win_y_return, &mask_return);
-
- if(acquired()) {
- XWindowAttributes attributes;
- XGetWindowAttributes(device.display, settings.handle, &attributes);
-
- //absolute -> relative conversion
- table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.screenwidth / 2);
- table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.screenheight / 2);
-
- if(table[mouse(0).axis(0)] != 0 || table[mouse(0).axis(1)] != 0) {
- //if mouse movement occurred, re-center mouse for next poll
- XWarpPointer(device.display, None, device.rootwindow, 0, 0, 0, 0, device.screenwidth / 2, device.screenheight / 2);
- }
- } else {
- table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.relativex);
- table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.relativey);
-
- device.relativex = root_x_return;
- device.relativey = root_y_return;
- }
-
- //manual device polling is limited to only five buttons ...
- table[mouse(0).button(0)] = (bool)(mask_return & Button1Mask);
- table[mouse(0).button(1)] = (bool)(mask_return & Button2Mask);
- table[mouse(0).button(2)] = (bool)(mask_return & Button3Mask);
- table[mouse(0).button(3)] = (bool)(mask_return & Button4Mask);
- table[mouse(0).button(4)] = (bool)(mask_return & Button5Mask);
-
- //=========
- //Joypad(s)
- //=========
-
- SDL_JoystickUpdate();
- for(unsigned i = 0; i < Joypad::Count; i++) {
- if(!device.gamepad[i]) continue;
-
- //POV hats
- unsigned hats = min((unsigned)Joypad::Hats, SDL_JoystickNumHats(device.gamepad[i]));
- for(unsigned hat = 0; hat < hats; hat++) {
- uint8_t state = SDL_JoystickGetHat(device.gamepad[i], hat);
- if(state & SDL_HAT_UP ) table[joypad(i).hat(hat)] |= Joypad::HatUp;
- if(state & SDL_HAT_RIGHT) table[joypad(i).hat(hat)] |= Joypad::HatRight;
- if(state & SDL_HAT_DOWN ) table[joypad(i).hat(hat)] |= Joypad::HatDown;
- if(state & SDL_HAT_LEFT ) table[joypad(i).hat(hat)] |= Joypad::HatLeft;
- }
-
- //axes
- unsigned axes = min((unsigned)Joypad::Axes, SDL_JoystickNumAxes(device.gamepad[i]));
- for(unsigned axis = 0; axis < axes; axis++) {
- table[joypad(i).axis(axis)] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis);
- }
-
- //buttons
- for(unsigned button = 0; button < Joypad::Buttons; button++) {
- table[joypad(i).button(button)] = (bool)SDL_JoystickGetButton(device.gamepad[i], button);
- }
- }
-
+ xlibKeyboard.poll(table);
+ xlibMouse.poll(table);
+ sdl.poll(table);
return true;
}
@@ -175,56 +62,16 @@ struct pInputSDL {
}
bool init() {
- SDL_InitSubSystem(SDL_INIT_JOYSTICK);
- SDL_JoystickEventState(SDL_IGNORE);
-
- device.display = XOpenDisplay(0);
- device.rootwindow = DefaultRootWindow(device.display);
- XWindowAttributes attributes;
- XGetWindowAttributes(device.display, device.rootwindow, &attributes);
- device.screenwidth = attributes.width;
- device.screenheight = attributes.height;
- x_init(device.display);
-
- //Xlib: "because XShowCursor(false) would be too easy."
- //create a fully transparent cursor named InvisibleCursor,
- //for use while acquire() / XGrabPointer() is active.
- Pixmap pixmap;
- XColor black, unused;
- static char invisible_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- Colormap colormap = DefaultColormap(device.display, DefaultScreen(device.display));
- XAllocNamedColor(device.display, colormap, "black", &black, &unused);
- pixmap = XCreateBitmapFromData(device.display, settings.handle, invisible_data, 8, 8);
- device.InvisibleCursor = XCreatePixmapCursor(device.display, pixmap, pixmap, &black, &black, 0, 0);
- XFreePixmap(device.display, pixmap);
- XFreeColors(device.display, colormap, &black.pixel, 1, 0);
-
- device.mouseacquired = false;
- device.relativex = 0;
- device.relativey = 0;
-
- unsigned joypads = min((unsigned)Joypad::Count, SDL_NumJoysticks());
- for(unsigned i = 0; i < joypads; i++) device.gamepad[i] = SDL_JoystickOpen(i);
-
+ if(xlibKeyboard.init() == false) return false;
+ if(xlibMouse.init(settings.handle) == false) return false;
+ if(sdl.init() == false) return false;
return true;
}
void term() {
- unacquire();
- XFreeCursor(device.display, device.InvisibleCursor);
-
- for(unsigned i = 0; i < Joypad::Count; i++) {
- if(device.gamepad[i]) SDL_JoystickClose(device.gamepad[i]);
- device.gamepad[i] = 0;
- }
-
- SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
- XCloseDisplay(device.display);
- }
-
- pInputSDL() {
- for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
- settings.handle = 0;
+ xlibKeyboard.term();
+ xlibMouse.term();
+ sdl.term();
}
};
diff --git a/ruby/input/udev.cpp b/ruby/input/udev.cpp
index c3fea635..53c10ce6 100644
--- a/ruby/input/udev.cpp
+++ b/ruby/input/udev.cpp
@@ -57,13 +57,22 @@ struct pInputUdev {
return xlibMouse.acquired();
}
+ vector poll() {
+ vector devices;
+ xlibKeyboard.poll(devices);
+ xlibMouse.poll(devices);
+ udev.poll(devices);
+ return devices;
+ }
+
bool poll(int16_t* table) {
xlibKeyboard.poll(table);
xlibMouse.poll(table);
udev.poll(table);
+ return true;
}
- void rumble(unsigned id, bool enable) {
+ void rumble(uint64_t id, bool enable) {
udev.rumble(id, enable);
}
diff --git a/ruby/input/x.cpp b/ruby/input/x.cpp
deleted file mode 100644
index be85e075..00000000
--- a/ruby/input/x.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-
-namespace ruby {
-
-class pInputX {
-public:
- Display *display;
- #include "xlibkeys.hpp"
-
- bool cap(const string& name) {
- if(name == Input::KeyboardSupport) return true;
- return false;
- }
-
- any get(const string& name) {
- return false;
- }
-
- bool set(const string& name, const any &value) {
- return false;
- }
-
- bool acquire() { return false; }
- bool unacquire() { return false; }
- bool acquired() { return false; }
-
- bool poll(int16_t* table) {
- memset(table, 0, Scancode::Limit * sizeof(int16_t));
- x_poll(display, table);
- return true;
- }
-
- void rumble(unsigned id, bool enable) {
- }
-
- bool init() {
- display = XOpenDisplay(0);
- x_init(display);
- return true;
- }
-
- void term() {
- XCloseDisplay(display);
- }
-};
-
-DeclareInput(X)
-
-}
diff --git a/ruby/input/xlib.cpp b/ruby/input/xlib.cpp
new file mode 100644
index 00000000..e7179355
--- /dev/null
+++ b/ruby/input/xlib.cpp
@@ -0,0 +1,75 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "keyboard/xlib.cpp"
+#include "mouse/xlib.cpp"
+
+namespace ruby {
+
+struct pInputXlib {
+ InputKeyboardXlib xlibKeyboard;
+ InputMouseXlib xlibMouse;
+
+ struct Settings {
+ uintptr_t handle = 0;
+ } settings;
+
+ bool cap(const string& name) {
+ if(name == Input::KeyboardSupport) return true;
+ if(name == Input::MouseSupport) return true;
+ return false;
+ }
+
+ any get(const string& name) {
+ if(name == Input::Handle) return (uintptr_t)settings.handle;
+ return false;
+ }
+
+ bool set(const string& name, const any &value) {
+ if(name == Input::Handle) {
+ settings.handle = any_cast(value);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool acquire() {
+ return xlibMouse.acquire();
+ }
+
+ bool unacquire() {
+ return xlibMouse.unacquire();
+ }
+
+ bool acquired() {
+ return xlibMouse.acquired();
+ }
+
+ bool poll(int16_t* table) {
+ xlibKeyboard.poll(table);
+ xlibMouse.poll(table);
+ return true;
+ }
+
+ void rumble(unsigned id, bool enable) {
+ }
+
+ bool init() {
+ if(xlibKeyboard.init() == false) return false;
+ if(xlibMouse.init(settings.handle) == false) return false;
+ return true;
+ }
+
+ void term() {
+ xlibKeyboard.term();
+ xlibMouse.term();
+ }
+};
+
+DeclareInput(Xlib)
+
+}
diff --git a/ruby/input/xlibkeys.hpp b/ruby/input/xlibkeys.hpp
deleted file mode 100644
index c7eff5e3..00000000
--- a/ruby/input/xlibkeys.hpp
+++ /dev/null
@@ -1,263 +0,0 @@
-uint8_t scancode[256];
-
-enum XScancode {
- Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
- ScrollLock, Pause, Tilde,
- Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
- Dash, Equal, Backspace,
- Insert, Delete, Home, End, PageUp, PageDown,
- A, B, C, D, E, F, G, H, I, J, K, L, M,
- N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
- LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
- Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
- Point, Enter, Add, Subtract, Multiply, Divide,
- Up, Down, Left, Right,
- Tab, Return, Spacebar, Menu,
- LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, LeftSuper, RightSuper,
-};
-
-void x_poll(Display* display, int16_t* table) {
- if(!display) return;
-
- char state[32];
- XQueryKeymap(display, state);
-
- #define key(id) table[keyboard(0)[id]]
- #define pressed(id) (bool)(state[scancode[id] >> 3] & (1 << (scancode[id] & 7)))
-
- key(Keyboard::Escape) = pressed(Escape);
-
- key(Keyboard::F1) = pressed(F1);
- key(Keyboard::F2) = pressed(F2);
- key(Keyboard::F3) = pressed(F3);
- key(Keyboard::F4) = pressed(F4);
- key(Keyboard::F5) = pressed(F5);
- key(Keyboard::F6) = pressed(F6);
- key(Keyboard::F7) = pressed(F7);
- key(Keyboard::F8) = pressed(F8);
- key(Keyboard::F9) = pressed(F9);
- key(Keyboard::F10) = pressed(F10);
- key(Keyboard::F11) = pressed(F11);
- key(Keyboard::F12) = pressed(F12);
-
- key(Keyboard::ScrollLock) = pressed(ScrollLock);
- key(Keyboard::Pause) = pressed(Pause);
- key(Keyboard::Tilde) = pressed(Tilde);
-
- key(Keyboard::Num1) = pressed(Num1);
- key(Keyboard::Num2) = pressed(Num2);
- key(Keyboard::Num3) = pressed(Num3);
- key(Keyboard::Num4) = pressed(Num4);
- key(Keyboard::Num5) = pressed(Num5);
- key(Keyboard::Num6) = pressed(Num6);
- key(Keyboard::Num7) = pressed(Num7);
- key(Keyboard::Num8) = pressed(Num8);
- key(Keyboard::Num9) = pressed(Num9);
- key(Keyboard::Num0) = pressed(Num0);
-
- key(Keyboard::Dash) = pressed(Dash);
- key(Keyboard::Equal) = pressed(Equal);
- key(Keyboard::Backspace) = pressed(Backspace);
-
- key(Keyboard::Insert) = pressed(Insert);
- key(Keyboard::Delete) = pressed(Delete);
- key(Keyboard::Home) = pressed(Home);
- key(Keyboard::End) = pressed(End);
- key(Keyboard::PageUp) = pressed(PageUp);
- key(Keyboard::PageDown) = pressed(PageDown);
-
- key(Keyboard::A) = pressed(A);
- key(Keyboard::B) = pressed(B);
- key(Keyboard::C) = pressed(C);
- key(Keyboard::D) = pressed(D);
- key(Keyboard::E) = pressed(E);
- key(Keyboard::F) = pressed(F);
- key(Keyboard::G) = pressed(G);
- key(Keyboard::H) = pressed(H);
- key(Keyboard::I) = pressed(I);
- key(Keyboard::J) = pressed(J);
- key(Keyboard::K) = pressed(K);
- key(Keyboard::L) = pressed(L);
- key(Keyboard::M) = pressed(M);
- key(Keyboard::N) = pressed(N);
- key(Keyboard::O) = pressed(O);
- key(Keyboard::P) = pressed(P);
- key(Keyboard::Q) = pressed(Q);
- key(Keyboard::R) = pressed(R);
- key(Keyboard::S) = pressed(S);
- key(Keyboard::T) = pressed(T);
- key(Keyboard::U) = pressed(U);
- key(Keyboard::V) = pressed(V);
- key(Keyboard::W) = pressed(W);
- key(Keyboard::X) = pressed(X);
- key(Keyboard::Y) = pressed(Y);
- key(Keyboard::Z) = pressed(Z);
-
- key(Keyboard::LeftBracket) = pressed(LeftBracket);
- key(Keyboard::RightBracket) = pressed(RightBracket);
- key(Keyboard::Backslash) = pressed(Backslash);
- key(Keyboard::Semicolon) = pressed(Semicolon);
- key(Keyboard::Apostrophe) = pressed(Apostrophe);
- key(Keyboard::Comma) = pressed(Comma);
- key(Keyboard::Period) = pressed(Period);
- key(Keyboard::Slash) = pressed(Slash);
-
- key(Keyboard::Keypad1) = pressed(Keypad1);
- key(Keyboard::Keypad2) = pressed(Keypad2);
- key(Keyboard::Keypad3) = pressed(Keypad3);
- key(Keyboard::Keypad4) = pressed(Keypad4);
- key(Keyboard::Keypad5) = pressed(Keypad5);
- key(Keyboard::Keypad6) = pressed(Keypad6);
- key(Keyboard::Keypad7) = pressed(Keypad7);
- key(Keyboard::Keypad8) = pressed(Keypad8);
- key(Keyboard::Keypad9) = pressed(Keypad9);
- key(Keyboard::Keypad0) = pressed(Keypad0);
-
- key(Keyboard::Point) = pressed(Point);
- key(Keyboard::Enter) = pressed(Enter);
- key(Keyboard::Add) = pressed(Add);
- key(Keyboard::Subtract) = pressed(Subtract);
- key(Keyboard::Multiply) = pressed(Multiply);
- key(Keyboard::Divide) = pressed(Divide);
-
- key(Keyboard::Up) = pressed(Up);
- key(Keyboard::Down) = pressed(Down);
- key(Keyboard::Left) = pressed(Left);
- key(Keyboard::Right) = pressed(Right);
-
- key(Keyboard::Tab) = pressed(Tab);
- key(Keyboard::Return) = pressed(Return);
- key(Keyboard::Spacebar) = pressed(Spacebar);
- key(Keyboard::Menu) = pressed(Menu);
-
- key(Keyboard::Shift) = pressed(LeftShift) || pressed(RightShift);
- key(Keyboard::Control) = pressed(LeftControl) || pressed(RightControl);
- key(Keyboard::Alt) = pressed(LeftAlt) || pressed(RightAlt);
- key(Keyboard::Super) = pressed(LeftSuper) || pressed(RightSuper);
-
- #undef key
- #undef pressed
-}
-
-void x_init(Display* display) {
- if(!display) return;
-
- memset(&scancode, 0, sizeof scancode);
-
- #define assign(x, y) scancode[x] = XKeysymToKeycode(display, y)
- assign(Escape, XK_Escape);
-
- assign(F1, XK_F1);
- assign(F2, XK_F2);
- assign(F3, XK_F3);
- assign(F4, XK_F4);
- assign(F5, XK_F5);
- assign(F6, XK_F6);
- assign(F7, XK_F7);
- assign(F8, XK_F8);
- assign(F9, XK_F9);
- assign(F10, XK_F10);
- assign(F11, XK_F11);
- assign(F12, XK_F12);
-
- assign(ScrollLock, XK_Scroll_Lock);
- assign(Pause, XK_Pause);
-
- assign(Tilde, XK_asciitilde);
-
- assign(Num0, XK_0);
- assign(Num1, XK_1);
- assign(Num2, XK_2);
- assign(Num3, XK_3);
- assign(Num4, XK_4);
- assign(Num5, XK_5);
- assign(Num6, XK_6);
- assign(Num7, XK_7);
- assign(Num8, XK_8);
- assign(Num9, XK_9);
-
- assign(Dash, XK_minus);
- assign(Equal, XK_equal);
- assign(Backspace, XK_BackSpace);
-
- assign(Insert, XK_Insert);
- assign(Delete, XK_Delete);
- assign(Home, XK_Home);
- assign(End, XK_End);
- assign(PageUp, XK_Prior);
- assign(PageDown, XK_Next);
-
- assign(A, XK_A);
- assign(B, XK_B);
- assign(C, XK_C);
- assign(D, XK_D);
- assign(E, XK_E);
- assign(F, XK_F);
- assign(G, XK_G);
- assign(H, XK_H);
- assign(I, XK_I);
- assign(J, XK_J);
- assign(K, XK_K);
- assign(L, XK_L);
- assign(M, XK_M);
- assign(N, XK_N);
- assign(O, XK_O);
- assign(P, XK_P);
- assign(Q, XK_Q);
- assign(R, XK_R);
- assign(S, XK_S);
- assign(T, XK_T);
- assign(U, XK_U);
- assign(V, XK_V);
- assign(W, XK_W);
- assign(X, XK_X);
- assign(Y, XK_Y);
- assign(Z, XK_Z);
-
- assign(LeftBracket, XK_bracketleft);
- assign(RightBracket, XK_bracketright);
- assign(Backslash, XK_backslash);
- assign(Semicolon, XK_semicolon);
- assign(Apostrophe, XK_apostrophe);
- assign(Comma, XK_comma);
- assign(Period, XK_period);
- assign(Slash, XK_slash);
-
- assign(Keypad0, XK_KP_0);
- assign(Keypad1, XK_KP_1);
- assign(Keypad2, XK_KP_2);
- assign(Keypad3, XK_KP_3);
- assign(Keypad4, XK_KP_4);
- assign(Keypad5, XK_KP_5);
- assign(Keypad6, XK_KP_6);
- assign(Keypad7, XK_KP_7);
- assign(Keypad8, XK_KP_8);
- assign(Keypad9, XK_KP_9);
-
- assign(Add, XK_KP_Add);
- assign(Subtract, XK_KP_Subtract);
- assign(Multiply, XK_KP_Multiply);
- assign(Divide, XK_KP_Divide);
- assign(Enter, XK_KP_Enter);
-
- assign(Up, XK_Up);
- assign(Down, XK_Down);
- assign(Left, XK_Left);
- assign(Right, XK_Right);
-
- assign(Tab, XK_Tab);
- assign(Return, XK_Return);
- assign(Spacebar, XK_space);
-
- assign(LeftControl, XK_Control_L);
- assign(RightControl, XK_Control_R);
- assign(LeftAlt, XK_Alt_L);
- assign(RightAlt, XK_Alt_R);
- assign(LeftShift, XK_Shift_L);
- assign(RightShift, XK_Shift_R);
- assign(LeftSuper, XK_Super_L);
- assign(RightSuper, XK_Super_R);
- assign(Menu, XK_Menu);
-
- #undef assign
-}
diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp
index b6f34657..567a894f 100644
--- a/ruby/ruby.cpp
+++ b/ruby/ruby.cpp
@@ -395,8 +395,8 @@ void InputInterface::driver(const char* driver) {
else if(!strcmp(driver, "SDL")) p = new InputSDL();
#endif
- #ifdef INPUT_X
- else if(!strcmp(driver, "X-Windows")) p = new InputX();
+ #ifdef INPUT_XLIB
+ else if(!strcmp(driver, "Xlib")) p = new InputXlib();
#endif
else p = new Input();
@@ -415,8 +415,8 @@ const char* InputInterface::optimalDriver() {
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
- #elif defined(INPUT_X)
- return "X-Windows";
+ #elif defined(INPUT_XLIB)
+ return "Xlib";
#else
return "None";
@@ -436,8 +436,8 @@ const char* InputInterface::safestDriver() {
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
- #elif defined(INPUT_X)
- return "X-Windows";
+ #elif defined(INPUT_XLIB)
+ return "Xlib";
#else
return "none";
@@ -473,8 +473,8 @@ const char* InputInterface::availableDrivers() {
"SDL;"
#endif
- #if defined(INPUT_X)
- "X-Windows;"
+ #if defined(INPUT_XLIB)
+ "Xlib;"
#endif
"None";
@@ -499,8 +499,9 @@ bool InputInterface::set(const string& name, const any& value) { return p ? p->s
bool InputInterface::acquire() { return p ? p->acquire() : false; }
bool InputInterface::unacquire() { return p ? p->unacquire() : false; }
bool InputInterface::acquired() { return p ? p->acquired() : false; }
+vector InputInterface::poll() { return p ? p->poll() : vector(); }
bool InputInterface::poll(int16_t* table) { return p ? p->poll(table) : false; }
-void InputInterface::rumble(unsigned id, bool enable) { if(p) return p->rumble(id, enable); }
+void InputInterface::rumble(uint64_t id, bool enable) { if(p) return p->rumble(id, enable); }
InputInterface::InputInterface() : p(nullptr) {}
InputInterface::~InputInterface() { term(); }
diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp
index 8bcc495e..7ade4fe6 100644
--- a/ruby/ruby.hpp
+++ b/ruby/ruby.hpp
@@ -63,6 +63,8 @@ private:
};
struct InputInterface {
+ nall::function onChange;
+
void driver(const char* driver = "");
const char* optimalDriver();
const char* safestDriver();
@@ -78,8 +80,9 @@ struct InputInterface {
bool unacquire();
bool acquired();
+ nall::vector poll();
bool poll(int16_t* table);
- void rumble(unsigned id, bool enable);
+ void rumble(uint64_t id, bool enable);
InputInterface();
~InputInterface();
diff --git a/target-ethos/Makefile b/target-ethos/Makefile
index 2624ab06..2799c30b 100644
--- a/target-ethos/Makefile
+++ b/target-ethos/Makefile
@@ -25,7 +25,7 @@ else ifeq ($(platform),macosx)
else ifeq ($(platform),linux)
ruby := video.glx video.xv video.xshm video.sdl
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
- ruby += input.udev input.sdl input.x
+ ruby += input.udev
else ifeq ($(platform),bsd)
ruby := video.glx
ruby += audio.openal audio.oss
diff --git a/target-ethos/input/hotkeys.cpp b/target-ethos/input/hotkeys.cpp
index 34128416..d1c61623 100644
--- a/target-ethos/input/hotkeys.cpp
+++ b/target-ethos/input/hotkeys.cpp
@@ -2,7 +2,7 @@ void InputManager::appendHotkeys() {
{
auto hotkey = new HotkeyInput;
hotkey->name = "Toggle Fullscreen Mode";
- hotkey->mapping = "KB0::F11";
+ hotkey->mapping = "1/Button/F11";
hotkey->press = [] {
utility->toggleFullScreen();
diff --git a/target-ethos/input/input.cpp b/target-ethos/input/input.cpp
index d7b22838..bd733cf0 100644
--- a/target-ethos/input/input.cpp
+++ b/target-ethos/input/input.cpp
@@ -1,82 +1,82 @@
#include "../ethos.hpp"
#include "hotkeys.cpp"
InputManager* inputManager = nullptr;
+HID::Null hidNull;
void AbstractInput::bind() {
inputList.reset();
lstring list = mapping.split(",");
for(auto& mapping : list) {
- Input::Type type;
- if(mapping.endsWith(".Up")) type = Input::Type::HatUp;
- else if(mapping.endsWith(".Down")) type = Input::Type::HatDown;
- else if(mapping.endsWith(".Left")) type = Input::Type::HatLeft;
- else if(mapping.endsWith(".Right")) type = Input::Type::HatRight;
- else if(mapping.endsWith(".Lo")) type = Input::Type::AxisLo;
- else if(mapping.endsWith(".Hi")) type = Input::Type::AxisHi;
- else if(mapping.beginsWith("JP") && mapping.find("Axis")) type = Input::Type::Axis;
- else if(mapping.beginsWith("JP") && mapping.endsWith("Rumble")) type = Input::Type::Rumble;
- else if(mapping.beginsWith("MS") && mapping.endsWith("axis")) type = Input::Type::MouseAxis;
- else if(mapping.beginsWith("MS")) type = Input::Type::MouseButton;
- else type = Input::Type::Button;
+ lstring values = mapping.split("/");
+ if(values.size() == 1) continue; //skip "None" mapping
- if(type == Input::Type::Rumble) {
- unsigned joypad = mapping[2] - '0';
- inputList.append({type, joypad});
- } else {
- string decode = mapping;
- if(auto position = decode.find(".")) decode.resize(position());
- unsigned scancode = Scancode::decode(decode);
- inputList.append({type, scancode});
+ uint64_t id = hex(values[0]);
+ string group = values(1, "");
+ string input = values(2, "");
+ string qualifier = values(3, "");
+
+ Input item;
+ for(auto device : inputManager->devices) {
+ if(id != device->id) continue;
+ if(group == "Rumble") {
+ item.device = device;
+ item.id = id;
+ item.group = 0;
+ item.input = 0;
+ break;
+ }
+ if(auto groupID = device->find(group)) {
+ if(auto inputID = device->group[groupID()].find(input)) {
+ item.device = device;
+ item.id = id;
+ item.group = groupID();
+ item.input = inputID();
+ item.qualifier = Input::Qualifier::None;
+ if(qualifier == "Lo") item.qualifier = Input::Qualifier::Lo;
+ if(qualifier == "Hi") item.qualifier = Input::Qualifier::Hi;
+ break;
+ }
+ }
}
+ if(item.device == nullptr) continue;
+
+ inputList.append(item);
}
}
bool AbstractInput::append(string encode) {
- if(mapping.find(encode)) return true; //mapping already bound
+ lstring mappings = mapping.split(",");
+ if(mappings.find(encode)) return true; //mapping already bound
if(mapping.empty() || mapping == "None") mapping = encode; //remove "None"
else mapping.append(",", encode); //add to existing mapping list
bind();
return true;
}
-AbstractInput::AbstractInput() : state(false) {
-}
-
//
-bool DigitalInput::bind(unsigned scancode, int16_t value) {
- using nall::Keyboard;
- using nall::Mouse;
-
- if(scancode == Scancode::None || scancode == keyboard(0)[Keyboard::Escape]) {
+bool DigitalInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) {
+ if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) {
inputList.reset();
mapping = "None";
return true;
}
- string encode = Scancode::encode(scancode);
+ string encode = {hex(device.id), "/", device.group[group].name, "/", device.group[group].input[input].name};
- if(Keyboard::isAnyKey(scancode) || Keyboard::isAnyModifier(scancode) || Joypad::isAnyButton(scancode)) {
- if(value == 0) return false;
- return append(encode);
+ if((device.isKeyboard() && group == HID::Keyboard::GroupID::Button)
+ || (device.isMouse() && group == HID::Mouse::GroupID::Button)
+ || (device.isJoypad() && group == HID::Joypad::GroupID::Button)
+ ) {
+ if(newValue != 0) return append(encode);
}
- if(Mouse::isAnyButton(scancode)) {
- if(value == 0) return false;
- return append(encode);
- }
-
- if(Joypad::isAnyHat(scancode)) {
- if(value & Joypad::HatUp ) { encode.append(".Up" ); return append(encode); }
- if(value & Joypad::HatDown ) { encode.append(".Down" ); return append(encode); }
- if(value & Joypad::HatLeft ) { encode.append(".Left" ); return append(encode); }
- if(value & Joypad::HatRight) { encode.append(".Right"); return append(encode); }
- }
-
- if(Joypad::isAnyAxis(scancode)) {
- if(value < -12288) { encode.append(".Lo"); return append(encode); }
- if(value > +24576) { encode.append(".Hi"); return append(encode); }
+ if((device.isJoypad() && group == HID::Joypad::GroupID::Axis)
+ || (device.isJoypad() && group == HID::Joypad::GroupID::Hat)
+ ) {
+ if(newValue < -16384) return append({encode, "/Lo"});
+ if(newValue > +16384) return append({encode, "/Hi"});
}
return false;
@@ -84,20 +84,24 @@ bool DigitalInput::bind(unsigned scancode, int16_t value) {
int16_t DigitalInput::poll() {
if(program->focused() == false) return 0;
+ if(inputList.size() == 0) return 0;
bool result = logic;
for(auto& item : inputList) {
- int16_t value = inputManager->poll(item.scancode);
+ HID::Device& device = *(item.device);
+ int16_t value = device.group[item.group].input[item.input].value;
bool output = logic;
- switch(item.type) {
- case Input::Type::Button: output = value; break;
- case Input::Type::MouseButton: output = value & input.acquired(); break;
- case Input::Type::HatUp: output = value & Joypad::HatUp; break;
- case Input::Type::HatDown: output = value & Joypad::HatDown; break;
- case Input::Type::HatLeft: output = value & Joypad::HatLeft; break;
- case Input::Type::HatRight: output = value & Joypad::HatRight; break;
- case Input::Type::AxisLo: output = value < -16384; break;
- case Input::Type::AxisHi: output = value > +16384; break;
+ if((device.isKeyboard() && item.group == HID::Keyboard::GroupID::Button)
+ || (device.isMouse() && item.group == HID::Mouse::GroupID::Button)
+ || (device.isJoypad() && item.group == HID::Joypad::GroupID::Button)
+ ) {
+ output = value;
+ }
+ if((device.isJoypad() && item.group == HID::Joypad::GroupID::Axis)
+ || (device.isJoypad() && item.group == HID::Joypad::GroupID::Hat)
+ ) {
+ if(item.qualifier == Input::Qualifier::Lo) output = value < -16384;
+ if(item.qualifier == Input::Qualifier::Hi) output = value > +16384;
}
if(logic == 0) result |= output;
if(logic == 1) result &= output;
@@ -108,34 +112,37 @@ int16_t DigitalInput::poll() {
//
-bool RelativeInput::bind(unsigned scancode, int16_t value) {
- using nall::Keyboard;
- using nall::Mouse;
-
- if(scancode == Scancode::None || scancode == keyboard(0)[Keyboard::Escape]) {
+bool RelativeInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) {
+ if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) {
inputList.reset();
mapping = "None";
return true;
}
- string encode = Scancode::encode(scancode);
+ string encode = {hex(device.id), "/", device.group[group].name, "/", device.group[group].input[input].name};
- if(Mouse::isAnyAxis(scancode)) return append(encode);
- if(Joypad::isAnyAxis(scancode)) return append(encode);
+ if((device.isMouse() && group == HID::Mouse::GroupID::Axis)
+ || (device.isJoypad() && group == HID::Joypad::GroupID::Axis)
+ || (device.isJoypad() && group == HID::Joypad::GroupID::Hat)
+ ) {
+ if(newValue < -16384) return append(encode);
+ if(newValue > +16384) return append(encode);
+ }
return false;
}
int16_t RelativeInput::poll() {
if(program->focused() == false) return 0;
+ if(inputList.size() == 0) return 0;
int16_t result = 0;
for(auto& item : inputList) {
- int16_t value = inputManager->poll(item.scancode);
- switch(item.type) {
- case Input::Type::MouseAxis: value = input.acquired() ? value : 0; break;
- case Input::Type::Axis: value = value; break;
- }
+ HID::Device& device = *(item.device);
+ int16_t value = device.group[item.group].input[item.input].value;
+ if(device.isJoypad() && item.group == HID::Joypad::GroupID::Axis) value >>= 8;
+ if(device.isJoypad() && item.group == HID::Joypad::GroupID::Hat) value = (value < 0 ? -1 : value > 0 ? + 1 : 0);
+ if(device.isMouse() && input.acquired() == false) value = 0;
result += value;
}
@@ -144,105 +151,28 @@ int16_t RelativeInput::poll() {
//
-bool AbsoluteInput::bind(unsigned scancode, int16_t value) {
- using nall::Keyboard;
- using nall::Mouse;
-
- if(scancode == Scancode::None || scancode == keyboard(0)[Keyboard::Escape]) {
+bool RumbleInput::bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) {
+ if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) {
inputList.reset();
mapping = "None";
return true;
}
- string encode = Scancode::encode(scancode);
+ string encode = {hex(device.id), "/Rumble"};
- if(Mouse::isAnyAxis(scancode)) {
- //only one input can be assigned for absolute positioning
- inputList.reset();
- mapping = encode;
- return true;
+ if(device.isJoypad() && group == HID::Joypad::GroupID::Button) {
+ if(newValue != 0) return append(encode);
}
return false;
}
-int16_t AbsoluteInput::poll() {
- if(program->focused() == false) return -32768;
- int16_t result = -32768; //offscreen value
-
- using nall::Mouse;
-
- Position position = phoenix::Mouse::position();
- Geometry geometry = presentation->geometry();
-
- if(position.x < geometry.x
- || position.y < geometry.y
- || position.x >= geometry.x + geometry.width
- || position.y >= geometry.y + geometry.height) {
- //cursor is offscreen
- position.x = -32768;
- position.y = -32768;
- } else {
- //convert from screen to viewport coordinates
- double x = position.x - geometry.x;
- double y = position.y - geometry.y;
-
- //scale coordinate range to -0.5 to +0.5 (0.0 = center)
- x = x * 1.0 / geometry.width - 0.5;
- y = y * 1.0 / geometry.height - 0.5;
-
- //scale coordinates to -32767 to +32767
- signed px = (signed)(x * 65535.0);
- signed py = (signed)(y * 65535.0);
-
- //clamp to valid range
- position.x = max(-32767, min(+32767, px));
- position.y = max(-32767, min(+32767, py));
- }
-
- for(auto& item : inputList) {
- if(item.scancode == mouse(0)[Mouse::Xaxis]) {
- result = position.x;
- }
-
- if(item.scancode == mouse(0)[Mouse::Yaxis]) {
- result = position.y;
- }
- }
-
- return result;
-}
-
-bool RumbleInput::bind(unsigned scancode, int16_t value) {
- using nall::Keyboard;
-
- if(scancode == Scancode::None || scancode == keyboard(0)[Keyboard::Escape]) {
- inputList.reset();
- mapping = "None";
- return true;
- }
-
- string encode = Scancode::encode(scancode);
-
- if(Joypad::isAnyButton(scancode)) {
- if(value == 0) return false;
- if(auto position = encode.find("::")) encode.resize(position());
- encode.append("::Rumble");
- return append(encode);
- }
-
- return false;
-}
-
-int16_t RumbleInput::poll() {
- return false;
-}
-
void RumbleInput::rumble(bool enable) {
if(program->focused() == false) return;
+ if(inputList.size() == 0) return;
for(auto& item : inputList) {
- input.rumble(item.scancode, enable);
+ input.rumble(item.id, enable);
}
}
@@ -255,48 +185,51 @@ HotkeyInput::HotkeyInput() {
//
+void InputManager::onChange(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) {
+ if(settings->focused()) {
+ inputSettings->inputEvent(device, group, input, oldValue, newValue);
+ hotkeySettings->inputEvent(device, group, input, oldValue, newValue);
+ }
+}
+
+HID::Device* InputManager::findMouse() {
+ for(auto device : devices) {
+ if(device->isMouse()) return device;
+ }
+ return nullptr;
+}
+
void InputManager::bind() {
for(auto& input : inputMap) input->bind();
for(auto& input : hotkeyMap) input->bind();
}
void InputManager::poll() {
- using nall::Keyboard;
-
- activeScancode = !activeScancode;
- if(input.poll(scancode[activeScancode]) == false) return;
-
- for(unsigned n = 0; n < Scancode::Limit; n++) {
- if(scancode[0][n] != scancode[1][n]) {
- if(settings->focused()) {
- inputSettings->inputEvent(n, scancode[activeScancode][n]);
- hotkeySettings->inputEvent(n, scancode[activeScancode][n]);
- }
+ auto devices = input.poll();
+ bool changed = devices.size() != this->devices.size();
+ if(changed == false) {
+ for(unsigned n = 0; n < devices.size(); n++) {
+ changed = devices[n] != this->devices[n];
+ if(changed) break;
}
}
+ if(changed == true) {
+ this->devices = devices;
+ bind();
+ }
if(presentation->focused()) pollHotkeys();
}
-int16_t InputManager::poll(unsigned scancode) {
- return this->scancode[activeScancode][scancode];
-}
-
void InputManager::saveConfiguration() {
config.save(program->path("input.bml"));
}
InputManager::InputManager() {
inputManager = this;
- scancode[0] = new int16_t[Scancode::Limit]();
- scancode[1] = new int16_t[Scancode::Limit]();
- activeScancode = 0;
bootstrap();
-}
-InputManager::~InputManager() {
- delete[] scancode[0];
- delete[] scancode[1];
+ input.onChange = {&InputManager::onChange, this};
}
void InputManager::bootstrap() {
@@ -316,8 +249,7 @@ void InputManager::bootstrap() {
AbstractInput* abstract = nullptr;
if(input.type == 0) abstract = new DigitalInput;
if(input.type == 1) abstract = new RelativeInput;
- if(input.type == 2) abstract = new AbsoluteInput;
- if(input.type == 3) abstract = new RumbleInput;
+ if(input.type == 2) abstract = new RumbleInput;
if(abstract == nullptr) continue;
abstract->name = string{input.name}.replace(" ", "");
diff --git a/target-ethos/input/input.hpp b/target-ethos/input/input.hpp
index 2d11f03c..0cbf9205 100644
--- a/target-ethos/input/input.hpp
+++ b/target-ethos/input/input.hpp
@@ -1,45 +1,42 @@
+extern HID::Null hidNull;
+
struct AbstractInput {
string name;
string mapping;
- bool logic; //0 = OR, 1 = AND
- bool state;
+ bool logic = 0; //0 = OR, 1 = AND
+ bool state = 0;
struct Input {
- enum class Type : unsigned { Button, MouseButton, MouseAxis, HatUp, HatDown, HatLeft, HatRight, Axis, AxisLo, AxisHi, Rumble } type;
- unsigned scancode;
+ HID::Device* device = nullptr;
+ uint64_t id = 0;
+ unsigned group = 0;
+ unsigned input = 0;
+ enum class Qualifier : unsigned { None, Lo, Hi } qualifier;
};
vector inputList;
void bind();
bool append(string mapping);
- virtual bool bind(unsigned scancode, int16_t value) = 0;
- virtual int16_t poll() = 0;
+ virtual bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) { return false; }
+ virtual int16_t poll() { return 0; }
virtual void rumble(bool enable) {}
- AbstractInput();
};
struct DigitalInput : AbstractInput {
using AbstractInput::bind;
- bool bind(unsigned scancode, int16_t value);
+ bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue);
int16_t poll();
};
struct RelativeInput : AbstractInput {
using AbstractInput::bind;
- bool bind(unsigned scancode, int16_t value);
- int16_t poll();
-};
-
-struct AbsoluteInput : AbstractInput {
- using AbstractInput::bind;
- bool bind(unsigned scancode, int16_t value);
+ bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue);
int16_t poll();
};
struct RumbleInput : AbstractInput {
using AbstractInput::bind;
- bool bind(unsigned scancode, int16_t value);
- int16_t poll();
+ bool bind(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue);
void rumble(bool enable);
};
@@ -50,18 +47,17 @@ struct HotkeyInput : DigitalInput {
};
struct InputManager {
+ vector devices;
vector inputMap;
vector hotkeyMap;
- int16_t* scancode[2];
- bool activeScancode;
+ void onChange(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue);
+ HID::Device* findMouse();
void bind();
void poll();
- int16_t poll(unsigned scancode);
void saveConfiguration();
void bootstrap();
InputManager();
- ~InputManager();
//hotkeys.cpp
void appendHotkeys();
diff --git a/target-ethos/settings/hotkey.cpp b/target-ethos/settings/hotkey.cpp
index 44c32979..4395d1ed 100644
--- a/target-ethos/settings/hotkey.cpp
+++ b/target-ethos/settings/hotkey.cpp
@@ -26,8 +26,6 @@ void HotkeySettings::refresh() {
unsigned index = 0;
for(auto& hotkey : inputManager->hotkeyMap) {
string mapping = hotkey->mapping;
- mapping.replace("KB0::", "");
- mapping.replace("MS0::", "Mouse::");
mapping.replace(",", " and ");
inputList.setText(index++, {hotkey->name, mapping});
}
@@ -36,7 +34,7 @@ void HotkeySettings::refresh() {
void HotkeySettings::eraseInput() {
activeInput = inputManager->hotkeyMap[inputList.selection()];
- inputEvent(Scancode::None, 1);
+ inputEvent(hidNull, 0, 0, 0, 1);
}
void HotkeySettings::assignInput() {
@@ -47,14 +45,11 @@ void HotkeySettings::assignInput() {
setEnabled(false);
}
-void HotkeySettings::inputEvent(unsigned scancode, int16_t value) {
- using nall::Mouse;
-
+void HotkeySettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) {
if(activeInput == nullptr) return;
- if(value != 1) return;
- if(Mouse::isAnyButton(scancode) || Mouse::isAnyAxis(scancode)) return;
- if(Joypad::isAnyAxis(scancode)) return;
- if(activeInput->bind(scancode, value) == false) return;
+ if(device.isMouse()) return;
+ if(device.isJoypad() && group == HID::Joypad::GroupID::Axis) return;
+ if(activeInput->bind(device, group, input, oldValue, newValue) == false) return;
activeInput = nullptr;
settings->setStatusText("");
diff --git a/target-ethos/settings/hotkey.hpp b/target-ethos/settings/hotkey.hpp
index ac187537..c254df73 100644
--- a/target-ethos/settings/hotkey.hpp
+++ b/target-ethos/settings/hotkey.hpp
@@ -8,7 +8,7 @@ struct HotkeySettings : SettingsLayout {
void refresh();
void eraseInput();
void assignInput();
- void inputEvent(unsigned scancode, int16_t value);
+ void inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue);
HotkeySettings();
private:
diff --git a/target-ethos/settings/input.cpp b/target-ethos/settings/input.cpp
index 3aa0a6a3..a5d5ca13 100644
--- a/target-ethos/settings/input.cpp
+++ b/target-ethos/settings/input.cpp
@@ -69,8 +69,7 @@ void InputSettings::synchronize() {
assign[2].setVisible(true);
}
- if(dynamic_cast(selectedInput)
- || dynamic_cast(selectedInput)) {
+ if(dynamic_cast(selectedInput)) {
assign[0].setText("Mouse X-axis");
assign[1].setText("Mouse Y-axis");
assign[0].setVisible(true);
@@ -123,8 +122,6 @@ void InputSettings::inputChanged() {
auto& input = activeDevice().input[number];
auto abstract = inputManager->inputMap(input.guid);
string mapping = abstract->mapping;
- mapping.replace("KB0::", "");
- mapping.replace("MS0::", "Mouse::");
mapping.replace(",", " or ");
inputList.setText(index++, {input.name, mapping});
}
@@ -138,7 +135,7 @@ void InputSettings::resetInput() {
unsigned length = device.input.size();
for(unsigned n = 0; n < length; n++) {
activeInput = inputManager->inputMap[device.input[n].guid];
- inputEvent(Scancode::None, 1);
+ inputEvent(hidNull, 0, 0, 0, 1);
}
}
@@ -146,7 +143,7 @@ void InputSettings::eraseInput() {
unsigned number = activeDevice().order[inputList.selection()];
auto& input = activeDevice().input[number];
activeInput = inputManager->inputMap[input.guid];
- inputEvent(Scancode::None, 1);
+ inputEvent(hidNull, 0, 0, 0, 1);
}
void InputSettings::assignInput() {
@@ -165,20 +162,22 @@ void InputSettings::assignMouseInput(unsigned n) {
activeInput = inputManager->inputMap[input.guid];
if(dynamic_cast(activeInput)) {
- return inputEvent(mouse(0).button(n), 1, true);
+ if(auto hidMouse = inputManager->findMouse()) {
+ return inputEvent(*hidMouse, HID::Mouse::GroupID::Button, n, 0, 1, true);
+ }
}
- if(dynamic_cast(activeInput)
- || dynamic_cast(activeInput)) {
- return inputEvent(mouse(0).axis(n), 1, true);
+ if(dynamic_cast(activeInput)) {
+ if(auto hidMouse = inputManager->findMouse()) {
+ return inputEvent(*hidMouse, HID::Mouse::GroupID::Axis, n, 0, +32767, true);
+ }
}
}
-void InputSettings::inputEvent(unsigned scancode, int16_t value, bool allowMouseInput) {
- using nall::Mouse;
+void InputSettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue, bool allowMouseInput) {
if(activeInput == nullptr) return;
- if(allowMouseInput == false && (Mouse::isAnyButton(scancode) || Mouse::isAnyAxis(scancode))) return;
- if(activeInput->bind(scancode, value) == false) return;
+ if(allowMouseInput == false && device.isMouse()) return;
+ if(activeInput->bind(device, group, input, oldValue, newValue) == false) return;
activeInput = nullptr;
inputChanged();
diff --git a/target-ethos/settings/input.hpp b/target-ethos/settings/input.hpp
index 39ab4348..20a505f3 100644
--- a/target-ethos/settings/input.hpp
+++ b/target-ethos/settings/input.hpp
@@ -28,7 +28,7 @@ struct InputSettings : SettingsLayout {
void eraseInput();
void assignInput();
void assignMouseInput(unsigned n);
- void inputEvent(unsigned scancode, int16_t value, bool allowMouseInput = false);
+ void inputEvent(HID::Device& device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue, bool allowMouseInput = false);
InputSettings();
private: