Added WIN_GetRectangles function.
Fixed WindowFromPoint to work accross processes.
This commit is contained in:
parent
2489dc901d
commit
5797fbb87e
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
173
windows/winpos.c
173
windows/winpos.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue