mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-28 15:27:05 +02:00
DevNotes: The main change here was to turn WndProcEater into a class and create multiple instances of it, so that it could manage the WndProcs for multiple windows concurrently. The "frame" (top-level window) gets a WndProc that sets title and handles screensaver/alt-enter hacks. The "viewport" (provided by PCSX2) gets the usual keyboard input handler WndProc. Config buttons also have their own WndProc that avoid fuzzy logic conflicts with the other two. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2277 96395faa-99c1-11dd-bbfe-3dabce05a288
129 lines
3.7 KiB
C++
129 lines
3.7 KiB
C++
#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;
|
|
if (hWndEaten && IsWindow(hWndEaten)) {
|
|
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
|
|
}
|
|
hWndEaten = 0;
|
|
eatenWndProc = 0;
|
|
}
|
|
}
|
|
|
|
void WndProcEater::Release() {
|
|
while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc);
|
|
RemoveProp( hWndEaten, L"LilyHaxxor" );
|
|
}
|
|
|
|
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++;
|
|
}
|