You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
494 lines
10 KiB
494 lines
10 KiB
/*=========================================================================
|
|
*
|
|
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: winwatch.c
|
|
* Content: 16-bit window watch code
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 20-jun-95 craige split out of DCIMAN WINWATCH.C, tweaked
|
|
* 22-jun-95 craige re-worked for clipper stuff
|
|
* 02-jul-95 craige comment out clipper notify stuff
|
|
*
|
|
***************************************************************************/
|
|
#define _INC_DCIDDI
|
|
#include "ddraw16.h"
|
|
#undef _INC_DCIDDI
|
|
|
|
#ifdef CLIPPER_NOTIFY
|
|
static LPWINWATCH lpWWList;
|
|
static HHOOK hNextCallWndProc;
|
|
static BOOL bUnHook;
|
|
|
|
long FAR PASCAL _loadds CallWndProcHook(int hc, WPARAM wParam, LPARAM lParam);
|
|
|
|
extern HRGN FAR PASCAL InquireVisRgn(HDC hdc);
|
|
extern DWORD FAR PASCAL GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA prd);
|
|
|
|
/*
|
|
* doNotify
|
|
*/
|
|
void doNotify(LPWINWATCH pww, DWORD code)
|
|
{
|
|
if( pww->lpCallback )
|
|
{
|
|
extern void DDAPI DD32_ClippingNotify( LPVOID, DWORD );
|
|
DD32_ClippingNotify( pww->self32, code );
|
|
}
|
|
|
|
} /* doNotify */
|
|
|
|
/*
|
|
* DD16_WWOpen
|
|
*/
|
|
void DDAPI DD16_WWOpen( LPWINWATCH ptr )
|
|
{
|
|
if( lpWWList == NULL )
|
|
{
|
|
DPF( 2, "Setting Windows Hook" );
|
|
hNextCallWndProc = (HHOOK) SetWindowsHook( WH_CALLWNDPROC,
|
|
(HOOKPROC) CallWndProcHook );
|
|
}
|
|
lpWWList = ptr;
|
|
|
|
} /* DD16_WWOpen */
|
|
|
|
/*
|
|
* DD16_WWClose
|
|
*/
|
|
void DDAPI DD16_WWClose( LPWINWATCH pww, LPWINWATCH newlist )
|
|
{
|
|
if( pww->prd16 != NULL )
|
|
{
|
|
LocalFree( (HLOCAL) pww->prd16 );
|
|
pww->prd16 = NULL;
|
|
}
|
|
if( newlist == NULL )
|
|
{
|
|
DPF( 3, "Flagging to Unhook" );
|
|
bUnHook = TRUE;
|
|
}
|
|
lpWWList = newlist;
|
|
|
|
} /* DD16_WWClose */
|
|
|
|
/*
|
|
* DD16_WWNotifyInit
|
|
*/
|
|
void DDAPI DD16_WWNotifyInit(
|
|
LPWINWATCH pww,
|
|
LPCLIPPERCALLBACK lpcallback,
|
|
LPVOID param )
|
|
{
|
|
doNotify( pww, WINWATCHNOTIFY_STOP );
|
|
|
|
pww->lpCallback = lpcallback;
|
|
pww->lpContext = param;
|
|
|
|
doNotify( pww, WINWATCHNOTIFY_START );
|
|
doNotify( pww, WINWATCHNOTIFY_CHANGED );
|
|
pww->fNotify = FALSE;
|
|
|
|
} /* DD16_WWNotifyInit */
|
|
|
|
/*
|
|
* getWindowRegionData
|
|
*/
|
|
static DWORD getWindowRegionData( HWND hwnd, DWORD size, RGNDATA NEAR * prd )
|
|
{
|
|
HDC hdc;
|
|
DWORD dw;
|
|
|
|
hdc = GetDCEx( hwnd, NULL, DCX_USESTYLE | DCX_CACHE );
|
|
dw = GetRegionData( InquireVisRgn( hdc ), size, prd );
|
|
ReleaseDC( hwnd, hdc );
|
|
return dw;
|
|
|
|
} /* getWindowRegionData */
|
|
|
|
/*
|
|
* DD16_WWGetClipList
|
|
*/
|
|
DWORD DDAPI DD16_WWGetClipList(
|
|
LPWINWATCH pww,
|
|
LPRECT prect,
|
|
DWORD rdsize,
|
|
LPRGNDATA prd )
|
|
{
|
|
DWORD dw;
|
|
DWORD size;
|
|
|
|
/*
|
|
* we have to see if the intersect rect has changed.
|
|
*/
|
|
if( prect )
|
|
{
|
|
if( !EqualRect(prect, &pww->rect) )
|
|
{
|
|
pww->fDirty = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !IsRectEmpty( &pww->rect ) )
|
|
{
|
|
pww->fDirty = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if we are not dirty just return the saved RGNDATA
|
|
*/
|
|
if( !pww->fDirty && pww->prd16 )
|
|
{
|
|
size = sizeof( *prd ) + (WORD) pww->prd16->rdh.nRgnSize;
|
|
if( prd == NULL )
|
|
{
|
|
return size;
|
|
}
|
|
if( rdsize < size )
|
|
{
|
|
size = rdsize;
|
|
}
|
|
_fmemcpy( prd, pww->prd16, (UINT) size );
|
|
return size;
|
|
}
|
|
|
|
/*
|
|
* get the RGNDATA, growing the memory if we have to
|
|
*/
|
|
dw = getWindowRegionData( (HWND) pww->hWnd, pww->dwRDSize, pww->prd16 );
|
|
|
|
if( dw > pww->dwRDSize )
|
|
{
|
|
DPF( 2, "GetClipList: growing RGNDATA memory from %ld to %ld",pww->dwRDSize, dw);
|
|
|
|
if( pww->prd16 != NULL )
|
|
{
|
|
LocalFree((HLOCAL)pww->prd16);
|
|
}
|
|
|
|
/*
|
|
* allocate new space plus some slop
|
|
*/
|
|
pww->dwRDSize = dw + 8*sizeof(RECTL);
|
|
pww->prd16 = (RGNDATA NEAR *) LocalAlloc(LPTR, (UINT)pww->dwRDSize);
|
|
|
|
if( pww->prd16 == NULL )
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
dw = getWindowRegionData( (HWND) pww->hWnd, pww->dwRDSize, pww->prd16 );
|
|
|
|
if( dw > pww->dwRDSize )
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* now intersect the region with the passed rect
|
|
*/
|
|
if( prect )
|
|
{
|
|
pww->rect = *prect;
|
|
|
|
DPF( 2, "GetClipList: intersect with [%d %d %d %d]", *prect);
|
|
ClipRgnToRect( (HWND) pww->hWnd, prect, pww->prd16 );
|
|
}
|
|
else
|
|
{
|
|
SetRectEmpty( &pww->rect );
|
|
}
|
|
|
|
pww->fDirty = FALSE;
|
|
|
|
size = sizeof( *prd ) + (WORD) pww->prd16->rdh.nRgnSize;
|
|
if( prd == NULL )
|
|
{
|
|
return size;
|
|
}
|
|
if( rdsize < size )
|
|
{
|
|
size = rdsize;
|
|
}
|
|
_fmemcpy( prd, pww->prd16, (UINT) size );
|
|
return size;
|
|
|
|
error:
|
|
pww->dwRDSize = 0;
|
|
return 0;
|
|
|
|
} /* DD16_WWGetClipList */
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* ROUTINES TO HANDLE NOTIFICATION MESSAGES FOLLOW *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* handleWindowDestroyed
|
|
*/
|
|
static void handleWindowDestroy( HWND hwnd )
|
|
{
|
|
LPWINWATCH pww;
|
|
|
|
DPF( 2, "*** handleWindowDestroy: hwnd=%08lx", hwnd );
|
|
|
|
again:
|
|
for( pww=lpWWList; pww; pww=pww->next16 )
|
|
{
|
|
if( (hwnd == NULL) || ((HWND)pww->hWnd == hwnd) )
|
|
{
|
|
extern void DDAPI DD32_WWClose( DWORD );
|
|
|
|
doNotify( pww, WINWATCHNOTIFY_DESTROY );
|
|
DD32_WWClose( (DWORD) pww->self32 );
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
} /* handleWindowDestroy */
|
|
|
|
/*
|
|
* handleWindowPosChanged
|
|
*/
|
|
static void handleWindowPosChanged( HWND hwnd )
|
|
{
|
|
LPWINWATCH pww;
|
|
LPWINWATCH next;
|
|
RECT rect;
|
|
RECT rectT;
|
|
|
|
DPF( 20, "*** handleWindowPosChanged: hwnd=%08lx", hwnd );
|
|
|
|
/*
|
|
* get the screen rect that changed
|
|
*/
|
|
GetWindowRect( hwnd, &rect );
|
|
|
|
/*
|
|
* send message to each notify routine
|
|
*/
|
|
pww = lpWWList;
|
|
while( pww != NULL )
|
|
{
|
|
next = pww->next16;
|
|
|
|
GetWindowRect((HWND)pww->hWnd, &rectT);
|
|
|
|
if( IntersectRect( &rectT, &rectT, &rect ) )
|
|
{
|
|
pww->fNotify = TRUE;
|
|
pww->fDirty = TRUE;
|
|
}
|
|
|
|
if( pww->fNotify && pww->lpCallback )
|
|
{
|
|
DPF( 20, "clip changed %04X [%d %d %d %d]", (HWND)pww->hWnd, rectT);
|
|
doNotify( pww, WINWATCHNOTIFY_CHANGED );
|
|
pww->fNotify = FALSE;
|
|
}
|
|
pww = next;
|
|
}
|
|
|
|
} /* handleWindowPosChanged */
|
|
|
|
/*
|
|
* sendChanging
|
|
*/
|
|
static void sendChanging( LPRECT prect )
|
|
{
|
|
LPWINWATCH pww;
|
|
LPWINWATCH next;
|
|
RECT rectT;
|
|
|
|
pww = lpWWList;
|
|
while( pww != NULL )
|
|
{
|
|
next = pww->next16;
|
|
|
|
GetWindowRect( (HWND)pww->hWnd, &rectT );
|
|
|
|
if( IntersectRect(&rectT, &rectT, prect) )
|
|
{
|
|
pww->fDirty = TRUE;
|
|
|
|
if( pww->lpCallback )
|
|
{
|
|
DPF( 20, "clip changing %04X [%d %d %d %d]", (HWND)pww->hWnd, rectT);
|
|
doNotify( pww, WINWATCHNOTIFY_CHANGING );
|
|
pww->fNotify = TRUE;
|
|
pww->fDirty = TRUE;
|
|
}
|
|
}
|
|
|
|
pww = next;
|
|
}
|
|
|
|
} /* sendChanging */
|
|
|
|
/*
|
|
* handleWindowPosChanging
|
|
*/
|
|
static void handleWindowPosChanging( HWND hwnd, LPWINDOWPOS pwinpos )
|
|
{
|
|
RECT rect;
|
|
RECT rect_win;
|
|
int cx;
|
|
int cy;
|
|
|
|
/*
|
|
* get the current screen rect.
|
|
*/
|
|
DPF( 20, "*** handleWindowPosChanging: hwnd=%08lx", hwnd );
|
|
GetWindowRect( hwnd, &rect_win);
|
|
rect = rect_win;
|
|
|
|
if( pwinpos == NULL )
|
|
{
|
|
sendChanging( &rect );
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* compute the new rect
|
|
*/
|
|
if( pwinpos->flags & SWP_NOSIZE )
|
|
{
|
|
cx = rect.right - rect.left;
|
|
cy = rect.bottom - rect.top;
|
|
}
|
|
else
|
|
{
|
|
cx = pwinpos->cx;
|
|
cy = pwinpos->cy;
|
|
}
|
|
|
|
if( !(pwinpos->flags & SWP_NOMOVE) )
|
|
{
|
|
rect.left = pwinpos->x;
|
|
rect.top = pwinpos->y;
|
|
|
|
if( GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD )
|
|
{
|
|
ClientToScreen(GetParent(hwnd), (LPPOINT)&rect);
|
|
}
|
|
}
|
|
|
|
rect.right = rect.left + cx;
|
|
rect.bottom = rect.top + cy;
|
|
|
|
/*
|
|
* only send changing if we are really changing... if the new
|
|
* rect is the same as the old rect, then check if something else
|
|
* interesting is happening...
|
|
*/
|
|
if( EqualRect( &rect, &rect_win ) )
|
|
{
|
|
if( !(pwinpos->flags & SWP_NOZORDER) )
|
|
{
|
|
sendChanging(&rect);
|
|
}
|
|
|
|
if( pwinpos->flags & (SWP_SHOWWINDOW|SWP_HIDEWINDOW) )
|
|
{
|
|
sendChanging(&rect);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sendChanging( &rect_win );
|
|
sendChanging( &rect );
|
|
}
|
|
|
|
} /* handleWindowPosChanging */
|
|
|
|
/*
|
|
* checkScreenLock
|
|
*/
|
|
static void checkScreenLock( void )
|
|
{
|
|
static BOOL bScreenLocked;
|
|
BOOL is_locked;
|
|
HDC hdc;
|
|
RECT rect;
|
|
|
|
hdc = GetDC(NULL);
|
|
is_locked = (GetClipBox(hdc, &rect) == NULLREGION);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
if( is_locked != bScreenLocked )
|
|
{
|
|
/*
|
|
* pretend the desktop window has moved, this will cause
|
|
* all WINWATCH handles to be set to dirty, and also be notified.
|
|
*/
|
|
handleWindowPosChanging( GetDesktopWindow(), NULL );
|
|
handleWindowPosChanged( GetDesktopWindow() );
|
|
bScreenLocked = is_locked;
|
|
}
|
|
|
|
} /* checkScreenLock */
|
|
|
|
/*
|
|
* CallWndProcHook
|
|
*/
|
|
long FAR PASCAL _loadds CallWndProcHook( int hc, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
/* reversed MSG minus time and pt */
|
|
typedef struct
|
|
{
|
|
LONG lParam;
|
|
WORD wParam;
|
|
WORD message;
|
|
HWND hwnd;
|
|
} MSGR, FAR *LPMSGR;
|
|
|
|
LPMSGR lpmsg;
|
|
LPWINDOWPOS lpwinpos;
|
|
long rc;
|
|
|
|
if( hc == HC_ACTION )
|
|
{
|
|
lpmsg = (MSGR FAR *)lParam;
|
|
|
|
switch( lpmsg->message )
|
|
{
|
|
case WM_DESTROY:
|
|
handleWindowDestroy( lpmsg->hwnd );
|
|
break;
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
lpwinpos = (LPWINDOWPOS) lpmsg->lParam;
|
|
handleWindowPosChanging( lpwinpos->hwnd, lpwinpos );
|
|
break;
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
lpwinpos = (LPWINDOWPOS) lpmsg->lParam;
|
|
handleWindowPosChanged( lpwinpos->hwnd );
|
|
break;
|
|
|
|
case WM_EXITSIZEMOVE:
|
|
checkScreenLock();
|
|
break;
|
|
case WM_ENTERSIZEMOVE:
|
|
checkScreenLock();
|
|
break;
|
|
}
|
|
}
|
|
|
|
rc = DefHookProc(hc, wParam, lParam, &(HOOKPROC)hNextCallWndProc);
|
|
if( bUnHook )
|
|
{
|
|
DPF( 2, "Unhooking WindowsHook" );
|
|
UnhookWindowsHook( WH_CALLWNDPROC, (HOOKPROC)CallWndProcHook );
|
|
bUnHook = FALSE;
|
|
}
|
|
return rc;
|
|
|
|
} /* CallWndProcHook */
|
|
#endif
|