Files
pcsx2/plugins/LilyPad/WndProcEater.cpp
T
Jake.Stine 1ea29b0e62 Lilypad: Implemented full support for child-window GS viewports (fixes windows messaging being broken from the prev rev).
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
2009-11-30 20:52:09 +00:00

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++;
}