mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-09 14:22:58 +02:00
New method of ensuring thread safety. Device update code should always run in GS thread, even if the emulator really doesn't want to let me (Basically ancient versions of Pcsx2...Or any 3rd party emulators with their own version of MTGS). Updates on PADpoll, PADkeyEvent, or PADupdate, if one is called in the right thread. Updates in thread's WndProc otherwise. Overkill, perhaps, but I prefer to keep things compatible. Removed "Update in GS thread" option. Windows Messaging/Raw Input keyboard event queuing should work a little better. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1896 96395faa-99c1-11dd-bbfe-3dabce05a288
181 lines
4.7 KiB
C++
181 lines
4.7 KiB
C++
#include "Global.h"
|
|
#include "WindowsMessaging.h"
|
|
#include "VKey.h"
|
|
#include "DeviceEnumerator.h"
|
|
#include "WndProcEater.h"
|
|
#include "WindowsKeyboard.h"
|
|
#include "WindowsMouse.h"
|
|
|
|
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output);
|
|
|
|
class WindowsMessagingKeyboard;
|
|
class WindowsMessagingMouse;
|
|
|
|
static WindowsMessagingKeyboard *wmk = 0;
|
|
static WindowsMessagingMouse *wmm = 0;
|
|
|
|
class WindowsMessagingKeyboard : public WindowsKeyboard {
|
|
public:
|
|
|
|
WindowsMessagingKeyboard() : WindowsKeyboard(WM, L"WM Keyboard") {
|
|
}
|
|
|
|
int Activate(InitInfo *initInfo) {
|
|
// Redundant. Should match the next line.
|
|
// Deactivate();
|
|
if (wmk) wmk->Deactivate();
|
|
HWND hWnd = initInfo->hWnd;
|
|
if (initInfo->hWndButton) {
|
|
hWnd = initInfo->hWndButton;
|
|
}
|
|
if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
|
|
Deactivate();
|
|
return 0;
|
|
}
|
|
|
|
wmk = this;
|
|
InitState();
|
|
|
|
active = 1;
|
|
return 1;
|
|
}
|
|
|
|
void Deactivate() {
|
|
if (active) {
|
|
if (!wmm)
|
|
ReleaseExtraProc(WindowsMessagingWndProc);
|
|
wmk = 0;
|
|
active = 0;
|
|
FreeState();
|
|
}
|
|
}
|
|
|
|
|
|
void CheckKey(int vkey) {
|
|
UpdateKey(vkey, 1&(((unsigned short)GetAsyncKeyState(vkey))>>15));
|
|
}
|
|
};
|
|
|
|
class WindowsMessagingMouse : public WindowsMouse {
|
|
public:
|
|
|
|
WindowsMessagingMouse() : WindowsMouse(WM, 1, L"WM Mouse") {
|
|
}
|
|
|
|
int Activate(InitInfo *initInfo) {
|
|
// Redundant. Should match the next line.
|
|
// Deactivate();
|
|
if (wmm) wmm->Deactivate();
|
|
HWND hWnd = initInfo->hWnd;
|
|
if (initInfo->hWndButton) {
|
|
hWnd = initInfo->hWndButton;
|
|
}
|
|
|
|
if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
|
|
Deactivate();
|
|
return 0;
|
|
}
|
|
GetMouseCapture(hWnd);
|
|
|
|
active = 1;
|
|
|
|
wmm = this;
|
|
AllocState();
|
|
|
|
return 1;
|
|
}
|
|
|
|
void Deactivate() {
|
|
if (active) {
|
|
if (!wmk)
|
|
ReleaseExtraProc(WindowsMessagingWndProc);
|
|
ReleaseMouseCapture();
|
|
wmm = 0;
|
|
active = 0;
|
|
FreeState();
|
|
}
|
|
}
|
|
};
|
|
|
|
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
|
|
if (wmk) {
|
|
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) {
|
|
if (wParam == VK_SHIFT) {
|
|
wmk->CheckKey(VK_RSHIFT);
|
|
wmk->CheckKey(VK_LSHIFT);
|
|
}
|
|
else if (wParam == VK_CONTROL) {
|
|
wmk->CheckKey(VK_RCONTROL);
|
|
wmk->CheckKey(VK_LCONTROL);
|
|
}
|
|
else if (wParam == VK_MENU) {
|
|
wmk->CheckKey(VK_RMENU);
|
|
wmk->CheckKey(VK_LMENU);
|
|
}
|
|
else
|
|
wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
|
|
return NO_WND_PROC;
|
|
}
|
|
// Needed to prevent default handling of keys in some situations.
|
|
else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR) {
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_ACTIVATE) {
|
|
// Not really needed, but doesn't hurt.
|
|
memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls);
|
|
}
|
|
}
|
|
if (wmm) {
|
|
if (uMsg == WM_MOUSEMOVE) {
|
|
POINT p;
|
|
GetCursorPos(&p);
|
|
// Need check to prevent cursor movement cascade.
|
|
if (p.x != wmm->center.x || p.y != wmm->center.y) {
|
|
wmm->UpdateAxis(0, p.x - wmm->center.x);
|
|
wmm->UpdateAxis(1, p.y - wmm->center.y);
|
|
|
|
SetCursorPos(wmm->center.x, wmm->center.y);
|
|
}
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
|
|
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
|
|
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
|
|
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
|
|
wmm->UpdateButton(3+((wParam>>16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_MOUSEWHEEL) {
|
|
wmm->UpdateAxis(2, ((int)wParam>>16)/WHEEL_DELTA);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_MOUSEHWHEEL) {
|
|
wmm->UpdateAxis(3, ((int)wParam>>16)/WHEEL_DELTA);
|
|
return NO_WND_PROC;
|
|
}
|
|
else if (uMsg == WM_SIZE && wmm->active) {
|
|
WindowsMouse::WindowResized(hWnd);
|
|
}
|
|
// Taken care of elsewhere. When binding, killing focus means stop reading input.
|
|
// When running PCSX2, I release all mouse and keyboard input elsewhere.
|
|
/*else if (uMsg == WM_KILLFOCUS) {
|
|
wmm->Deactivate();
|
|
}//*/
|
|
}
|
|
return CONTINUE_BLISSFULLY;
|
|
}
|
|
|
|
void EnumWindowsMessagingDevices() {
|
|
dm->AddDevice(new WindowsMessagingKeyboard());
|
|
dm->AddDevice(new WindowsMessagingMouse());
|
|
}
|