Added WIN_GetRectangles function.

Fixed WindowFromPoint to work accross processes.
This commit is contained in:
Alexandre Julliard 2001-12-06 22:33:58 +00:00
parent 2489dc901d
commit 5797fbb87e
3 changed files with 113 additions and 107 deletions

View File

@ -92,6 +92,7 @@ extern void WIN_SetOwner( HWND hwnd, HWND owner );
extern LONG WIN_SetStyle( HWND hwnd, LONG style ); extern LONG WIN_SetStyle( HWND hwnd, LONG style );
extern LONG WIN_SetExStyle( HWND hwnd, LONG style ); extern LONG WIN_SetExStyle( HWND hwnd, LONG style );
extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient ); extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
extern BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient );
extern LRESULT WIN_DestroyWindow( HWND hwnd ); extern LRESULT WIN_DestroyWindow( HWND hwnd );
extern void WIN_DestroyThreadWindows( HWND hwnd ); extern void WIN_DestroyThreadWindows( HWND hwnd );
extern BOOL WIN_CreateDesktopWindow(void); extern BOOL WIN_CreateDesktopWindow(void);

View File

@ -568,6 +568,52 @@ void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClien
} }
/***********************************************************************
* WIN_GetRectangles
*
* Get the window and client rectangles.
*/
BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
{
WND *win = WIN_GetPtr( hwnd );
BOOL ret = TRUE;
if (!win) return FALSE;
if (win == WND_OTHER_PROCESS)
{
SERVER_START_REQ( get_window_rectangles )
{
req->handle = hwnd;
if ((ret = !wine_server_call( req )))
{
if (rectWindow)
{
rectWindow->left = reply->window.left;
rectWindow->top = reply->window.top;
rectWindow->right = reply->window.right;
rectWindow->bottom = reply->window.bottom;
}
if (rectClient)
{
rectClient->left = reply->client.left;
rectClient->top = reply->client.top;
rectClient->right = reply->client.right;
rectClient->bottom = reply->client.bottom;
}
}
}
SERVER_END_REQ;
}
else
{
if (rectWindow) *rectWindow = win->rectWindow;
if (rectClient) *rectClient = win->rectClient;
WIN_ReleasePtr( win );
}
return ret;
}
/*********************************************************************** /***********************************************************************
* WIN_DestroyWindow * WIN_DestroyWindow
* *

View File

@ -173,32 +173,7 @@ void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
*/ */
BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
{ {
BOOL ret; BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
WND *wndPtr = WIN_GetPtr( hwnd );
if (!wndPtr) return FALSE;
if (wndPtr != WND_OTHER_PROCESS)
{
*rect = wndPtr->rectWindow;
WIN_ReleasePtr( wndPtr );
ret = TRUE;
}
else
{
SERVER_START_REQ( get_window_rectangles )
{
req->handle = hwnd;
if ((ret = !wine_server_call_err( req )))
{
rect->left = reply->window.left;
rect->top = reply->window.top;
rect->right = reply->window.right;
rect->bottom = reply->window.bottom;
}
}
SERVER_END_REQ;
}
if (ret) if (ret)
{ {
MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 ); MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
@ -292,31 +267,14 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
{ {
BOOL ret; BOOL ret;
WND *wndPtr = WIN_GetPtr( hwnd );
rect->left = rect->top = rect->right = rect->bottom = 0; rect->right = rect->bottom = 0;
if (!wndPtr) return FALSE; if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
if (wndPtr != WND_OTHER_PROCESS)
{ {
rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left; rect->right -= rect->left;
rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top; rect->bottom -= rect->top;
WIN_ReleasePtr( wndPtr );
ret = TRUE;
}
else
{
SERVER_START_REQ( get_window_rectangles )
{
req->handle = hwnd;
if ((ret = !wine_server_call_err( req )))
{
rect->right = reply->client.right - reply->client.left;
rect->bottom = reply->client.bottom - reply->client.top;
}
}
SERVER_END_REQ;
} }
rect->left = rect->top = 0;
return ret; return ret;
} }
@ -351,57 +309,64 @@ BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam ) static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
{ {
int i, res; int i, res;
LONG style, exstyle;
RECT rectWindow, rectClient;
WND *wndPtr; WND *wndPtr;
HWND *list = WIN_ListChildren( parent ); HWND *list = WIN_ListChildren( parent );
if (!list) return 0; if (!list) return 0;
for (i = 0; list[i]; i++) for (i = 0; list[i]; i++)
{ {
if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
/* If point is in window, and window is visible, and it */ /* If point is in window, and window is visible, and it */
/* is enabled (or it's a top-level window), then explore */ /* is enabled (or it's a top-level window), then explore */
/* its children. Otherwise, go to the next window. */ /* its children. Otherwise, go to the next window. */
if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next; /* not visible -> skip */ style = GetWindowLongW( list[i], GWL_STYLE );
if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED)) if (!(style & WS_VISIBLE)) continue; /* not visible -> skip */
goto next; /* disabled child -> skip */ if ((style & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT)) continue; /* disabled child -> skip */
goto next; /* transparent -> skip */ exstyle = GetWindowLongW( list[i], GWL_EXSTYLE );
if (wndPtr->hrgnWnd) if ((exstyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
continue; /* transparent -> skip */
if (!WIN_GetRectangles( list[i], &rectWindow, &rectClient )) continue;
if (!PtInRect( &rectWindow, pt )) continue; /* not in window -> skip */
/* FIXME: check window region for other processes too */
if ((wndPtr = WIN_GetPtr( list[i] )) && wndPtr != WND_OTHER_PROCESS)
{ {
if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left, if (wndPtr->hrgnWnd && !PtInRegion( wndPtr->hrgnWnd,
pt.y - wndPtr->rectWindow.top )) pt.x - rectWindow.left, pt.y - rectWindow.top ))
goto next; /* point outside window region -> skip */ {
WIN_ReleasePtr( wndPtr );
continue; /* point outside window region -> skip */
}
WIN_ReleasePtr( wndPtr );
} }
else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */
/* If window is minimized or disabled, return at once */ /* If window is minimized or disabled, return at once */
if (wndPtr->dwStyle & WS_MINIMIZE) if (style & WS_MINIMIZE)
{ {
WIN_ReleaseWndPtr( wndPtr );
*hittest = HTCAPTION; *hittest = HTCAPTION;
return list[i]; return list[i];
} }
if (wndPtr->dwStyle & WS_DISABLED) if (style & WS_DISABLED)
{ {
WIN_ReleaseWndPtr( wndPtr );
*hittest = HTERROR; *hittest = HTERROR;
return list[i]; return list[i];
} }
/* If point is in client area, explore children */ /* If point is in client area, explore children */
if (PtInRect( &wndPtr->rectClient, pt )) if (PtInRect( &rectClient, pt ))
{ {
POINT new_pt; POINT new_pt;
HWND ret; HWND ret;
new_pt.x = pt.x - wndPtr->rectClient.left; new_pt.x = pt.x - rectClient.left;
new_pt.y = pt.y - wndPtr->rectClient.top; new_pt.y = pt.y - rectClient.top;
WIN_ReleaseWndPtr( wndPtr );
if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam ))) if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
return ret; return ret;
} }
else WIN_ReleaseWndPtr( wndPtr );
/* Now it's inside window, send WM_NCCHITTEST (if same thread) */ /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
if (!WIN_IsCurrentThread( list[i] )) if (!WIN_IsCurrentThread( list[i] ))
@ -414,10 +379,7 @@ static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM l
*hittest = res; /* Found the window */ *hittest = res; /* Found the window */
return list[i]; return list[i];
} }
continue; /* continue search with next sibling */ /* continue search with next sibling */
next:
WIN_ReleaseWndPtr( wndPtr );
} }
return 0; return 0;
} }
@ -430,40 +392,36 @@ static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM l
*/ */
HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
{ {
WND *wndScope;
POINT xy = pt; POINT xy = pt;
int res; int res;
LONG style;
TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y); TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
if (!hwndScope) hwndScope = GetDesktopWindow(); if (!hwndScope) hwndScope = GetDesktopWindow();
if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0; style = GetWindowLongW( hwndScope, GWL_STYLE );
hwndScope = wndScope->hwndSelf; /* make it a full handle */
*hittest = HTERROR; *hittest = HTERROR;
if( wndScope->dwStyle & WS_DISABLED ) if (style & WS_DISABLED) return 0;
MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope, GA_PARENT ), &xy, 1 );
if (!(style & WS_MINIMIZE))
{ {
WIN_ReleaseWndPtr(wndScope); RECT rectClient;
return 0; if (WIN_GetRectangles( hwndScope, NULL, &rectClient ) && PtInRect( &rectClient, xy ))
}
if (wndScope->parent)
MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
{
HWND ret;
xy.x -= wndScope->rectClient.left;
xy.y -= wndScope->rectClient.top;
WIN_ReleaseWndPtr( wndScope );
if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
{ {
TRACE( "found child %x\n", ret ); HWND ret;
return ret;
xy.x -= rectClient.left;
xy.y -= rectClient.top;
if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
{
TRACE( "found child %x\n", ret );
return ret;
}
} }
} }
else WIN_ReleaseWndPtr( wndScope );
/* If nothing found, try the scope window */ /* If nothing found, try the scope window */
if (!WIN_IsCurrentThread( hwndScope )) if (!WIN_IsCurrentThread( hwndScope ))
@ -512,28 +470,29 @@ HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
HWND *list; HWND *list;
int i; int i;
RECT rect; RECT rect;
HWND retvalue = 0; HWND retvalue;
GetClientRect( hwndParent, &rect ); GetClientRect( hwndParent, &rect );
if (!PtInRect( &rect, pt )) return 0; if (!PtInRect( &rect, pt )) return 0;
if (!(list = WIN_ListChildren( hwndParent ))) return 0; if (!(list = WIN_ListChildren( hwndParent ))) return 0;
for (i = 0; list[i] && !retvalue; i++) for (i = 0; list[i]; i++)
{ {
WND *wnd = WIN_FindWndPtr( list[i] ); if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
if (!wnd) continue; if (!PtInRect( &rect, pt )) continue;
if (PtInRect( &wnd->rectWindow, pt )) if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
{ {
if ( (uFlags & CWP_SKIPINVISIBLE) && LONG style = GetWindowLongW( list[i], GWL_STYLE );
!(wnd->dwStyle & WS_VISIBLE) ); if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
else if ( (uFlags & CWP_SKIPDISABLED) && if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
(wnd->dwStyle & WS_DISABLED) );
else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
(wnd->dwExStyle & WS_EX_TRANSPARENT) );
else retvalue = list[i];
} }
WIN_ReleaseWndPtr( wnd ); if (uFlags & CWP_SKIPTRANSPARENT)
{
if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
}
break;
} }
retvalue = list[i];
HeapFree( GetProcessHeap(), 0, list ); HeapFree( GetProcessHeap(), 0, list );
if (!retvalue) retvalue = hwndParent; if (!retvalue) retvalue = hwndParent;
return retvalue; return retvalue;