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.
This commit is contained in:
Alexandre Julliard 2001-10-16 21:58:58 +00:00
parent 0d50965a13
commit fb0ff053c0
16 changed files with 659 additions and 545 deletions

View File

@ -43,7 +43,6 @@ const struct builtin_class_descr ICONTITLE_builtin_class =
*/
HWND ICONTITLE_Create( HWND owner )
{
WND* wndPtr;
HWND hWnd;
HINSTANCE instance = GetWindowLongA( owner, GWL_HINSTANCE );
LONG style = WS_CLIPSIBLINGS;
@ -57,10 +56,9 @@ HWND ICONTITLE_Create( HWND owner )
hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
style, 0, 0, 1, 1,
owner, 0, instance, NULL );
if (!(wndPtr = WIN_GetPtr( hWnd ))) return 0;
wndPtr->owner = owner; /* MDI depends on this */
wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
WIN_ReleasePtr(wndPtr);
WIN_SetOwner( hWnd, owner ); /* MDI depends on this */
SetWindowLongW( hWnd, GWL_STYLE,
GetWindowLongW( hWnd, GWL_STYLE ) & ~(WS_CAPTION | WS_BORDER) );
return hWnd;
}

View File

@ -566,9 +566,36 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
/* Send WM_NCCALCSIZE message to get new client area */
if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
{
WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
winpos, &newClientRect );
NCCALCSIZE_PARAMS params;
WINDOWPOS winposCopy;
params.rgrc[0] = newWindowRect;
params.rgrc[1] = wndPtr->rectWindow;
params.rgrc[2] = wndPtr->rectClient;
params.lppos = &winposCopy;
winposCopy = *winpos;
SendMessageW( winpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
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];
/* FIXME: WVR_ALIGNxxx */
if( newClientRect.left != wndPtr->rectClient.left ||
newClientRect.top != wndPtr->rectClient.top )
winpos->flags &= ~SWP_NOCLIENTMOVE;
if( (newClientRect.right - newClientRect.left !=
wndPtr->rectClient.right - wndPtr->rectClient.left) ||
(newClientRect.bottom - newClientRect.top !=
wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
winpos->flags &= ~SWP_NOCLIENTSIZE;
}
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
@ -579,8 +606,7 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
/* FIXME: actually do something with WVR_VALIDRECTS */
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
if( winpos->flags & SWP_SHOWWINDOW )
{

View File

@ -533,6 +533,10 @@ static size_t pack_message( HWND hwnd, UINT message, WPARAM wparam, LPARAM lpara
if (lparam) return sizeof(BOOL);
return 0;
case WM_WINE_SETWINDOWPOS:
push_data( data, (WINDOWPOS *)lparam, sizeof(WINDOWPOS) );
return 0;
/* these contain an HFONT */
case WM_SETFONT:
case WM_GETFONT:
@ -644,6 +648,7 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
break;
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
case WM_WINE_SETWINDOWPOS:
minsize = sizeof(WINDOWPOS);
break;
case WM_COPYDATA:
@ -1072,6 +1077,30 @@ static void reply_message( struct received_message_info *info, LRESULT result, B
}
/***********************************************************************
* handle_internal_message
*
* Handle an internal Wine message instead of calling the window proc.
*/
static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch(msg)
{
case WM_WINE_SETWINDOWPOS:
return USER_Driver.pSetWindowPos( (WINDOWPOS *)lparam );
case WM_WINE_SHOWWINDOW:
return USER_Driver.pShowWindow( hwnd, wparam );
case WM_WINE_DESTROYWINDOW:
return WIN_DestroyWindow( hwnd );
case WM_WINE_SETPARENT:
return (LRESULT)WIN_SetParent( hwnd, (HWND)wparam );
default:
FIXME( "unknown internal message %x\n", msg );
return 0;
}
}
/***********************************************************************
* call_window_proc
*
@ -1082,7 +1111,7 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
LRESULT result;
WNDPROC winproc;
/* FIXME: should check for exiting queue */
if (msg & 0x80000000) return handle_internal_message( hwnd, msg, wparam, lparam );
/* first the WH_CALLWNDPROC hook */
if (HOOK_IsHooked( WH_CALLWNDPROC ))
@ -1308,8 +1337,6 @@ static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info
unsigned int res;
int timeout = -1;
/* FIXME: should check for exiting queue */
if (info->type != MSG_NOTIFY &&
info->type != MSG_CALLBACK &&
info->type != MSG_POSTED &&
@ -1489,7 +1516,9 @@ LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
if (USER_IsExitingThread( dest_tid )) return 0;
if (dest_tid == GetCurrentThreadId())
{
@ -1535,7 +1564,9 @@ LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
if (USER_IsExitingThread( dest_tid )) return 0;
if (dest_tid == GetCurrentThreadId())
{
@ -1624,7 +1655,9 @@ BOOL WINAPI SendNotifyMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
return TRUE;
}
dest_tid = GetWindowThreadProcessId( hwnd, NULL );
if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
if (USER_IsExitingThread( dest_tid )) return TRUE;
if (dest_tid == GetCurrentThreadId())
{
@ -1676,7 +1709,9 @@ BOOL WINAPI SendMessageCallbackW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa
return TRUE;
}
dest_tid = GetWindowThreadProcessId( hwnd, NULL );
if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
if (USER_IsExitingThread( dest_tid )) return TRUE;
if (dest_tid == GetCurrentThreadId())
{
@ -1740,6 +1775,7 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
BOOL WINAPI PostMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
struct send_message_info info;
DWORD dest_tid;
if (is_pointer_message( msg ))
{
@ -1758,7 +1794,11 @@ BOOL WINAPI PostMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
EnumWindows( broadcast_message_callback, (LPARAM)&info );
return TRUE;
}
return put_message_in_queue( GetWindowThreadProcessId( hwnd, NULL ), &info, NULL );
if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
if (USER_IsExitingThread( dest_tid )) return TRUE;
return put_message_in_queue( dest_tid, &info, NULL );
}
@ -1783,6 +1823,7 @@ BOOL WINAPI PostThreadMessageW( DWORD thread, UINT msg, WPARAM wparam, LPARAM lp
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (USER_IsExitingThread( thread )) return TRUE;
info.type = MSG_POSTED;
info.hwnd = 0;

View File

@ -34,8 +34,10 @@ WINE_LOOK TWEAK_WineLook = WIN31_LOOK;
WORD USER_HeapSel = 0; /* USER heap selector */
static HMODULE graphics_driver;
static DWORD exiting_thread_id;
extern void COMM_Init(void);
extern void WDML_NotifyThreadDetach(void);
#define GET_USER_FUNC(name) USER_Driver.p##name = (void*)GetProcAddress( graphics_driver, #name )
@ -257,20 +259,29 @@ static BOOL process_attach(void)
/**********************************************************************
* thread
* USER_IsExitingThread
*/
BOOL USER_IsExitingThread( DWORD tid )
{
return (tid == exiting_thread_id);
}
/**********************************************************************
* thread_detach
*/
static void thread_detach(void)
{
HQUEUE16 hQueue = GetThreadQueue16( 0 );
extern void WDML_NotifyThreadDetach(void);
exiting_thread_id = GetCurrentThreadId();
WDML_NotifyThreadDetach();
if (hQueue)
{
TIMER_RemoveQueueTimers( hQueue );
HOOK_FreeQueueHooks();
QUEUE_SetExitingQueue( hQueue );
WIN_DestroyThreadWindows( GetDesktopWindow() );
QUEUE_DeleteMsgQueue();
}
@ -290,6 +301,7 @@ static void thread_detach(void)
CURSORICON_FreeModuleIcons( hModule );
}
}
exiting_thread_id = 0;
}

View File

@ -872,7 +872,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
rect = wndPtr->rectWindow;
SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
wndPtr->rectClient = rect;
WIN_SetRectangles( hwnd, &wndPtr->rectWindow, &rect );
X11DRV_sync_client_window_position( display, wndPtr );
X11DRV_register_window( display, hwnd, data );
@ -1005,18 +1005,14 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
{
Display *display = thread_display();
WND *wndPtr;
DWORD dwStyle;
HWND retvalue;
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
dwStyle = wndPtr->dwStyle;
if (!parent) parent = GetDesktopWindow();
/* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all */
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
BOOL was_visible = ShowWindow( hwnd, SW_HIDE );
if (!IsWindow( parent )) return 0;
if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
retvalue = wndPtr->parent; /* old parent */
if (parent != retvalue)
@ -1027,7 +1023,7 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
if (parent != GetDesktopWindow()) /* a child window */
{
if (!(dwStyle & WS_CHILD))
if (!(wndPtr->dwStyle & WS_CHILD))
{
HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
if (menu) DestroyMenu( menu );
@ -1041,15 +1037,14 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
data->whole_rect.left, data->whole_rect.top );
wine_tsx11_unlock();
}
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleasePtr( wndPtr );
/* SetParent additionally needs to make hwnd the topmost window
in the x-order and send the expected WM_WINDOWPOSCHANGING and
WM_WINDOWPOSCHANGED notification messages.
*/
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */

View File

@ -523,7 +523,7 @@ static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT
if (!(pWinpos->flags & SWP_NOSENDCHANGING))
SendMessageA( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
if (!(wndPtr = WIN_FindWndPtr( pWinpos->hwnd ))) return FALSE;
if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return FALSE;
/* Calculate new position and size */
@ -547,26 +547,47 @@ static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT
pWinpos->y - wndPtr->rectWindow.top );
}
pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleasePtr( wndPtr );
return TRUE;
}
/***********************************************************************
* SWP_DoNCCalcSize
*/
static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
RECT* pNewWindowRect, RECT* pNewClientRect )
static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
{
UINT wvrFlags = 0;
WND *wndPtr;
if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
/* Send WM_NCCALCSIZE message to get new client area */
if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
{
wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
pWinpos, pNewClientRect );
NCCALCSIZE_PARAMS params;
WINDOWPOS winposCopy;
params.rgrc[0] = *pNewWindowRect;
params.rgrc[1] = wndPtr->rectWindow;
params.rgrc[2] = wndPtr->rectClient;
params.lppos = &winposCopy;
winposCopy = *pWinpos;
WIN_ReleasePtr( wndPtr );
wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
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)
*pNewClientRect = params.rgrc[0];
/* FIXME: WVR_ALIGNxxx */
if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
if( pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top )
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
@ -578,12 +599,17 @@ static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
pWinpos->flags &= ~SWP_NOCLIENTSIZE;
}
else
if( !(pWinpos->flags & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top) )
{
if (!(pWinpos->flags & SWP_NOMOVE) &&
(pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top))
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
}
WIN_ReleasePtr( wndPtr );
return wvrFlags;
}
/***********************************************************************
* SWP_DoOwnedPopups
*
@ -783,7 +809,7 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
/* Common operations */
wvrFlags = SWP_DoNCCalcSize( wndPtr, winpos, &newWindowRect, &newClientRect );
wvrFlags = SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect );
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
{
@ -816,8 +842,7 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
/* FIXME: actually do something with WVR_VALIDRECTS */
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE;
else if (winpos->flags & SWP_HIDEWINDOW)
@ -993,7 +1018,7 @@ static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt )
UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
WND *wndPtr;
UINT swpFlags = 0;
POINT size;
WINDOWPLACEMENT wpl;
@ -1003,20 +1028,21 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
wpl.length = sizeof(wpl);
GetWindowPlacement( hwnd, &wpl );
if (HOOK_CallHooksA( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd ))
return SWP_NOSIZE | SWP_NOMOVE;
if (IsIconic( hwnd ))
{
if (cmd == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
if (!SendMessageA( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
swpFlags |= SWP_NOCOPYBITS;
}
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
size.x = wndPtr->rectWindow.left;
size.y = wndPtr->rectWindow.top;
if (!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, (WPARAM)wndPtr->hwndSelf, cmd))
{
if( wndPtr->dwStyle & WS_MINIMIZE )
{
if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
{
swpFlags = SWP_NOSIZE | SWP_NOMOVE;
goto done;
}
swpFlags |= SWP_NOCOPYBITS;
}
switch( cmd )
{
case SW_MINIMIZE:
@ -1069,12 +1095,10 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
}
}
else
if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
{
swpFlags = (UINT16)(-1);
goto done;
if (!(wndPtr->dwStyle & WS_MAXIMIZE)) break;
wndPtr->dwStyle &= ~WS_MAXIMIZE;
}
else wndPtr->dwStyle &= ~WS_MAXIMIZE;
/* Restore to normal position */
@ -1084,9 +1108,7 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
break;
}
} else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
done:
WIN_ReleaseWndPtr( wndPtr );
return swpFlags;
}

View File

@ -69,8 +69,6 @@ HWND PERQDATA_SetCaptureWnd( HWND hWndCapture, INT hittest );
extern MESSAGEQUEUE *QUEUE_Current(void);
extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_DeleteMsgQueue(void);
#endif /* __WINE_QUEUE_H */

View File

@ -35,7 +35,14 @@ struct DIDEVICEOBJECTDATA;
typedef VOID CALLBACK (*LPMOUSE_EVENT_PROC)(DWORD,DWORD,DWORD,DWORD,DWORD);
struct tagWND;
/* internal messages codes */
enum wine_internal_message
{
WM_WINE_DESTROYWINDOW = 0x80000000,
WM_WINE_SETWINDOWPOS,
WM_WINE_SHOWWINDOW,
WM_WINE_SETPARENT
};
typedef struct tagUSER_DRIVER {
/* keyboard functions */
@ -99,6 +106,8 @@ extern void USER_Lock(void);
extern void USER_Unlock(void);
extern void USER_CheckNotLock(void);
extern BOOL USER_IsExitingThread( DWORD tid );
VOID WINAPI MOUSE_Enable(LPMOUSE_EVENT_PROC lpMouseEventProc);
VOID WINAPI MOUSE_Disable(VOID);

View File

@ -88,12 +88,16 @@ extern HWND WIN_IsCurrentProcess( HWND hwnd );
extern HWND WIN_IsCurrentThread( HWND hwnd );
extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
extern void WIN_UnlinkWindow( HWND hwnd );
extern void WIN_SetOwner( HWND hwnd, HWND owner );
extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
extern HWND WIN_FindWinToRepaint( HWND hwnd );
extern LRESULT WIN_DestroyWindow( HWND hwnd );
extern void WIN_DestroyThreadWindows( HWND hwnd );
extern BOOL WIN_CreateDesktopWindow(void);
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL );
extern HWND *WIN_ListParents( HWND hwnd );
extern HWND *WIN_ListChildren( HWND hwnd );
extern HWND WIN_SetParent( HWND hwnd, HWND parent );
extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
inline static HWND WIN_GetFullHandle( HWND hwnd )

View File

@ -28,10 +28,6 @@ extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos, POIN
extern BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse,
BOOL fChangeFocus );
extern BOOL WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg );
extern LONG WINPOS_SendNCCalcSize(HWND hwnd, BOOL calcValidRect,
RECT *newWindowRect, RECT *oldWindowRect,
RECT *oldClientRect, WINDOWPOS *winpos,
RECT *newClientRect );
extern LONG WINPOS_HandleWindowPosChanging16(HWND hwnd, struct tagWINDOWPOS16 *winpos);
extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos);
extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest );

View File

@ -144,11 +144,9 @@ DCE* DCE_FreeDCE( DCE *dce )
void DCE_FreeWindowDCE( HWND hwnd )
{
DCE *pDCE;
WND *pWnd = WIN_FindWndPtr( hwnd );
WND *pWnd = WIN_GetPtr( hwnd );
pDCE = firstDCE;
hwnd = pWnd->hwndSelf; /* make it a full handle */
while( pDCE )
{
if( pDCE->hwndCurrent == hwnd )
@ -189,8 +187,7 @@ void DCE_FreeWindowDCE( HWND hwnd )
}
pDCE = pDCE->next;
}
WIN_ReleaseWndPtr( pWnd );
WIN_ReleasePtr( pWnd );
}
@ -359,14 +356,19 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
DWORD dcxFlags = 0;
BOOL bUpdateVisRgn = TRUE;
BOOL bUpdateClipOrigin = FALSE;
HWND parent;
HWND parent, full;
TRACE("hwnd %04x, hrgnClip %04x, flags %08x\n",
hwnd, hrgnClip, (unsigned)flags);
if (!hwnd) hwnd = GetDesktopWindow();
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
hwnd = wndPtr->hwndSelf; /* make it a full handle */
if (!(full = WIN_IsCurrentProcess( hwnd )) && full != GetDesktopWindow())
{
FIXME( "not supported yet on other process window %x\n", full );
return 0;
}
hwnd = full;
if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
/* fixup flags */
@ -494,7 +496,7 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
TRACE("(%04x,%04x,0x%lx): returning %04x\n", hwnd, hrgnClip, flags, hdc);
END:
WIN_ReleaseWndPtr(wndPtr);
WIN_ReleasePtr(wndPtr);
return hdc;
}

View File

@ -306,11 +306,20 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
BOOL bIcon;
HRGN hrgnUpdate;
RECT clipRect, clientRect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return 0;
HWND full_handle;
WND *wndPtr;
bIcon = (wndPtr->dwStyle & WS_MINIMIZE && GetClassLongA(hwnd, GCL_HICON));
if (!(full_handle = WIN_IsCurrentThread( hwnd )))
{
if (IsWindow(hwnd))
FIXME( "window %x belongs to other thread\n", hwnd );
return 0;
}
hwnd = full_handle;
bIcon = (IsIconic(hwnd) && GetClassLongA(hwnd, GCL_HICON));
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
/* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */
@ -320,7 +329,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
* Make sure the window is still a window. All window locks are suspended
* when the WM_NCPAINT is sent.
*/
if (!IsWindow(wndPtr->hwndSelf))
if (!IsWindow( hwnd ))
{
WIN_ReleaseWndPtr(wndPtr);
return 0;
@ -336,7 +345,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
TRACE("hrgnUpdate = %04x, \n", hrgnUpdate);
if (GetClassLongA(wndPtr->hwndSelf, GCL_STYLE) & CS_PARENTDC)
if (GetClassLongA( hwnd, GCL_STYLE ) & CS_PARENTDC)
{
/* Don't clip the output to the update region for CS_PARENTDC window */
if( hrgnUpdate )

View File

@ -24,7 +24,6 @@
DEFAULT_DEBUG_CHANNEL(msg);
static HQUEUE16 hExitingQueue = 0;
static PERQUEUEDATA *pQDataWin16 = NULL; /* Global perQData for Win16 tasks */
HQUEUE16 hActiveQueue = 0;
@ -324,24 +323,6 @@ void QUEUE_Unlock( MESSAGEQUEUE *queue )
}
/***********************************************************************
* QUEUE_IsExitingQueue
*/
BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue )
{
return (hExitingQueue && (hQueue == hExitingQueue));
}
/***********************************************************************
* QUEUE_SetExitingQueue
*/
void QUEUE_SetExitingQueue( HQUEUE16 hQueue )
{
hExitingQueue = hQueue;
}
/***********************************************************************
* QUEUE_CreateMsgQueue
*
@ -417,7 +398,6 @@ void QUEUE_DeleteMsgQueue(void)
msgQueue->magic = 0;
if( hActiveQueue == hQueue ) hActiveQueue = 0;
if (hExitingQueue == hQueue) hExitingQueue = 0;
HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */

View File

@ -175,6 +175,18 @@ static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
}
/*******************************************************************
* send_parent_notify
*/
static void send_parent_notify( HWND hwnd, UINT msg )
{
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
}
/***********************************************************************
* WIN_GetPtr
*
@ -351,6 +363,14 @@ void WIN_UnlinkWindow( HWND hwnd )
void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
{
BOOL ret;
WND *wndPtr = WIN_GetPtr( hwnd );
if (!wndPtr) return;
if (wndPtr == WND_OTHER_PROCESS)
{
if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
return;
}
SERVER_START_REQ( link_window )
{
@ -360,15 +380,67 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
if (ret && parent)
if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent);
WIN_ReleasePtr( wndPtr );
}
/***********************************************************************
* WIN_SetOwner
*
* Change the owner of a window.
*/
void WIN_SetOwner( HWND hwnd, HWND owner )
{
WND *win = WIN_FindWndPtr( hwnd );
if (win)
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
if (wndPtr)
win->owner = owner;
WIN_ReleaseWndPtr( win );
}
}
/***********************************************************************
* WIN_SetRectangles
*
* Set the window and client rectangles.
*/
void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
{
WND *win = WIN_GetPtr( hwnd );
BOOL ret;
if (!win) return;
if (win == WND_OTHER_PROCESS)
{
wndPtr->parent = WIN_GetFullHandle(parent);
WIN_ReleaseWndPtr( wndPtr );
if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
return;
}
SERVER_START_REQ( set_window_rectangles )
{
req->handle = hwnd;
req->window.left = rectWindow->left;
req->window.top = rectWindow->top;
req->window.right = rectWindow->right;
req->window.bottom = rectWindow->bottom;
req->client.left = rectClient->left;
req->client.top = rectClient->top;
req->client.right = rectClient->right;
req->client.bottom = rectClient->bottom;
ret = !SERVER_CALL();
}
SERVER_END_REQ;
if (ret)
{
win->rectWindow = *rectWindow;
win->rectClient = *rectClient;
TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
}
WIN_ReleasePtr( win );
}
@ -481,18 +553,28 @@ HWND WIN_FindWinToRepaint( HWND hwnd )
*
* Destroy storage associated to a window. "Internals" p.358
*/
static void WIN_DestroyWindow( HWND hwnd )
LRESULT WIN_DestroyWindow( HWND hwnd )
{
WND *wndPtr;
HWND *list;
TRACE("%04x\n", hwnd );
if (!(hwnd = WIN_IsCurrentThread( hwnd )))
{
ERR( "window doesn't belong to current thread\n" );
return 0;
}
/* free child windows */
if ((list = WIN_ListChildren( hwnd )))
{
int i;
for (i = 0; list[i]; i++) WIN_DestroyWindow( list[i] );
for (i = 0; list[i]; i++)
{
if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
}
HeapFree( GetProcessHeap(), 0, list );
}
@ -517,7 +599,7 @@ static void WIN_DestroyWindow( HWND hwnd )
TIMER_RemoveWindowTimers( hwnd );
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
wndPtr->hmemTaskQ = 0;
if (!(wndPtr->dwStyle & WS_CHILD))
@ -538,6 +620,7 @@ static void WIN_DestroyWindow( HWND hwnd )
wndPtr->class = NULL;
wndPtr->dwMagic = 0; /* Mark it as invalid */
WIN_ReleaseWndPtr( wndPtr );
return 0;
}
/***********************************************************************
@ -576,10 +659,10 @@ BOOL WIN_CreateDesktopWindow(void)
WNDPROC winproc;
DCE *dce;
CREATESTRUCTA cs;
RECT rect;
TRACE("Creating desktop window\n");
if (!WINPOS_CreateInternalPosAtom() ||
!(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
&wndExtra, &winproc, &clsStyle, &dce )))
@ -595,11 +678,6 @@ BOOL WIN_CreateDesktopWindow(void)
pWndDesktop->owner = 0;
pWndDesktop->class = class;
pWndDesktop->hInstance = 0;
pWndDesktop->rectWindow.left = 0;
pWndDesktop->rectWindow.top = 0;
pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
pWndDesktop->rectClient = pWndDesktop->rectWindow;
pWndDesktop->text = NULL;
pWndDesktop->hmemTaskQ = 0;
pWndDesktop->hrgnUpdate = 0;
@ -625,13 +703,16 @@ BOOL WIN_CreateDesktopWindow(void)
cs.hwndParent = 0;
cs.x = 0;
cs.y = 0;
cs.cx = pWndDesktop->rectWindow.right;
cs.cy = pWndDesktop->rectWindow.bottom;
cs.cx = GetSystemMetrics( SM_CXSCREEN );
cs.cy = GetSystemMetrics( SM_CYSCREEN );
cs.style = pWndDesktop->dwStyle;
cs.dwExStyle = pWndDesktop->dwExStyle;
cs.lpszName = NULL;
cs.lpszClass = DESKTOP_CLASS_ATOM;
SetRect( &rect, 0, 0, cs.cx, cs.cy );
WIN_SetRectangles( hwndDesktop, &rect, &rect );
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
@ -721,6 +802,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
INT wndExtra;
DWORD clsStyle;
WNDPROC winproc;
RECT rect;
DCE *dce;
BOOL unicode = (type == WIN_PROC_32W);
@ -867,11 +949,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
/* Initialize the dimensions before sending WM_GETMINMAXINFO */
wndPtr->rectWindow.left = cs->x;
wndPtr->rectWindow.top = cs->y;
wndPtr->rectWindow.right = cs->x + cs->cx;
wndPtr->rectWindow.bottom = cs->y + cs->cy;
wndPtr->rectClient = wndPtr->rectWindow;
SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
WIN_SetRectangles( hwnd, &rect, &rect );
/* Send the WM_GETMINMAXINFO message and fix the size if needed */
@ -887,11 +966,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
if (cs->cx < 0) cs->cx = 0;
if (cs->cy < 0) cs->cy = 0;
wndPtr->rectWindow.left = cs->x;
wndPtr->rectWindow.top = cs->y;
wndPtr->rectWindow.right = cs->x + cs->cx;
wndPtr->rectWindow.bottom = cs->y + cs->cy;
wndPtr->rectClient = wndPtr->rectWindow;
SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
WIN_SetRectangles( hwnd, &rect, &rect );
/* Set the window menu */
@ -923,18 +999,14 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
return 0;
}
if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
{
/* Notify the parent window only */
SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
send_parent_notify( hwnd, WM_CREATE );
if( !IsWindow(hwnd) )
{
hwnd = 0;
goto end;
}
}
if (cs->style & WS_VISIBLE)
{
@ -1188,17 +1260,17 @@ static void WIN_SendDestroyMsg( HWND hwnd )
*/
BOOL WINAPI DestroyWindow( HWND hwnd )
{
WND * wndPtr;
BOOL retvalue;
BOOL is_child;
HWND h;
hwnd = WIN_GetFullHandle( hwnd );
if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
{
SetLastError( ERROR_ACCESS_DENIED );
return FALSE;
}
TRACE("(%04x)\n", hwnd);
/* Initialization */
if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
/* Look whether the focus is within the tree of windows we will
* be destroying.
*/
@ -1214,25 +1286,20 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
if (is_child)
{
if (!USER_IsExitingThread( GetCurrentThreadId() ))
send_parent_notify( hwnd, WM_DESTROY );
}
else if (!GetWindow( hwnd, GW_OWNER ))
{
HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
/* FIXME: clean up palette - see "Internals" p.352 */
}
if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
{
/* Notify the parent window only */
SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
if( !IsWindow(hwnd) )
{
retvalue = TRUE;
goto end;
}
}
if (!IsWindow(hwnd)) return TRUE;
if (USER_Driver.pResetSelectionOwner)
USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
@ -1240,38 +1307,30 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
/* Hide the window */
ShowWindow( hwnd, SW_HIDE );
if (!IsWindow(hwnd))
{
retvalue = TRUE;
goto end;
}
if (!IsWindow(hwnd)) return TRUE;
/* Recursively destroy owned windows */
if( !(wndPtr->dwStyle & WS_CHILD) )
if (!is_child)
{
HWND owner;
for (;;)
{
int i, got_one = 0;
HWND *list = WIN_ListChildren( wndPtr->parent );
HWND *list = WIN_ListChildren( GetDesktopWindow() );
if (list)
{
for (i = 0; list[i]; i++)
{
WND *siblingPtr;
if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
if (WIN_IsCurrentThread( list[i] ))
{
WIN_ReleaseWndPtr( siblingPtr );
DestroyWindow( list[i] );
got_one = 1;
continue;
}
else siblingPtr->owner = 0;
WIN_ReleaseWndPtr( siblingPtr );
WIN_SetOwner( list[i], 0 );
}
HeapFree( GetProcessHeap(), 0, list );
}
@ -1294,23 +1353,16 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
/* Send destroy messages */
WIN_SendDestroyMsg( hwnd );
if (!IsWindow(hwnd))
{
retvalue = TRUE;
goto end;
}
if (!IsWindow( hwnd )) return TRUE;
/* Unlink now so we won't bother with the children later on */
if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
WIN_UnlinkWindow( hwnd );
/* Destroy the window storage */
WIN_DestroyWindow( hwnd );
retvalue = TRUE;
end:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
return TRUE;
}
@ -1319,20 +1371,9 @@ end:
*/
BOOL WINAPI CloseWindow( HWND hwnd )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
BOOL retvalue;
if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
{
retvalue = FALSE;
goto end;
}
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
ShowWindow( hwnd, SW_MINIMIZE );
retvalue = TRUE;
end:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
return TRUE;
}
@ -1523,14 +1564,7 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
*/
BOOL WINAPI IsWindowEnabled(HWND hWnd)
{
WND * wndPtr;
BOOL retvalue;
if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
retvalue = !(wndPtr->dwStyle & WS_DISABLED);
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
}
@ -2114,34 +2148,25 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type )
/*****************************************************************
* SetParent (USER32.@)
* WIN_SetParent
*
* Implementation of SetParent, runs in the thread owning the window.
*/
HWND WINAPI SetParent( HWND hwnd, HWND parent )
HWND WIN_SetParent( HWND hwnd, HWND parent )
{
WND *wndPtr;
DWORD dwStyle;
HWND retvalue;
if (!parent) parent = GetDesktopWindow();
else parent = WIN_GetFullHandle( parent );
/* sanity checks */
if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
BOOL was_visible;
if (USER_Driver.pSetParent)
return USER_Driver.pSetParent( hwnd, parent );
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
dwStyle = wndPtr->dwStyle;
/* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all */
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
was_visible = ShowWindow( hwnd, SW_HIDE );
if (!IsWindow( parent )) return 0;
if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
retvalue = wndPtr->parent; /* old parent */
if (parent != retvalue)
@ -2150,28 +2175,55 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
if (parent != GetDesktopWindow()) /* a child window */
{
if (!(dwStyle & WS_CHILD))
if (!(wndPtr->dwStyle & WS_CHILD))
{
HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
if (menu) DestroyMenu( menu );
}
}
}
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleasePtr( wndPtr );
/* SetParent additionally needs to make hwnd the topmost window
in the x-order and send the expected WM_WINDOWPOSCHANGING and
WM_WINDOWPOSCHANGED notification messages.
*/
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
return retvalue;
}
/*****************************************************************
* SetParent (USER32.@)
*/
HWND WINAPI SetParent( HWND hwnd, HWND parent )
{
HWND full_handle;
if (!parent) parent = GetDesktopWindow();
else parent = WIN_GetFullHandle( parent );
if (!IsWindow( parent ))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if ((full_handle = WIN_IsCurrentThread( hwnd )))
return WIN_SetParent( full_handle, parent );
if ((full_handle = WIN_GetFullHandle(hwnd)) == GetDesktopWindow())
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
return SendMessageW( full_handle, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
}
/*******************************************************************
* IsChild (USER32.@)
*/

View File

@ -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 @@ void WINPOS_CheckInternalPos( HWND hwnd )
{
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 @@ void WINPOS_CheckInternalPos( HWND hwnd )
if ( !pMsgQ )
{
WARN("\tMessage queue not found. Exiting!\n" );
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleasePtr( wndPtr );
return;
}
@ -112,8 +115,7 @@ void WINPOS_CheckInternalPos( HWND hwnd )
}
QUEUE_Unlock( pMsgQ );
WIN_ReleaseWndPtr( wndPtr );
return;
WIN_ReleasePtr( wndPtr );
}
/***********************************************************************
@ -171,14 +173,39 @@ void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
*/
BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
BOOL ret;
WND *wndPtr = WIN_GetPtr( hwnd );
if (!wndPtr) return FALSE;
if (wndPtr != WND_OTHER_PROCESS)
{
*rect = wndPtr->rectWindow;
WIN_ReleaseWndPtr(wndPtr);
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",
TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
hwnd, rect->left, rect->top, rect->right, rect->bottom);
return TRUE;
}
return ret;
}
@ -248,17 +275,33 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
*/
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;
if (wndPtr != WND_OTHER_PROCESS)
{
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;
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 @@ static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM l
}
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,23 +442,29 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
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 );
/* If nothing found, try the scope window */
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 @@ HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
* 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 */
if (hwndFrom)
{
if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
HWND hwnd = hwndFrom;
while (hwnd)
{
ERR("bad hwndFrom = %04x\n",hwndFrom);
if (hwnd == hwndTo) return;
if (!(wndPtr = WIN_GetPtr( hwnd )))
{
ERR( "bad hwndFrom = %04x\n", hwnd );
return;
}
if ((list = WIN_ListParents( hwndFrom )))
{
for (i = 0; list[i]; i++)
{
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
offset->x += wndPtr->rectClient.left;
offset->y += wndPtr->rectClient.top;
WIN_ReleaseWndPtr( wndPtr );
if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
}
HeapFree( GetProcessHeap(), 0, list );
}
WIN_ReleaseWndPtr(wndPtr);
}
/* Translate origin to destination window coords */
if (hwndTo)
{
if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
HWND hwnd = hwndTo;
while (hwnd)
{
ERR("bad hwndTo = %04x\n", hwndTo );
if (!(wndPtr = WIN_GetPtr( hwnd )))
{
ERR( "bad hwndTo = %04x\n", hwnd );
return;
}
if ((list = WIN_ListParents( hwndTo )))
{
for (i = 0; list[i]; i++)
{
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
offset->x -= wndPtr->rectClient.left;
offset->y -= wndPtr->rectClient.top;
WIN_ReleaseWndPtr( wndPtr );
if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
}
HeapFree( GetProcessHeap(), 0, list );
}
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 @@ void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
/*******************************************************************
* 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 @@ INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
*/
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 IsIconic(HWND hWnd)
*/
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 @@ BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
/***********************************************************************
* 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 ShowWindowAsync( HWND hwnd, INT cmd )
*/
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 @@ CLEANUP_END:
BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
{
BOOL bRet = 0;
WND *pWnd;
HWND hwndActive = 0;
HWND hwndTo = 0;
HWND owner;
@ -1376,21 +1422,16 @@ BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
}
}
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 @@ BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
if( !hwndTo ) break;
}
}
WIN_ReleaseWndPtr( pWnd );
bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
@ -1451,45 +1491,6 @@ BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
}
/***********************************************************************
* 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)&params );
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
*
@ -1557,7 +1558,8 @@ BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
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 @@ HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
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++)
{
@ -1676,7 +1660,7 @@ HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
pDWP->actualCount++;
retvalue = newhdwp;
END:
WIN_ReleaseWndPtr(pWnd);
USER_Unlock();
return retvalue;
}

View File

@ -1200,7 +1200,6 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
LPDRAGINFO16 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
SEGPTR spDragInfo = K32WOWGlobalLock16(hDragInfo);
Window w_aux_root, w_aux_child;
WND* pDropWnd;
WND* pWnd;
if( !lpDragInfo || !spDragInfo ) return;
@ -1224,13 +1223,12 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
}
pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
WIN_ReleaseWndPtr(pWnd);
GlobalFree16( hDragInfo );
if( bAccept )
{
if (!bAccept) return;
TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
dndSelection, 0, 65535, FALSE,
AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
@ -1264,6 +1262,7 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
if( lpDrop )
{
WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
lpDrop->pFiles = sizeof(DROPFILES);
lpDrop->pt.x = x;
lpDrop->pt.y = y;
@ -1273,6 +1272,7 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
lpDrop->fWide = FALSE;
WIN_ReleaseWndPtr(pDropWnd);
p_drop = (char *)(lpDrop + 1);
p = p_data;
while(*p)
@ -1290,10 +1290,6 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
}
}
if( p_data ) TSXFree(p_data);
} /* WS_EX_ACCEPTFILES */
WIN_ReleaseWndPtr(pDropWnd);
}
/**********************************************************************
@ -1306,8 +1302,6 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
*/
static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
{
WND *pDropWnd;
WND *pWnd;
unsigned long data_length;
unsigned long aux_long, drop_len = 0;
unsigned char *p_data = NULL; /* property data */
@ -1322,14 +1316,7 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
Window w_aux;
} u; /* unused */
pWnd = WIN_FindWndPtr(hWnd);
if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
{
WIN_ReleaseWndPtr(pWnd);
return;
}
WIN_ReleaseWndPtr(pWnd);
if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
dndSelection, 0, 65535, FALSE,
@ -1362,13 +1349,12 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
&x, &y, &u.i, &u.i, &u.i);
pDropWnd = WIN_FindWndPtr( hWnd );
drop_len += sizeof(DROPFILES) + 1;
hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
lpDrop = (DROPFILES *) GlobalLock( hDrop );
if( lpDrop ) {
WND *pDropWnd = WIN_FindWndPtr( hWnd );
lpDrop->pFiles = sizeof(DROPFILES);
lpDrop->pt.x = (INT)x;
lpDrop->pt.y = (INT)y;
@ -1379,6 +1365,7 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
lpDrop->fWide = FALSE;
p_drop = (char*)(lpDrop + 1);
WIN_ReleaseWndPtr(pDropWnd);
}
/* create message content */
@ -1411,7 +1398,6 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
GlobalUnlock(hDrop);
PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
}
WIN_ReleaseWndPtr(pDropWnd);
}
if( p_data ) TSXFree(p_data);
}