mirror of https://github.com/PCSX2/pcsx2.git
156 lines
4.8 KiB
C++
156 lines
4.8 KiB
C++
/* LilyPad - Pad plugin for PS2 Emulator
|
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
|
*
|
|
* 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 "Global.h"
|
|
#include "WndProcEater.h"
|
|
|
|
WndProcEater::WndProcEater()
|
|
{
|
|
hWndEaten = 0;
|
|
eatenWndProc = 0;
|
|
|
|
extraProcs = 0;
|
|
numExtraProcs = 0;
|
|
|
|
hMutex = CreateMutex(0, 0, L"LilyPad");
|
|
}
|
|
|
|
WndProcEater::~WndProcEater() throw()
|
|
{
|
|
if (hMutex) {
|
|
ReleaseMutex(hMutex);
|
|
CloseHandle(hMutex);
|
|
}
|
|
}
|
|
|
|
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc)
|
|
{
|
|
// Probably isn't needed, but just in case...
|
|
if (hMutex)
|
|
WaitForSingleObject(hMutex, 100);
|
|
|
|
//printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc );
|
|
|
|
for (int i = 0; i < numExtraProcs; i++) {
|
|
if (extraProcs[i].proc == proc) {
|
|
extraProcs[i] = extraProcs[--numExtraProcs];
|
|
break;
|
|
}
|
|
}
|
|
if (!numExtraProcs && eatenWndProc) {
|
|
free(extraProcs);
|
|
extraProcs = 0;
|
|
// As numExtraProcs is 0, won't cause recursion if called from Release().
|
|
Release();
|
|
}
|
|
}
|
|
|
|
void WndProcEater::Release()
|
|
{
|
|
while (numExtraProcs)
|
|
ReleaseExtraProc(extraProcs[0].proc);
|
|
if (hWndEaten && IsWindow(hWndEaten)) {
|
|
RemoveProp(hWndEaten, L"LilyHaxxor");
|
|
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
|
|
hWndEaten = 0;
|
|
eatenWndProc = 0;
|
|
}
|
|
}
|
|
|
|
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (hWnd != hWndEaten)
|
|
fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n");
|
|
|
|
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
|
|
LRESULT out = 0;
|
|
// Here because want it for binding, even when no keyboard mode is selected.
|
|
if (uMsg == WM_GETDLGCODE) {
|
|
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
for (int i = 0; i < numExtraProcs; i++) {
|
|
// Note: Second bit of deviceUpdateQueued is only set when I receive a device change
|
|
// notification, which is handled in the GS thread in one of the extraProcs, so this
|
|
// is all I need to prevent bad things from happening while updating devices. No mutex needed.
|
|
// if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue;
|
|
|
|
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
|
|
if (res2 != res) {
|
|
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
|
|
ReleaseExtraProc(extraProcs[i].proc);
|
|
i--;
|
|
} else if (res2 > res)
|
|
res = res2;
|
|
}
|
|
}
|
|
|
|
if (res != NO_WND_PROC) {
|
|
if (out == WM_DESTROY) {
|
|
Release();
|
|
}
|
|
if (res == CONTINUE_BLISSFULLY)
|
|
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
|
|
else if (res == USE_DEFAULT_WND_PROC)
|
|
out = DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WndProcEater *obj = (WndProcEater *)GetProp(hWnd, L"LilyHaxxor");
|
|
return (obj == NULL) ?
|
|
DefWindowProc(hWnd, uMsg, wParam, lParam) :
|
|
obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
bool WndProcEater::SetWndHandle(HWND hWnd)
|
|
{
|
|
if (hWnd == hWndEaten)
|
|
return true;
|
|
|
|
//printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd );
|
|
|
|
Release();
|
|
SetProp(hWnd, L"LilyHaxxor", (HANDLE) this);
|
|
|
|
eatenWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
|
|
hWndEaten = (eatenWndProc) ? hWnd : 0;
|
|
|
|
return !!hWndEaten;
|
|
}
|
|
|
|
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags)
|
|
{
|
|
|
|
// check if Subclassing failed to init during SetWndHandle
|
|
if (!hWndEaten)
|
|
return;
|
|
|
|
// Probably isn't needed, but just in case...
|
|
if (hMutex)
|
|
WaitForSingleObject(hMutex, 100);
|
|
|
|
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc );
|
|
|
|
extraProcs = (ExtraWndProcInfo *)realloc(extraProcs, sizeof(ExtraWndProcInfo) * (numExtraProcs + 1));
|
|
extraProcs[numExtraProcs].proc = proc;
|
|
extraProcs[numExtraProcs].flags = flags;
|
|
numExtraProcs++;
|
|
}
|