mirror of https://github.com/PCSX2/pcsx2.git
PAD: Process keycodes the same way on Linux and macOS
This commit is contained in:
parent
532a7addd4
commit
b90de6d89f
|
@ -1262,6 +1262,7 @@ if(NOT PCSX2_CORE)
|
||||||
)
|
)
|
||||||
list(APPEND pcsx2OSXSources
|
list(APPEND pcsx2OSXSources
|
||||||
Linux/LnxConsolePipe.cpp
|
Linux/LnxConsolePipe.cpp
|
||||||
|
Darwin/DarwinKeyCodes.cpp
|
||||||
)
|
)
|
||||||
list(APPEND pcsx2FreeBSDSources
|
list(APPEND pcsx2FreeBSDSources
|
||||||
Linux/LnxConsolePipe.cpp
|
Linux/LnxConsolePipe.cpp
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
int TranslateOSXtoWXK(u32 keysym)
|
||||||
|
{
|
||||||
|
switch (keysym)
|
||||||
|
{
|
||||||
|
case kVK_ANSI_A: return 'A';
|
||||||
|
case kVK_ANSI_S: return 'S';
|
||||||
|
case kVK_ANSI_D: return 'D';
|
||||||
|
case kVK_ANSI_F: return 'F';
|
||||||
|
case kVK_ANSI_H: return 'H';
|
||||||
|
case kVK_ANSI_G: return 'G';
|
||||||
|
case kVK_ANSI_Z: return 'Z';
|
||||||
|
case kVK_ANSI_X: return 'X';
|
||||||
|
case kVK_ANSI_C: return 'C';
|
||||||
|
case kVK_ANSI_V: return 'V';
|
||||||
|
case kVK_ANSI_B: return 'B';
|
||||||
|
case kVK_ANSI_Q: return 'Q';
|
||||||
|
case kVK_ANSI_W: return 'W';
|
||||||
|
case kVK_ANSI_E: return 'E';
|
||||||
|
case kVK_ANSI_R: return 'R';
|
||||||
|
case kVK_ANSI_Y: return 'Y';
|
||||||
|
case kVK_ANSI_T: return 'T';
|
||||||
|
case kVK_ANSI_1: return '1';
|
||||||
|
case kVK_ANSI_2: return '2';
|
||||||
|
case kVK_ANSI_3: return '3';
|
||||||
|
case kVK_ANSI_4: return '4';
|
||||||
|
case kVK_ANSI_6: return '6';
|
||||||
|
case kVK_ANSI_5: return '5';
|
||||||
|
case kVK_ANSI_Equal: return '=';
|
||||||
|
case kVK_ANSI_9: return '9';
|
||||||
|
case kVK_ANSI_7: return '7';
|
||||||
|
case kVK_ANSI_Minus: return '-';
|
||||||
|
case kVK_ANSI_8: return '8';
|
||||||
|
case kVK_ANSI_0: return '0';
|
||||||
|
case kVK_ANSI_RightBracket: return ']';
|
||||||
|
case kVK_ANSI_O: return 'O';
|
||||||
|
case kVK_ANSI_U: return 'U';
|
||||||
|
case kVK_ANSI_LeftBracket: return '[';
|
||||||
|
case kVK_ANSI_I: return 'I';
|
||||||
|
case kVK_ANSI_P: return 'P';
|
||||||
|
case kVK_ANSI_L: return 'L';
|
||||||
|
case kVK_ANSI_J: return 'J';
|
||||||
|
case kVK_ANSI_Quote: return '\'';
|
||||||
|
case kVK_ANSI_K: return 'K';
|
||||||
|
case kVK_ANSI_Semicolon: return ';';
|
||||||
|
case kVK_ANSI_Backslash: return '\\';
|
||||||
|
case kVK_ANSI_Comma: return ',';
|
||||||
|
case kVK_ANSI_Slash: return '/';
|
||||||
|
case kVK_ANSI_N: return 'N';
|
||||||
|
case kVK_ANSI_M: return 'M';
|
||||||
|
case kVK_ANSI_Period: return '.';
|
||||||
|
case kVK_ANSI_Grave: return '`';
|
||||||
|
case kVK_ANSI_KeypadDecimal: return WXK_NUMPAD_DECIMAL;
|
||||||
|
case kVK_ANSI_KeypadMultiply: return WXK_NUMPAD_MULTIPLY;
|
||||||
|
case kVK_ANSI_KeypadPlus: return WXK_NUMPAD_ADD;
|
||||||
|
case kVK_ANSI_KeypadClear: return WXK_CLEAR;
|
||||||
|
case kVK_ANSI_KeypadDivide: return WXK_NUMPAD_DIVIDE;
|
||||||
|
case kVK_ANSI_KeypadEnter: return WXK_NUMPAD_ENTER;
|
||||||
|
case kVK_ANSI_KeypadMinus: return WXK_NUMPAD_SUBTRACT;
|
||||||
|
case kVK_ANSI_KeypadEquals: return WXK_NUMPAD_EQUAL;
|
||||||
|
case kVK_ANSI_Keypad0: return WXK_NUMPAD0;
|
||||||
|
case kVK_ANSI_Keypad1: return WXK_NUMPAD1;
|
||||||
|
case kVK_ANSI_Keypad2: return WXK_NUMPAD2;
|
||||||
|
case kVK_ANSI_Keypad3: return WXK_NUMPAD3;
|
||||||
|
case kVK_ANSI_Keypad4: return WXK_NUMPAD4;
|
||||||
|
case kVK_ANSI_Keypad5: return WXK_NUMPAD5;
|
||||||
|
case kVK_ANSI_Keypad6: return WXK_NUMPAD6;
|
||||||
|
case kVK_ANSI_Keypad7: return WXK_NUMPAD7;
|
||||||
|
case kVK_ANSI_Keypad8: return WXK_NUMPAD8;
|
||||||
|
case kVK_ANSI_Keypad9: return WXK_NUMPAD9;
|
||||||
|
|
||||||
|
case kVK_Return: return WXK_RETURN;
|
||||||
|
case kVK_Tab: return WXK_TAB;
|
||||||
|
case kVK_Space: return WXK_SPACE;
|
||||||
|
case kVK_Delete: return WXK_BACK;
|
||||||
|
case kVK_Escape: return WXK_ESCAPE;
|
||||||
|
case kVK_Command: return WXK_COMMAND;
|
||||||
|
case kVK_Shift: return WXK_SHIFT;
|
||||||
|
case kVK_CapsLock: return WXK_CAPITAL;
|
||||||
|
case kVK_Option: return WXK_ALT;
|
||||||
|
case kVK_Control: return WXK_RAW_CONTROL;
|
||||||
|
case kVK_RightCommand: return WXK_COMMAND;
|
||||||
|
case kVK_RightShift: return WXK_SHIFT;
|
||||||
|
case kVK_RightOption: return WXK_ALT;
|
||||||
|
case kVK_RightControl: return WXK_RAW_CONTROL;
|
||||||
|
case kVK_Function: return 0;
|
||||||
|
case kVK_F17: return WXK_F17;
|
||||||
|
#if wxCHECK_VERSION(3, 1, 0)
|
||||||
|
case kVK_VolumeUp: return WXK_VOLUME_UP;
|
||||||
|
case kVK_VolumeDown: return WXK_VOLUME_DOWN;
|
||||||
|
case kVK_Mute: return WXK_VOLUME_MUTE;
|
||||||
|
#endif
|
||||||
|
case kVK_F18: return WXK_F18;
|
||||||
|
case kVK_F19: return WXK_F19;
|
||||||
|
case kVK_F20: return WXK_F20;
|
||||||
|
case kVK_F5: return WXK_F5;
|
||||||
|
case kVK_F6: return WXK_F6;
|
||||||
|
case kVK_F7: return WXK_F7;
|
||||||
|
case kVK_F3: return WXK_F3;
|
||||||
|
case kVK_F8: return WXK_F8;
|
||||||
|
case kVK_F9: return WXK_F9;
|
||||||
|
case kVK_F11: return WXK_F11;
|
||||||
|
case kVK_F13: return WXK_F13;
|
||||||
|
case kVK_F16: return WXK_F16;
|
||||||
|
case kVK_F14: return WXK_F14;
|
||||||
|
case kVK_F10: return WXK_F10;
|
||||||
|
case kVK_F12: return WXK_F12;
|
||||||
|
case kVK_F15: return WXK_F15;
|
||||||
|
case kVK_Help: return WXK_HELP;
|
||||||
|
case kVK_Home: return WXK_HOME;
|
||||||
|
case kVK_PageUp: return WXK_PAGEUP;
|
||||||
|
case kVK_ForwardDelete: return WXK_DELETE;
|
||||||
|
case kVK_F4: return WXK_F4;
|
||||||
|
case kVK_End: return WXK_END;
|
||||||
|
case kVK_F2: return WXK_F2;
|
||||||
|
case kVK_PageDown: return WXK_PAGEDOWN;
|
||||||
|
case kVK_F1: return WXK_F1;
|
||||||
|
case kVK_LeftArrow: return WXK_LEFT;
|
||||||
|
case kVK_RightArrow: return WXK_RIGHT;
|
||||||
|
case kVK_DownArrow: return WXK_DOWN;
|
||||||
|
case kVK_UpArrow: return WXK_UP;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,8 @@
|
||||||
#include "gui/AppCoreThread.h"
|
#include "gui/AppCoreThread.h"
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string GetDumpName()
|
static std::string GetDumpName()
|
||||||
|
@ -603,10 +605,17 @@ void GSRenderer::EndCapture()
|
||||||
|
|
||||||
void GSRenderer::KeyEvent(const HostKeyEvent& e)
|
void GSRenderer::KeyEvent(const HostKeyEvent& e)
|
||||||
{
|
{
|
||||||
#if !defined(PCSX2_CORE) && !defined(__APPLE__) // TODO: Add hotkey support on macOS
|
#if !defined(PCSX2_CORE)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_shift_key = !!(::GetAsyncKeyState(VK_SHIFT) & 0x8000);
|
m_shift_key = !!(::GetAsyncKeyState(VK_SHIFT) & 0x8000);
|
||||||
m_control_key = !!(::GetAsyncKeyState(VK_CONTROL) & 0x8000);
|
m_control_key = !!(::GetAsyncKeyState(VK_CONTROL) & 0x8000);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
m_shift_key = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_Shift)
|
||||||
|
|| CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_RightShift);
|
||||||
|
m_control_key = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_Control)
|
||||||
|
|| CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_RightControl)
|
||||||
|
|| CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_Command)
|
||||||
|
|| CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_RightCommand);
|
||||||
#else
|
#else
|
||||||
switch (e.key)
|
switch (e.key)
|
||||||
{
|
{
|
||||||
|
@ -628,12 +637,12 @@ void GSRenderer::KeyEvent(const HostKeyEvent& e)
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
#define VK_F5 XK_F5
|
#define VK_F5 XK_F5
|
||||||
#define VK_F6 XK_F6
|
|
||||||
#define VK_DELETE XK_Delete
|
#define VK_DELETE XK_Delete
|
||||||
#define VK_INSERT XK_Insert
|
|
||||||
#define VK_PRIOR XK_Prior
|
|
||||||
#define VK_NEXT XK_Next
|
#define VK_NEXT XK_Next
|
||||||
#define VK_HOME XK_Home
|
#elif defined(__APPLE__)
|
||||||
|
#define VK_F5 kVK_F5
|
||||||
|
#define VK_DELETE kVK_ForwardDelete
|
||||||
|
#define VK_NEXT kVK_PageDown
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: These are all BROKEN! They mess with GS thread state from the UI thread.
|
// NOTE: These are all BROKEN! They mess with GS thread state from the UI thread.
|
||||||
|
@ -657,7 +666,7 @@ void GSRenderer::KeyEvent(const HostKeyEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __APPLE__
|
#endif // PCSX2_CORE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSRenderer::PurgePool()
|
void GSRenderer::PurgePool()
|
||||||
|
|
18
pcsx2/Host.h
18
pcsx2/Host.h
|
@ -26,14 +26,16 @@ struct HostKeyEvent
|
||||||
{
|
{
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
NoEvent = 0,
|
NoEvent,
|
||||||
KeyPressed = 1,
|
KeyPressed,
|
||||||
KeyReleased = 2,
|
KeyReleased,
|
||||||
MousePressed = 3,
|
MousePressed,
|
||||||
MouseReleased = 4,
|
MouseReleased,
|
||||||
MouseWheelDown = 5,
|
MouseWheelDown,
|
||||||
MouseWheelUp = 6,
|
MouseWheelUp,
|
||||||
MouseMove = 7,
|
MouseMove,
|
||||||
|
FocusGained,
|
||||||
|
FocustLost,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
|
|
@ -31,6 +31,6 @@ void PADconfigure();
|
||||||
s32 PADfreeze(FreezeAction mode, freezeData* data);
|
s32 PADfreeze(FreezeAction mode, freezeData* data);
|
||||||
s32 PADsetSlot(u8 port, u8 slot);
|
s32 PADsetSlot(u8 port, u8 slot);
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
void PADWriteEvent(HostKeyEvent& evt);
|
void PADWriteEvent(HostKeyEvent& evt);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -220,7 +220,7 @@ HostKeyEvent* PADkeyEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef __unix__
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
if (g_ev_fifo.size() == 0)
|
if (g_ev_fifo.size() == 0)
|
||||||
{
|
{
|
||||||
//PAD_LOG("No events in queue, returning empty event");
|
//PAD_LOG("No events in queue, returning empty event");
|
||||||
|
@ -234,15 +234,10 @@ HostKeyEvent* PADkeyEvent()
|
||||||
AnalyzeKeyEvent(s_event);
|
AnalyzeKeyEvent(s_event);
|
||||||
//PAD_LOG("Returning Event. Event Type: %d, Key: %d", s_event.type, s_event.key);
|
//PAD_LOG("Returning Event. Event Type: %d, Key: %d", s_event.type, s_event.key);
|
||||||
return &s_event;
|
return &s_event;
|
||||||
#else // MacOS
|
|
||||||
s_event = event;
|
|
||||||
event.type = HostKeyEvent::Type::NoEvent;
|
|
||||||
event.key = 0;
|
|
||||||
return &s_event;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
void PADWriteEvent(HostKeyEvent& evt)
|
void PADWriteEvent(HostKeyEvent& evt)
|
||||||
{
|
{
|
||||||
// if (evt.evt != 6) { // Skip mouse move events for logging
|
// if (evt.evt != 6) { // Skip mouse move events for logging
|
||||||
|
@ -280,4 +275,4 @@ void PADconfigure()
|
||||||
DisplayDialog();
|
DisplayDialog();
|
||||||
paused_core.AllowResume();
|
paused_core.AllowResume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,29 +64,7 @@ static void PressButton(u32 pad, u32 button)
|
||||||
|
|
||||||
void UpdateKeyboardInput()
|
void UpdateKeyboardInput()
|
||||||
{
|
{
|
||||||
for (u32 pad = 0; pad < GAMEPAD_NUMBER; pad++)
|
g_ev_fifo.consume_all(AnalyzeKeyEvent);
|
||||||
{
|
|
||||||
const auto& map = g_conf.keysym_map[pad];
|
|
||||||
// If we loop over all keys press/release based on current state,
|
|
||||||
// joystick axes (which have two bound keys) will always go to the later-polled key
|
|
||||||
// Instead, release all keys first and then set the ones that are pressed
|
|
||||||
for (const auto& key : map)
|
|
||||||
g_key_status.release(pad, key.second);
|
|
||||||
for (const auto& key : map)
|
|
||||||
{
|
|
||||||
bool state;
|
|
||||||
if (key.first >> 16 == 0)
|
|
||||||
{
|
|
||||||
state = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key.first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, (CGMouseButton)(key.first & 0xFFFF));
|
|
||||||
}
|
|
||||||
if (state)
|
|
||||||
PressButton(pad, key.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PollForNewKeyboardKeys(u32& pkey)
|
bool PollForNewKeyboardKeys(u32& pkey)
|
||||||
|
@ -101,31 +79,103 @@ bool PollForNewKeyboardKeys(u32& pkey)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto btn : {kCGMouseButtonLeft, kCGMouseButtonCenter, kCGMouseButtonRight})
|
#define CHECK(button, value) \
|
||||||
{
|
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, (button))) \
|
||||||
if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, btn))
|
{ \
|
||||||
{
|
pkey = (value); \
|
||||||
pkey = btn | (1 << 16);
|
return true; \
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
CHECK(kCGMouseButtonLeft, 0x10001)
|
||||||
|
CHECK(kCGMouseButtonCenter, 0x10002)
|
||||||
|
CHECK(kCGMouseButtonRight, 0x10003)
|
||||||
|
#undef CHECK
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
static bool s_grab_input = false;
|
static bool s_grab_input = false;
|
||||||
static bool s_Shift = false;
|
static bool s_Shift = false;
|
||||||
|
|
||||||
|
void UpdateKeyboardInput()
|
||||||
|
{
|
||||||
|
HostKeyEvent evt = {};
|
||||||
|
XEvent E = {0};
|
||||||
|
|
||||||
|
// Keyboard input send by PCSX2
|
||||||
|
g_ev_fifo.consume_all(AnalyzeKeyEvent);
|
||||||
|
|
||||||
|
// keyboard input
|
||||||
|
if (!GSdsp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (XPending(GSdsp) > 0)
|
||||||
|
{
|
||||||
|
XNextEvent(GSdsp, &E);
|
||||||
|
|
||||||
|
// Change the format of the structure to be compatible with GSOpen2
|
||||||
|
// mode (event come from pcsx2 not X)
|
||||||
|
evt.type = static_cast<HostKeyEvent::Type>(E.type);
|
||||||
|
switch (E.type)
|
||||||
|
{
|
||||||
|
case MotionNotify:
|
||||||
|
evt.key = (E.xbutton.x & 0xFFFF) | (E.xbutton.y << 16);
|
||||||
|
evt.type = HostKeyEvent::Type::MouseMove;
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
evt.key = E.xbutton.button | 0x10000;
|
||||||
|
evt.type = HostKeyEvent::Type::MouseReleased;
|
||||||
|
break;
|
||||||
|
case ButtonPress:
|
||||||
|
evt.key = E.xbutton.button | 0x10000;
|
||||||
|
evt.type = HostKeyEvent::Type::MousePressed;
|
||||||
|
break;
|
||||||
|
case KeyPress:
|
||||||
|
evt.key = (int)XLookupKeysym(&E.xkey, 0);
|
||||||
|
evt.type = HostKeyEvent::Type::KeyPressed;
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
evt.key = (int)XLookupKeysym(&E.xkey, 0);
|
||||||
|
evt.type = HostKeyEvent::Type::KeyReleased;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzeKeyEvent(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PollForNewKeyboardKeys(u32& pkey)
|
||||||
|
{
|
||||||
|
GdkEvent* ev = gdk_event_get();
|
||||||
|
|
||||||
|
if (ev != NULL)
|
||||||
|
{
|
||||||
|
if (ev->type == GDK_KEY_PRESS)
|
||||||
|
{
|
||||||
|
pkey = ev->key.keyval != GDK_KEY_Escape ? ev->key.keyval : UINT32_MAX;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (ev->type == GDK_BUTTON_PRESS)
|
||||||
|
{
|
||||||
|
pkey = ev->button.button | 0x10000;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned int s_previous_mouse_x = 0;
|
static unsigned int s_previous_mouse_x = 0;
|
||||||
static unsigned int s_previous_mouse_y = 0;
|
static unsigned int s_previous_mouse_y = 0;
|
||||||
|
|
||||||
void AnalyzeKeyEvent(HostKeyEvent& evt)
|
void AnalyzeKeyEvent(HostKeyEvent& evt)
|
||||||
{
|
{
|
||||||
KeySym key = (KeySym)evt.key;
|
|
||||||
int pad = 0;
|
int pad = 0;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
for (u32 cpad = 0; cpad < GAMEPAD_NUMBER; cpad++)
|
for (u32 cpad = 0; cpad < GAMEPAD_NUMBER; cpad++)
|
||||||
{
|
{
|
||||||
int tmp_index = get_keyboard_key(cpad, key);
|
int tmp_index = get_keyboard_key(cpad, evt.key);
|
||||||
if (tmp_index != -1)
|
if (tmp_index != -1)
|
||||||
{
|
{
|
||||||
pad = cpad;
|
pad = cpad;
|
||||||
|
@ -133,17 +183,18 @@ void AnalyzeKeyEvent(HostKeyEvent& evt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (static_cast<int>(evt.type))
|
switch (evt.type)
|
||||||
{
|
{
|
||||||
case KeyPress:
|
case HostKeyEvent::Type::KeyPressed:
|
||||||
// Shift F12 is not yet use by pcsx2. So keep it to grab/ungrab input
|
// Shift F12 is not yet use by pcsx2. So keep it to grab/ungrab input
|
||||||
// I found it very handy vs the automatic fullscreen detection
|
// I found it very handy vs the automatic fullscreen detection
|
||||||
// 1/ Does not need to detect full-screen
|
// 1/ Does not need to detect full-screen
|
||||||
// 2/ Can use a debugger in full-screen
|
// 2/ Can use a debugger in full-screen
|
||||||
// 3/ Can grab input in window without the need of a pixelated full-screen
|
// 3/ Can grab input in window without the need of a pixelated full-screen
|
||||||
if (key == XK_Shift_R || key == XK_Shift_L)
|
#ifdef __unix__
|
||||||
|
if (evt.key == XK_Shift_R || evt.key == XK_Shift_L)
|
||||||
s_Shift = true;
|
s_Shift = true;
|
||||||
if (key == XK_F12 && s_Shift)
|
if (evt.key == XK_F12 && s_Shift)
|
||||||
{
|
{
|
||||||
if (!s_grab_input)
|
if (!s_grab_input)
|
||||||
{
|
{
|
||||||
|
@ -158,6 +209,7 @@ void AnalyzeKeyEvent(HostKeyEvent& evt)
|
||||||
XUngrabKeyboard(GSdsp, CurrentTime);
|
XUngrabKeyboard(GSdsp, CurrentTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
PressButton(pad, index);
|
PressButton(pad, index);
|
||||||
|
@ -165,38 +217,42 @@ void AnalyzeKeyEvent(HostKeyEvent& evt)
|
||||||
//PAD_LOG("Key pressed:%d", index);
|
//PAD_LOG("Key pressed:%d", index);
|
||||||
|
|
||||||
event.type = HostKeyEvent::Type::KeyPressed;
|
event.type = HostKeyEvent::Type::KeyPressed;
|
||||||
event.key = key;
|
event.key = evt.key;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyRelease:
|
case HostKeyEvent::Type::KeyReleased:
|
||||||
if (key == XK_Shift_R || key == XK_Shift_L)
|
#ifdef __unix__
|
||||||
|
if (evt.key == XK_Shift_R || evt.key == XK_Shift_L)
|
||||||
s_Shift = false;
|
s_Shift = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
g_key_status.release(pad, index);
|
g_key_status.release(pad, index);
|
||||||
|
|
||||||
event.type = HostKeyEvent::Type::KeyReleased;
|
event.type = HostKeyEvent::Type::KeyReleased;
|
||||||
event.key = key;
|
event.key = evt.key;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FocusIn:
|
case HostKeyEvent::Type::FocusGained:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FocusOut:
|
case HostKeyEvent::Type::FocustLost:
|
||||||
|
#ifdef __unix__
|
||||||
s_Shift = false;
|
s_Shift = false;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonPress:
|
case HostKeyEvent::Type::MousePressed:
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
g_key_status.press(pad, index);
|
g_key_status.press(pad, index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case HostKeyEvent::Type::MouseReleased:
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
g_key_status.release(pad, index);
|
g_key_status.release(pad, index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MotionNotify:
|
case HostKeyEvent::Type::MouseMove:
|
||||||
// FIXME: How to handle when the mouse does not move, no event generated!!!
|
// FIXME: How to handle when the mouse does not move, no event generated!!!
|
||||||
// 1/ small move == no move. Cons : can not do small movement
|
// 1/ small move == no move. Cons : can not do small movement
|
||||||
// 2/ use a watchdog timer thread
|
// 2/ use a watchdog timer thread
|
||||||
|
@ -253,63 +309,10 @@ void AnalyzeKeyEvent(HostKeyEvent& evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HostKeyEvent::Type::NoEvent:
|
||||||
|
case HostKeyEvent::Type::MouseWheelDown:
|
||||||
|
case HostKeyEvent::Type::MouseWheelUp:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateKeyboardInput()
|
|
||||||
{
|
|
||||||
HostKeyEvent evt = {};
|
|
||||||
XEvent E = {0};
|
|
||||||
|
|
||||||
// Keyboard input send by PCSX2
|
|
||||||
g_ev_fifo.consume_all(AnalyzeKeyEvent);
|
|
||||||
|
|
||||||
// keyboard input
|
|
||||||
if (!GSdsp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (XPending(GSdsp) > 0)
|
|
||||||
{
|
|
||||||
XNextEvent(GSdsp, &E);
|
|
||||||
|
|
||||||
// Change the format of the structure to be compatible with GSOpen2
|
|
||||||
// mode (event come from pcsx2 not X)
|
|
||||||
evt.type = static_cast<HostKeyEvent::Type>(E.type);
|
|
||||||
switch (E.type)
|
|
||||||
{
|
|
||||||
case MotionNotify:
|
|
||||||
evt.key = (E.xbutton.x & 0xFFFF) | (E.xbutton.y << 16);
|
|
||||||
break;
|
|
||||||
case ButtonRelease:
|
|
||||||
case ButtonPress:
|
|
||||||
evt.key = E.xbutton.button;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
evt.key = (int)XLookupKeysym(&E.xkey, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnalyzeKeyEvent(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PollForNewKeyboardKeys(u32& pkey)
|
|
||||||
{
|
|
||||||
GdkEvent* ev = gdk_event_get();
|
|
||||||
|
|
||||||
if (ev != NULL)
|
|
||||||
{
|
|
||||||
if (ev->type == GDK_KEY_PRESS)
|
|
||||||
{
|
|
||||||
pkey = ev->key.keyval != GDK_KEY_Escape ? ev->key.keyval : UINT32_MAX;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (ev->type == GDK_BUTTON_PRESS)
|
|
||||||
{
|
|
||||||
pkey = ev->button.button;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -25,14 +25,16 @@ static std::string KeyName(int pad, int key, int keysym)
|
||||||
{
|
{
|
||||||
switch (keysym & 0xFFFF)
|
switch (keysym & 0xFFFF)
|
||||||
{
|
{
|
||||||
case kCGMouseButtonLeft:
|
case 0:
|
||||||
|
return "Mouse ???";
|
||||||
|
case 1:
|
||||||
return "Mouse Left";
|
return "Mouse Left";
|
||||||
case kCGMouseButtonRight:
|
case 2:
|
||||||
return "Mouse Right";
|
|
||||||
case kCGMouseButtonCenter:
|
|
||||||
return "Mouse Middle";
|
return "Mouse Middle";
|
||||||
|
case 3:
|
||||||
|
return "Mouse Right";
|
||||||
default: // Use only number for extra button
|
default: // Use only number for extra button
|
||||||
return "Mouse " + std::to_string(keysym & 0xFFFF);
|
return "Mouse " + std::to_string((keysym & 0xFFFF) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,12 +169,12 @@ static std::string KeyName(int pad, int key, int keysym)
|
||||||
static std::string KeyName(int pad, int key, int keysym)
|
static std::string KeyName(int pad, int key, int keysym)
|
||||||
{
|
{
|
||||||
// Mouse
|
// Mouse
|
||||||
if (keysym < 10)
|
if (keysym >> 16)
|
||||||
{
|
{
|
||||||
switch (keysym)
|
switch (keysym & 0xFFFF)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return "";
|
return "Mouse ???";
|
||||||
case 1:
|
case 1:
|
||||||
return "Mouse Left";
|
return "Mouse Left";
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -180,7 +182,7 @@ static std::string KeyName(int pad, int key, int keysym)
|
||||||
case 3:
|
case 3:
|
||||||
return "Mouse Right";
|
return "Mouse Right";
|
||||||
default: // Use only number for extra button
|
default: // Use only number for extra button
|
||||||
return "Mouse " + std::to_string(keysym);
|
return "Mouse " + std::to_string((keysym & 0xFFFF) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,9 +153,11 @@ protected:
|
||||||
wxIMPLEMENT_DYNAMIC_CLASS( Pcsx2AppMethodEvent, pxActionEvent );
|
wxIMPLEMENT_DYNAMIC_CLASS( Pcsx2AppMethodEvent, pxActionEvent );
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
extern int TranslateVKToWXK( u32 keysym );
|
extern int TranslateVKToWXK(u32 keysym);
|
||||||
#elif defined( __WXGTK__ )
|
#elif defined(__WXGTK__)
|
||||||
extern int TranslateGDKtoWXK( u32 keysym );
|
extern int TranslateGDKtoWXK(u32 keysym);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
extern int TranslateOSXtoWXK(u32 keysym);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Pcsx2App::PadKeyDispatch(const HostKeyEvent& ev)
|
void Pcsx2App::PadKeyDispatch(const HostKeyEvent& ev)
|
||||||
|
@ -166,9 +168,9 @@ void Pcsx2App::PadKeyDispatch(const HostKeyEvent& ev)
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
const int vkey = TranslateVKToWXK(ev.key);
|
const int vkey = TranslateVKToWXK(ev.key);
|
||||||
#elif defined( __WXMAC__ )
|
#elif defined( __WXMAC__ )
|
||||||
const int vkey = wxCharCodeWXToOSX( (wxKeyCode) ev.key );
|
const int vkey = TranslateOSXtoWXK(ev.key);
|
||||||
#elif defined( __WXGTK__ )
|
#elif defined( __WXGTK__ )
|
||||||
const int vkey = TranslateGDKtoWXK( ev.key );
|
const int vkey = TranslateGDKtoWXK(ev.key);
|
||||||
#else
|
#else
|
||||||
# error Unsupported Target Platform.
|
# error Unsupported Target Platform.
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -397,24 +397,24 @@ void GSPanel::OnMouseEvent( wxMouseEvent& evt )
|
||||||
DoShowMouse();
|
DoShowMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
||||||
// the event before the pad see it. So you send key event directly to the pad.
|
// the event before the pad see it. So you send key event directly to the pad.
|
||||||
HostKeyEvent event;
|
HostKeyEvent event;
|
||||||
// FIXME how to handle double click ???
|
// FIXME how to handle double click ???
|
||||||
if (evt.ButtonDown())
|
if (evt.ButtonDown())
|
||||||
{
|
{
|
||||||
event.type = static_cast<HostKeyEvent::Type>(4); // X equivalent of ButtonPress
|
event.type = HostKeyEvent::Type::MousePressed;
|
||||||
event.key = evt.GetButton();
|
event.key = evt.GetButton() | 0x10000;
|
||||||
}
|
}
|
||||||
else if (evt.ButtonUp())
|
else if (evt.ButtonUp())
|
||||||
{
|
{
|
||||||
event.type = static_cast<HostKeyEvent::Type>(5); // X equivalent of ButtonRelease
|
event.type = HostKeyEvent::Type::MouseReleased;
|
||||||
event.key = evt.GetButton();
|
event.key = evt.GetButton() | 0x10000;
|
||||||
}
|
}
|
||||||
else if (evt.Moving() || evt.Dragging())
|
else if (evt.Moving() || evt.Dragging())
|
||||||
{
|
{
|
||||||
event.type = static_cast<HostKeyEvent::Type>(6); // X equivalent of MotionNotify
|
event.type = HostKeyEvent::Type::MouseMove;
|
||||||
long x, y;
|
long x, y;
|
||||||
evt.GetPosition(&x, &y);
|
evt.GetPosition(&x, &y);
|
||||||
|
|
||||||
|
@ -464,15 +464,15 @@ void GSPanel::OnKeyDownOrUp( wxKeyEvent& evt )
|
||||||
// to the APP level message handler, which in turn routes them right back here -- yes it's
|
// to the APP level message handler, which in turn routes them right back here -- yes it's
|
||||||
// silly, but oh well).
|
// silly, but oh well).
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
||||||
// the event before the pad see it. So you send key event directly to the pad.
|
// the event before the pad see it. So you send key event directly to the pad.
|
||||||
HostKeyEvent event;
|
HostKeyEvent event;
|
||||||
event.key = evt.GetRawKeyCode();
|
event.key = evt.GetRawKeyCode();
|
||||||
if (evt.GetEventType() == wxEVT_KEY_UP)
|
if (evt.GetEventType() == wxEVT_KEY_UP)
|
||||||
event.type = static_cast<HostKeyEvent::Type>(3); // X equivalent of KEYRELEASE;
|
event.type = HostKeyEvent::Type::KeyReleased;
|
||||||
else if (evt.GetEventType() == wxEVT_KEY_DOWN)
|
else if (evt.GetEventType() == wxEVT_KEY_DOWN)
|
||||||
event.type = static_cast<HostKeyEvent::Type>(2); // X equivalent of KEYPRESS;
|
event.type = HostKeyEvent::Type::KeyPressed;
|
||||||
else
|
else
|
||||||
event.type = HostKeyEvent::Type::NoEvent;
|
event.type = HostKeyEvent::Type::NoEvent;
|
||||||
|
|
||||||
|
@ -547,10 +547,10 @@ void GSPanel::OnFocus( wxFocusEvent& evt )
|
||||||
else
|
else
|
||||||
DoShowMouse();
|
DoShowMouse();
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
||||||
// the event before the pad see it. So you send key event directly to the pad.
|
// the event before the pad see it. So you send key event directly to the pad.
|
||||||
HostKeyEvent event = {static_cast<HostKeyEvent::Type>(9), 0}; // X equivalent of FocusIn;
|
HostKeyEvent event = {HostKeyEvent::Type::FocusGained, 0};
|
||||||
PADWriteEvent(event);
|
PADWriteEvent(event);
|
||||||
#endif
|
#endif
|
||||||
//Console.Warning("GS frame > focus set");
|
//Console.Warning("GS frame > focus set");
|
||||||
|
@ -563,10 +563,10 @@ void GSPanel::OnFocusLost( wxFocusEvent& evt )
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
m_HasFocus = false;
|
m_HasFocus = false;
|
||||||
DoShowMouse();
|
DoShowMouse();
|
||||||
#if defined(__unix__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad. Wx deletes
|
||||||
// the event before the pad see it. So you send key event directly to the pad.
|
// the event before the pad see it. So you send key event directly to the pad.
|
||||||
HostKeyEvent event = {static_cast<HostKeyEvent::Type>(9), 0}; // X equivalent of FocusOut
|
HostKeyEvent event = {HostKeyEvent::Type::FocustLost, 0};
|
||||||
PADWriteEvent(event);
|
PADWriteEvent(event);
|
||||||
#endif
|
#endif
|
||||||
//Console.Warning("GS frame > focus lost");
|
//Console.Warning("GS frame > focus lost");
|
||||||
|
|
Loading…
Reference in New Issue