/*========================================================================= * * 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