Added internal Wine messages to perform SetWindowPos, ShowWindow and SetParent in the correct thread. Replace QUEUE_IsExitingQueue by USER_IsExitingThread. Store window rectangles in the server. Prevent DestroyWindow on windows not belonging to the current thread.
diff --git a/windows/winpos.c b/windows/winpos.c index 1969780..64e11fe 100644 --- a/windows/winpos.c +++ b/windows/winpos.c
@@ -11,6 +11,7 @@ #include "wingdi.h" #include "winerror.h" #include "wine/winuser16.h" +#include "wine/server.h" #include "controls.h" #include "user.h" #include "region.h" @@ -83,7 +84,9 @@ { LPINTERNALPOS lpPos; MESSAGEQUEUE *pMsgQ = 0; - WND *wndPtr = WIN_FindWndPtr( hwnd ); + WND *wndPtr = WIN_GetPtr( hwnd ); + + if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return; lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos ); @@ -92,7 +95,7 @@ if ( !pMsgQ ) { WARN("\tMessage queue not found. Exiting!\n" ); - WIN_ReleaseWndPtr( wndPtr ); + WIN_ReleasePtr( wndPtr ); return; } @@ -112,8 +115,7 @@ } QUEUE_Unlock( pMsgQ ); - WIN_ReleaseWndPtr( wndPtr ); - return; + WIN_ReleasePtr( wndPtr ); } /*********************************************************************** @@ -169,16 +171,41 @@ /*********************************************************************** * GetWindowRect (USER32.@) */ -BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) +BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) { - WND * wndPtr = WIN_FindWndPtr( hwnd ); + BOOL ret; + WND *wndPtr = WIN_GetPtr( hwnd ); + if (!wndPtr) return FALSE; - *rect = wndPtr->rectWindow; - WIN_ReleaseWndPtr(wndPtr); - MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 ); - TRACE("hwnd %04x (%d,%d)-(%d,%d)\n", - hwnd, rect->left, rect->top, rect->right, rect->bottom); - return TRUE; + + 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 = !SERVER_CALL_ERR())) + { + rect->left = req->window.left; + rect->top = req->window.top; + rect->right = req->window.right; + rect->bottom = req->window.bottom; + } + } + SERVER_END_REQ; + } + if (ret) + { + MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 ); + TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n", + hwnd, rect->left, rect->top, rect->right, rect->bottom); + } + return ret; } @@ -246,19 +273,35 @@ /*********************************************************************** * GetClientRect (USER32.@) */ -BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) +BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) { - WND * wndPtr = WIN_FindWndPtr( hwnd ); + BOOL ret; + WND *wndPtr = WIN_GetPtr( hwnd ); rect->left = rect->top = rect->right = rect->bottom = 0; if (!wndPtr) return FALSE; - rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left; - rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top; - WIN_ReleaseWndPtr(wndPtr); - TRACE("hwnd %04x (%d,%d)-(%d,%d)\n", - hwnd, rect->left, rect->top, rect->right, rect->bottom); - return TRUE; + if (wndPtr != WND_OTHER_PROCESS) + { + rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left; + rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top; + WIN_ReleasePtr( wndPtr ); + ret = TRUE; + } + else + { + SERVER_START_REQ( get_window_rectangles ) + { + req->handle = hwnd; + if ((ret = !SERVER_CALL_ERR())) + { + rect->right = req->client.right - req->client.left; + rect->bottom = req->client.bottom - req->client.top; + } + } + SERVER_END_REQ; + } + return ret; } @@ -316,8 +359,6 @@ } else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */ - TRACE( "%ld,%ld is inside %04x\n", pt.x, pt.y, list[i] ); - /* If window is minimized or disabled, return at once */ if (wndPtr->dwStyle & WS_MINIMIZE) { @@ -401,7 +442,10 @@ 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 ); return ret; + } } else WIN_ReleaseWndPtr( wndScope ); @@ -409,15 +453,18 @@ if (!WIN_IsCurrentThread( hwndScope )) { *hittest = HTCLIENT; + TRACE( "returning %x\n", hwndScope ); return hwndScope; } res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) ); if (res != HTTRANSPARENT) { *hittest = res; /* Found the window */ + TRACE( "returning %x\n", hwndScope ); return hwndScope; } *hittest = HTNOWHERE; + TRACE( "nothing found\n" ); return 0; } @@ -483,59 +530,67 @@ * Calculate the offset between the origin of the two windows. Used * to implement MapWindowPoints. */ -static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, - POINT *offset ) +static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset ) { - WND * wndPtr = 0; - HWND *list; - int i; + WND * wndPtr; offset->x = offset->y = 0; - if (hwndFrom == hwndTo ) return; - /* Translate source window origin to screen coords */ + /* Translate source window origin to screen coords */ if (hwndFrom) { - if (!(wndPtr = WIN_FindWndPtr( hwndFrom ))) + HWND hwnd = hwndFrom; + + while (hwnd) { - ERR("bad hwndFrom = %04x\n",hwndFrom); - return; - } - if ((list = WIN_ListParents( hwndFrom ))) - { - for (i = 0; list[i]; i++) + if (hwnd == hwndTo) return; + if (!(wndPtr = WIN_GetPtr( hwnd ))) { - offset->x += wndPtr->rectClient.left; - offset->y += wndPtr->rectClient.top; - WIN_ReleaseWndPtr( wndPtr ); - if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break; + ERR( "bad hwndFrom = %04x\n", hwnd ); + return; } - HeapFree( GetProcessHeap(), 0, list ); + if (wndPtr == WND_OTHER_PROCESS) goto other_process; + offset->x += wndPtr->rectClient.left; + offset->y += wndPtr->rectClient.top; + hwnd = wndPtr->parent; + WIN_ReleasePtr( wndPtr ); } - WIN_ReleaseWndPtr(wndPtr); } - /* Translate origin to destination window coords */ + /* Translate origin to destination window coords */ if (hwndTo) { - if (!(wndPtr = WIN_FindWndPtr( hwndTo ))) + HWND hwnd = hwndTo; + + while (hwnd) { - ERR("bad hwndTo = %04x\n", hwndTo ); - return; - } - if ((list = WIN_ListParents( hwndTo ))) - { - for (i = 0; list[i]; i++) + if (!(wndPtr = WIN_GetPtr( hwnd ))) { - offset->x -= wndPtr->rectClient.left; - offset->y -= wndPtr->rectClient.top; - WIN_ReleaseWndPtr( wndPtr ); - if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break; + ERR( "bad hwndTo = %04x\n", hwnd ); + return; } - HeapFree( GetProcessHeap(), 0, list ); + if (wndPtr == WND_OTHER_PROCESS) goto other_process; + offset->x -= wndPtr->rectClient.left; + offset->y -= wndPtr->rectClient.top; + hwnd = wndPtr->parent; + WIN_ReleasePtr( wndPtr ); } - WIN_ReleaseWndPtr(wndPtr); } + return; + + other_process: /* one of the parents may belong to another process, do it the hard way */ + offset->x = offset->y = 0; + SERVER_START_REQ( get_windows_offset ) + { + req->from = hwndFrom; + req->to = hwndTo; + if (!SERVER_CALL()) + { + offset->x = req->x; + offset->y = req->y; + } + } + SERVER_END_REQ; } @@ -560,12 +615,11 @@ /******************************************************************* * MapWindowPoints (USER32.@) */ -INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, - LPPOINT lppt, UINT count ) +INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count ) { POINT offset; - WINPOS_GetWinOffset( WIN_GetFullHandle(hwndFrom), WIN_GetFullHandle(hwndTo), &offset ); + WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset ); while (count--) { lppt->x += offset.x; @@ -581,12 +635,7 @@ */ BOOL WINAPI IsIconic(HWND hWnd) { - BOOL retvalue; - WND * wndPtr = WIN_FindWndPtr(hWnd); - if (wndPtr == NULL) return FALSE; - retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0; - WIN_ReleaseWndPtr(wndPtr); - return retvalue; + return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0; } @@ -595,12 +644,7 @@ */ BOOL WINAPI IsZoomed(HWND hWnd) { - BOOL retvalue; - WND * wndPtr = WIN_FindWndPtr(hWnd); - if (wndPtr == NULL) return FALSE; - retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0; - WIN_ReleaseWndPtr(wndPtr); - return retvalue; + return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; } @@ -780,8 +824,7 @@ /*********************************************************************** * WINPOS_InitInternalPos */ -static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, - LPRECT restoreRect ) +static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect ) { LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf, atomInternalPos ); @@ -948,7 +991,11 @@ */ BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) { - return USER_Driver.pShowWindow( hwnd, cmd ); + HWND full_handle; + + if ((full_handle = WIN_IsCurrentThread( hwnd ))) + return USER_Driver.pShowWindow( full_handle, cmd ); + return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); } @@ -1360,7 +1407,6 @@ BOOL WINPOS_ActivateOtherWindow(HWND hwnd) { BOOL bRet = 0; - WND *pWnd; HWND hwndActive = 0; HWND hwndTo = 0; HWND owner; @@ -1376,21 +1422,16 @@ } } - pWnd = WIN_FindWndPtr( hwnd ); - hwnd = pWnd->hwndSelf; + if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return 0; if( hwnd == hwndPrevActive ) hwndPrevActive = 0; - if( hwndActive != hwnd && - ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) ) - { - WIN_ReleaseWndPtr( pWnd ); + if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() ))) return 0; - } - owner = GetWindow( hwnd, GW_OWNER ); - if( !(pWnd->dwStyle & WS_POPUP) || !owner || + if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) || + !(owner = GetWindow( hwnd, GW_OWNER )) || !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) ) { HWND tmp = GetAncestor( hwnd, GA_ROOT ); @@ -1403,7 +1444,6 @@ if( !hwndTo ) break; } } - WIN_ReleaseWndPtr( pWnd ); bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE ); @@ -1452,45 +1492,6 @@ /*********************************************************************** - * WINPOS_SendNCCalcSize - * - * Send a WM_NCCALCSIZE message to a window. - * All parameters are read-only except newClientRect. - * oldWindowRect, oldClientRect and winpos must be non-NULL only - * when calcValidRect is TRUE. - */ -LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect, - RECT *newWindowRect, RECT *oldWindowRect, - RECT *oldClientRect, WINDOWPOS *winpos, - RECT *newClientRect ) -{ - NCCALCSIZE_PARAMS params; - WINDOWPOS winposCopy; - LONG result; - - params.rgrc[0] = *newWindowRect; - if (calcValidRect) - { - winposCopy = *winpos; - params.rgrc[1] = *oldWindowRect; - params.rgrc[2] = *oldClientRect; - params.lppos = &winposCopy; - } - result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect, - (LPARAM)¶ms ); - TRACE("%d,%d-%d,%d\n", - params.rgrc[0].left, params.rgrc[0].top, - params.rgrc[0].right, params.rgrc[0].bottom ); - - /* If the application send back garbage, ignore it */ - if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom) - *newClientRect = params.rgrc[0]; - - return result; -} - - -/*********************************************************************** * WINPOS_HandleWindowPosChanging16 * * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc(). @@ -1557,7 +1558,8 @@ winpos.cx = cx; winpos.cy = cy; winpos.flags = flags; - return USER_Driver.pSetWindowPos( &winpos ); + if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos ); + return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos ); } @@ -1599,31 +1601,13 @@ DWP *pDWP; int i; HDWP newhdwp = hdwp,retvalue; - /* HWND parent; */ - WND *pWnd; hwnd = WIN_GetFullHandle( hwnd ); if (hwnd == GetDesktopWindow()) return 0; if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0; - if (!(pWnd = WIN_FindWndPtr( hwnd ))) return 0; - -/* Numega Bounds Checker Demo dislikes the following code. - In fact, I've not been able to find any "same parent" requirement in any docu - [AM 980509] - */ -#if 0 - /* All the windows of a DeferWindowPos() must have the same parent */ - parent = pWnd->parent->hwndSelf; - if (pDWP->actualCount == 0) pDWP->hwndParent = parent; - else if (parent != pDWP->hwndParent) - { - USER_HEAP_FREE( hdwp ); - retvalue = 0; - goto END; - } -#endif + USER_Lock(); for (i = 0; i < pDWP->actualCount; i++) { @@ -1638,7 +1622,7 @@ { pDWP->winPos[i].x = x; pDWP->winPos[i].y = y; - } + } if (!(flags & SWP_NOSIZE)) { pDWP->winPos[i].cx = cx; @@ -1676,7 +1660,7 @@ pDWP->actualCount++; retvalue = newhdwp; END: - WIN_ReleaseWndPtr(pWnd); + USER_Unlock(); return retvalue; }