From ddc3317b7a6cbec3beb7b60a40682ce037c94bb5 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 22 Oct 2001 19:08:33 +0000 Subject: [PATCH] Store in the server all the window information accessible with Get/SetWindowLong. --- controls/scroll.c | 36 +- dlls/ttydrv/wnd.c | 8 +- dlls/user/message.c | 13 +- dlls/user/user_main.c | 1 - dlls/x11drv/window.c | 124 ++---- dlls/x11drv/winpos.c | 236 +++++------ dlls/x11drv/x11drv.spec | 1 - include/user.h | 7 +- include/win.h | 3 +- include/wine/server_protocol.h | 42 +- server/protocol.def | 34 ++ server/request.h | 4 + server/trace.c | 47 ++- server/window.c | 64 ++- windows/defwnd.c | 8 +- windows/win.c | 699 ++++++++++++++++++++++----------- windows/winpos.c | 52 ++- 17 files changed, 875 insertions(+), 504 deletions(-) diff --git a/controls/scroll.c b/controls/scroll.c index 55b330db47c..6f83cd3d9e8 100644 --- a/controls/scroll.c +++ b/controls/scroll.c @@ -1714,10 +1714,8 @@ LPINT lpMax /* [out] Where to store maximum value */) BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, BOOL fShowH, BOOL fShowV ) { - WND *wndPtr = WIN_FindWndPtr( hwnd ); - BOOL retvalue = FALSE; + LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - if (!wndPtr) return FALSE; TRACE("hwnd=%04x bar=%d horz=%d, vert=%d\n", hwnd, nBar, fShowH, fShowV ); @@ -1725,20 +1723,19 @@ BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, { case SB_CTL: ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE ); - retvalue = TRUE; - goto END; + return TRUE; case SB_BOTH: case SB_HORZ: if (fShowH) { - fShowH = !(wndPtr->dwStyle & WS_HSCROLL); - wndPtr->dwStyle |= WS_HSCROLL; + fShowH = !(style & WS_HSCROLL); + style |= WS_HSCROLL; } else /* hide it */ { - fShowH = (wndPtr->dwStyle & WS_HSCROLL); - wndPtr->dwStyle &= ~WS_HSCROLL; + fShowH = (style & WS_HSCROLL); + style &= ~WS_HSCROLL; } if( nBar == SB_HORZ ) { fShowV = FALSE; @@ -1749,35 +1746,30 @@ BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, case SB_VERT: if (fShowV) { - fShowV = !(wndPtr->dwStyle & WS_VSCROLL); - wndPtr->dwStyle |= WS_VSCROLL; + fShowV = !(style & WS_VSCROLL); + style |= WS_VSCROLL; } else /* hide it */ { - fShowV = (wndPtr->dwStyle & WS_VSCROLL); - wndPtr->dwStyle &= ~WS_VSCROLL; + fShowV = (style & WS_VSCROLL); + style &= ~WS_VSCROLL; } if ( nBar == SB_VERT ) fShowH = FALSE; break; default: - retvalue = FALSE; /* Nothing to do! */ - goto END; + return FALSE; /* Nothing to do! */ } if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */ { + WIN_SetStyle( hwnd, style ); SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); - retvalue = TRUE; - goto END; + return TRUE; } - - retvalue = FALSE; /* no frame changes */ -END: - WIN_ReleaseWndPtr(wndPtr); - return retvalue; + return FALSE; /* no frame changes */ } diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c index d375c291b8c..47e4f4e5cf8 100644 --- a/dlls/ttydrv/wnd.c +++ b/dlls/ttydrv/wnd.c @@ -609,13 +609,9 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos ) WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect ); if( winpos->flags & SWP_SHOWWINDOW ) - { - wndPtr->dwStyle |= WS_VISIBLE; - } + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE ); else if( winpos->flags & SWP_HIDEWINDOW ) - { - wndPtr->dwStyle &= ~WS_VISIBLE; - } + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); /* ------------------------------------------------------------------------ FINAL */ diff --git a/dlls/user/message.c b/dlls/user/message.c index a9608cbaca7..14f458fc46a 100644 --- a/dlls/user/message.c +++ b/dlls/user/message.c @@ -1084,16 +1084,21 @@ static void reply_message( struct received_message_info *info, LRESULT result, B */ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { + if (hwnd == GetDesktopWindow()) return 0; switch(msg) { + case WM_WINE_DESTROYWINDOW: + return WIN_DestroyWindow( hwnd ); 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 ); + return ShowWindow( hwnd, wparam ); case WM_WINE_SETPARENT: - return (LRESULT)WIN_SetParent( hwnd, (HWND)wparam ); + return (LRESULT)SetParent( hwnd, (HWND)wparam ); + case WM_WINE_SETWINDOWLONG: + return (LRESULT)SetWindowLongW( hwnd, wparam, lparam ); + case WM_WINE_ENABLEWINDOW: + return EnableWindow( hwnd, wparam ); default: FIXME( "unknown internal message %x\n", msg ); return 0; diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c index 92dc3f52360..006e74c811c 100644 --- a/dlls/user/user_main.c +++ b/dlls/user/user_main.c @@ -87,7 +87,6 @@ static BOOL load_driver(void) GET_USER_FUNC(CreateWindow); GET_USER_FUNC(DestroyWindow); GET_USER_FUNC(GetDC); - GET_USER_FUNC(EnableWindow); GET_USER_FUNC(ForceWindowRaise); GET_USER_FUNC(MsgWaitForMultipleObjectsEx); GET_USER_FUNC(ScrollDC); diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c index bf5d0fa5ee7..830706236a7 100644 --- a/dlls/x11drv/window.c +++ b/dlls/x11drv/window.c @@ -22,6 +22,7 @@ #include "debugtools.h" #include "x11drv.h" #include "win.h" +#include "winpos.h" #include "dce.h" #include "options.h" @@ -106,8 +107,8 @@ static int get_window_attributes( Display *display, WND *win, XSetWindowAttribut BOOL is_top_level = is_window_top_level( win ); BOOL managed = is_top_level && is_window_managed( win ); - if (managed) win->dwExStyle |= WS_EX_MANAGED; - else win->dwExStyle &= ~WS_EX_MANAGED; + if (managed) WIN_SetExStyle( win->hwndSelf, win->dwExStyle | WS_EX_MANAGED ); + else WIN_SetExStyle( win->hwndSelf, win->dwExStyle & ~WS_EX_MANAGED ); attr->override_redirect = !managed; attr->colormap = X11DRV_PALETTE_PaletteXColormap; @@ -833,13 +834,17 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) data->hWMIconBitmap = 0; data->hWMIconMask = 0; - wndPtr = WIN_FindWndPtr( hwnd ); + wndPtr = WIN_GetPtr( hwnd ); wndPtr->pDriverData = data; + /* initialize the dimensions before sending WM_GETMINMAXINFO */ + SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy ); + WIN_SetRectangles( hwnd, &rect, &rect ); + if (!wndPtr->parent) { create_desktop( display, wndPtr, cs ); - WIN_ReleaseWndPtr( wndPtr ); + WIN_ReleasePtr( wndPtr ); return TRUE; } @@ -847,11 +852,30 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) if (!create_client_window( display, wndPtr )) goto failed; TSXSync( display, False ); - WIN_ReleaseWndPtr( wndPtr ); - SetPropA( hwnd, whole_window_atom, (HANDLE)data->whole_window ); SetPropA( hwnd, client_window_atom, (HANDLE)data->client_window ); + /* Send the WM_GETMINMAXINFO message and fix the size if needed */ + if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) + { + POINT maxSize, maxPos, minTrack, maxTrack; + + WIN_ReleasePtr( wndPtr ); + WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack); + if (maxSize.x < cs->cx) cs->cx = maxSize.x; + if (maxSize.y < cs->cy) cs->cy = maxSize.y; + if (cs->cx < minTrack.x ) cs->cx = minTrack.x; + if (cs->cy < minTrack.y ) cs->cy = minTrack.y; + if (cs->cx < 0) cs->cx = 0; + if (cs->cy < 0) cs->cy = 0; + + if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE; + SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy ); + WIN_SetRectangles( hwnd, &rect, &rect ); + X11DRV_sync_whole_window_position( display, wndPtr, 0 ); + } + WIN_ReleasePtr( wndPtr ); + /* send WM_NCCREATE */ TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy ); if (unicode) @@ -860,17 +884,20 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs ); if (!ret) { - X11DRV_DestroyWindow( hwnd ); + WARN("aborted by WM_xxCREATE!\n"); return FALSE; } - if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE; + if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE; sync_window_style( display, wndPtr ); /* send WM_NCCALCSIZE */ rect = wndPtr->rectWindow; + WIN_ReleasePtr( wndPtr ); SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect ); + + if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE; if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow; WIN_SetRectangles( hwnd, &wndPtr->rectWindow, &rect ); X11DRV_sync_client_window_position( display, wndPtr ); @@ -892,7 +919,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) else WIN_LinkWindow( hwnd, wndPtr->parent, HWND_TOP ); - WIN_ReleaseWndPtr( wndPtr ); + WIN_ReleasePtr( wndPtr ); if (unicode) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1); @@ -902,7 +929,6 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) if (!ret) { WIN_UnlinkWindow( hwnd ); - X11DRV_DestroyWindow( hwnd ); return FALSE; } @@ -932,7 +958,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) RECT newPos; UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; - wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE); + WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MAXIMIZE | WS_MINIMIZE) ); WINPOS_MinMaximize( hwnd, swFlag, &newPos ); swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow()) ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED @@ -946,8 +972,8 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) failed: - X11DRV_DestroyWindow( wndPtr->hwndSelf ); - WIN_ReleaseWndPtr( wndPtr ); + X11DRV_DestroyWindow( hwnd ); + if (wndPtr) WIN_ReleasePtr( wndPtr ); return FALSE; } @@ -1052,78 +1078,6 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent ) } -/******************************************************************* - * EnableWindow (X11DRV.@) - */ -BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable ) -{ - Display *display = thread_display(); - XWMHints *wm_hints; - WND *wndPtr; - BOOL retvalue; - - if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE; - hwnd = wndPtr->hwndSelf; /* make it a full handle */ - - retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0); - - if (enable && (wndPtr->dwStyle & WS_DISABLED)) - { - /* Enable window */ - wndPtr->dwStyle &= ~WS_DISABLED; - - if (wndPtr->dwExStyle & WS_EX_MANAGED) - { - wine_tsx11_lock(); - if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) ))) - wm_hints = XAllocWMHints(); - if (wm_hints) - { - wm_hints->flags |= InputHint; - wm_hints->input = TRUE; - XSetWMHints( display, get_whole_window(wndPtr), wm_hints ); - XFree(wm_hints); - } - wine_tsx11_unlock(); - } - - SendMessageA( hwnd, WM_ENABLE, TRUE, 0 ); - } - else if (!enable && !(wndPtr->dwStyle & WS_DISABLED)) - { - SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 ); - - /* Disable window */ - wndPtr->dwStyle |= WS_DISABLED; - - if (wndPtr->dwExStyle & WS_EX_MANAGED) - { - wine_tsx11_lock(); - if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) ))) - wm_hints = XAllocWMHints(); - if (wm_hints) - { - wm_hints->flags |= InputHint; - wm_hints->input = FALSE; - XSetWMHints( display, get_whole_window(wndPtr), wm_hints ); - XFree(wm_hints); - } - wine_tsx11_unlock(); - } - - if (hwnd == GetFocus()) - SetFocus( 0 ); /* A disabled window can't have the focus */ - - if (hwnd == GetCapture()) - ReleaseCapture(); /* A disabled window can't capture the mouse */ - - SendMessageA( hwnd, WM_ENABLE, FALSE, 0 ); - } - WIN_ReleaseWndPtr(wndPtr); - return retvalue; -} - - /***************************************************************** * SetFocus (X11DRV.@) * diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c index 5409293fd7a..6301e08b19d 100644 --- a/dlls/x11drv/winpos.c +++ b/dlls/x11drv/winpos.c @@ -14,6 +14,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "winerror.h" #include "x11drv.h" #include "hook.h" @@ -407,7 +408,7 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event ) */ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) { - WND *win = WIN_FindWndPtr( hwnd ); + WND *win = WIN_GetPtr( hwnd ); HWND top = 0; X11DRV_WND_DATA *data = win->pDriverData; Drawable drawable; @@ -505,7 +506,7 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) DeleteObject( visRgn ); } - WIN_ReleaseWndPtr( win ); + WIN_ReleasePtr( win ); return TRUE; } @@ -675,10 +676,14 @@ static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter) /* fix redundant flags and values in the WINDOWPOS structure */ static BOOL fixup_flags( WINDOWPOS *winpos ) { - WND *wndPtr = WIN_FindWndPtr( winpos->hwnd ); + WND *wndPtr = WIN_GetPtr( winpos->hwnd ); BOOL ret = TRUE; - if (!wndPtr) return FALSE; + if (!wndPtr || wndPtr == WND_OTHER_PROCESS) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } winpos->hwnd = wndPtr->hwndSelf; /* make it a full handle */ if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW; @@ -723,25 +728,20 @@ static BOOL fixup_flags( WINDOWPOS *winpos ) /* hwndInsertAfter must be a sibling of the window */ if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM)) { - WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter); - if (wnd) + winpos->hwndInsertAfter = WIN_GetFullHandle( winpos->hwndInsertAfter ); + if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != wndPtr->parent) ret = FALSE; + else { - winpos->hwndInsertAfter = wnd->hwndSelf; /* make it a full handle */ - if (wnd->parent != wndPtr->parent) ret = FALSE; - else - { - /* don't need to change the Zorder of hwnd if it's already inserted - * after hwndInsertAfter or when inserting hwnd after itself. - */ - if ((winpos->hwnd == winpos->hwndInsertAfter) || - (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) - winpos->flags |= SWP_NOZORDER; - } - WIN_ReleaseWndPtr(wnd); + /* don't need to change the Zorder of hwnd if it's already inserted + * after hwndInsertAfter or when inserting hwnd after itself. + */ + if ((winpos->hwnd == winpos->hwndInsertAfter) || + (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT ))) + winpos->flags |= SWP_NOZORDER; } } done: - WIN_ReleaseWndPtr(wndPtr); + WIN_ReleasePtr( wndPtr ); return ret; } @@ -754,18 +754,51 @@ static BOOL fixup_flags( WINDOWPOS *winpos ) void X11DRV_SetWindowStyle( HWND hwnd, LONG oldStyle ) { Display *display = thread_display(); - WND *wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return; + WND *wndPtr; + LONG changed; - if ((wndPtr->dwStyle & WS_VISIBLE) && (!(oldStyle & WS_VISIBLE))) + if (hwnd == GetDesktopWindow()) return; + if (!(wndPtr = WIN_GetPtr( hwnd ))) return; + if (wndPtr == WND_OTHER_PROCESS) return; + + changed = wndPtr->dwStyle ^ oldStyle; + + if (changed & WS_VISIBLE) { if (!IsRectEmpty( &wndPtr->rectWindow )) { - TRACE( "mapping win %x\n", hwnd ); - TSXMapWindow( display, get_whole_window(wndPtr) ); + if (wndPtr->dwStyle & WS_VISIBLE) + { + TRACE( "mapping win %x\n", hwnd ); + TSXMapWindow( display, get_whole_window(wndPtr) ); + } + else + { + TRACE( "unmapping win %x\n", hwnd ); + TSXUnmapWindow( display, get_whole_window(wndPtr) ); + } } } - WIN_ReleaseWndPtr(wndPtr); + + if (changed & WS_DISABLED) + { + if (wndPtr->dwExStyle & WS_EX_MANAGED) + { + XWMHints *wm_hints; + wine_tsx11_lock(); + if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) ))) + wm_hints = XAllocWMHints(); + if (wm_hints) + { + wm_hints->flags |= InputHint; + wm_hints->input = !(wndPtr->dwStyle & WS_DISABLED); + XSetWMHints( display, get_whole_window(wndPtr), wm_hints ); + XFree(wm_hints); + } + wine_tsx11_unlock(); + } + } + WIN_ReleasePtr(wndPtr); } @@ -844,37 +877,26 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos ) WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect ); - if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE; - else if (winpos->flags & SWP_HIDEWINDOW) - { - /* clear the update region */ - RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | - RDW_NOINTERNALPAINT | RDW_ALLCHILDREN ); - wndPtr->dwStyle &= ~WS_VISIBLE; - } - if (get_whole_window(wndPtr)) /* don't do anything if X window not created yet */ { Display *display = thread_display(); - wine_tsx11_lock(); if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW)) { - if (!IsRectEmpty( &oldWindowRect )) - { - XUnmapWindow( display, get_whole_window(wndPtr) ); - TRACE( "unmapping win %x\n", winpos->hwnd ); - } - else TRACE( "not unmapping zero size win %x\n", winpos->hwnd ); + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); + /* clear the update region */ +// RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | +// RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN ); } else if ((wndPtr->dwStyle & WS_VISIBLE) && !IsRectEmpty( &oldWindowRect ) && IsRectEmpty( &newWindowRect )) { /* resizing to zero size -> unmap */ TRACE( "unmapping zero size win %x\n", winpos->hwnd ); - XUnmapWindow( display, get_whole_window(wndPtr) ); + TSXUnmapWindow( display, get_whole_window(wndPtr) ); } + wine_tsx11_lock(); if (bChangePos) X11DRV_sync_whole_window_position( display, wndPtr, !(winpos->flags & SWP_NOZORDER) ); else @@ -893,12 +915,7 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos ) } if (winpos->flags & SWP_SHOWWINDOW) { - if (!IsRectEmpty( &newWindowRect )) - { - XMapWindow( display, get_whole_window(wndPtr) ); - TRACE( "mapping win %x\n", winpos->hwnd ); - } - else TRACE( "not mapping win %x, size is zero\n", winpos->hwnd ); + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE ); } else if ((wndPtr->dwStyle & WS_VISIBLE) && IsRectEmpty( &oldWindowRect ) && !IsRectEmpty( &newWindowRect )) @@ -910,6 +927,13 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos ) XFlush( display ); /* FIXME: should not be necessary */ wine_tsx11_unlock(); } + else /* no X window, simply toggle the window style */ + { + if (winpos->flags & SWP_SHOWWINDOW) + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE ); + else if (winpos->flags & SWP_HIDEWINDOW) + WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); + } /* manually expose the areas that X won't expose because they are still covered by something */ @@ -1021,6 +1045,7 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) WND *wndPtr; UINT swpFlags = 0; POINT size; + LONG old_style; WINDOWPLACEMENT wpl; TRACE("0x%04x %u\n", hwnd, cmd ); @@ -1046,14 +1071,10 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) switch( cmd ) { case SW_MINIMIZE: - if( wndPtr->dwStyle & WS_MAXIMIZE) - { - wndPtr->flags |= WIN_RESTORE_MAX; - wndPtr->dwStyle &= ~WS_MAXIMIZE; - } - else - wndPtr->flags &= ~WIN_RESTORE_MAX; - wndPtr->dwStyle |= WS_MINIMIZE; + if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX; + else wndPtr->flags &= ~WIN_RESTORE_MAX; + + WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE ); X11DRV_set_iconic_state( wndPtr ); @@ -1067,21 +1088,19 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) case SW_MAXIMIZE: WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL ); - if( wndPtr->dwStyle & WS_MINIMIZE ) + old_style = WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MINIMIZE) | WS_MAXIMIZE ); + if (old_style & WS_MINIMIZE) { - wndPtr->dwStyle &= ~WS_MINIMIZE; WINPOS_ShowIconTitle( hwnd, FALSE ); X11DRV_set_iconic_state( wndPtr ); } - wndPtr->dwStyle |= WS_MAXIMIZE; - SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); break; case SW_RESTORE: - if( wndPtr->dwStyle & WS_MINIMIZE ) + old_style = WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE) ); + if (old_style & WS_MINIMIZE) { - wndPtr->dwStyle &= ~WS_MINIMIZE; WINPOS_ShowIconTitle( hwnd, FALSE ); X11DRV_set_iconic_state( wndPtr ); @@ -1089,16 +1108,12 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) { /* Restore to maximized position */ WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL); - wndPtr->dwStyle |= WS_MAXIMIZE; + WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_MAXIMIZE ); SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); break; } } - else - { - if (!(wndPtr->dwStyle & WS_MAXIMIZE)) break; - wndPtr->dwStyle &= ~WS_MAXIMIZE; - } + else if (!(old_style & WS_MAXIMIZE)) break; /* Restore to normal position */ @@ -1250,7 +1265,7 @@ void X11DRV_MapNotify( HWND hwnd, XMapEvent *event ) HWND hwndFocus = GetFocus(); WND *win; - if (!(win = WIN_FindWndPtr( hwnd ))) return; + if (!(win = WIN_GetPtr( hwnd ))) return; if ((win->dwStyle & WS_VISIBLE) && (win->dwStyle & WS_MINIMIZE) && @@ -1260,16 +1275,7 @@ void X11DRV_MapNotify( HWND hwnd, XMapEvent *event ) unsigned int width, height, border, depth; Window root, top; RECT rect; - - DCE_InvalidateDCE( hwnd, &win->rectWindow ); - win->dwStyle &= ~WS_MINIMIZE; - win->dwStyle |= WS_VISIBLE; - WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE ); - - if (win->flags & WIN_RESTORE_MAX) - win->dwStyle |= WS_MAXIMIZE; - else - win->dwStyle &= ~WS_MAXIMIZE; + LONG style = (win->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE)) | WS_VISIBLE; /* FIXME: hack */ wine_tsx11_lock(); @@ -1283,12 +1289,19 @@ void X11DRV_MapNotify( HWND hwnd, XMapEvent *event ) rect.bottom = y + height; X11DRV_X_to_window_rect( win, &rect ); + DCE_InvalidateDCE( hwnd, &win->rectWindow ); + + if (win->flags & WIN_RESTORE_MAX) style |= WS_MAXIMIZE; + WIN_SetStyle( hwnd, style ); + WIN_ReleasePtr( win ); + + WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE ); SendMessageA( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 ); SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER | SWP_WINE_NOHOSTMOVE ); } + else WIN_ReleasePtr( win ); if (hwndFocus && IsChild( hwnd, hwndFocus )) X11DRV_SetFocus(hwndFocus); /* FIXME */ - WIN_ReleaseWndPtr( win ); } @@ -1299,28 +1312,26 @@ void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event ) { WND *win; - if (!(win = WIN_FindWndPtr( hwnd ))) return; + if (!(win = WIN_GetPtr( hwnd ))) return; if ((win->dwStyle & WS_VISIBLE) && (win->dwExStyle & WS_EX_MANAGED)) { + if (win->dwStyle & WS_MAXIMIZE) + win->flags |= WIN_RESTORE_MAX; + else + win->flags &= ~WIN_RESTORE_MAX; + + WIN_SetStyle( hwnd, (win->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE ); + WIN_ReleasePtr( win ); + EndMenu(); SendMessageA( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 ); - - win->flags &= ~WIN_RESTORE_MAX; - win->dwStyle |= WS_MINIMIZE; - - if (win->dwStyle & WS_MAXIMIZE) - { - win->flags |= WIN_RESTORE_MAX; - win->dwStyle &= ~WS_MAXIMIZE; - } - SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_WINE_NOHOSTMOVE ); WIN_InternalShowOwnedPopups( hwnd, FALSE, TRUE ); } - WIN_ReleaseWndPtr( win ); + else WIN_ReleasePtr( win ); } @@ -1538,23 +1549,26 @@ void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event ) * * Assign specified region to window (for non-rectangular windows) */ -BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) +int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) { - RECT rect; - WND *wndPtr = WIN_FindWndPtr(hwnd); - int ret = FALSE; + WND *wndPtr; - if (!wndPtr) return FALSE; + if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS) + { + if (IsWindow( hwnd )) + FIXME( "not supported on other process window %x\n", hwnd ); + wndPtr = NULL; + } + if (!wndPtr) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } if (wndPtr->hrgnWnd == hrgn) { - ret = TRUE; - goto done; - } - - if (hrgn) /* verify that region really exists */ - { - if (GetRgnBox( hrgn, &rect ) == ERROR) goto done; + WIN_ReleasePtr( wndPtr ); + return TRUE; } if (wndPtr->hrgnWnd) @@ -1584,8 +1598,11 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) DWORD size; DWORD dwBufferSize = GetRegionData(hrgn, 0, NULL); PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize); - if (!pRegionData) goto done; - + if (!pRegionData) + { + WIN_ReleasePtr( wndPtr ); + return TRUE; + } GetRegionData(hrgn, dwBufferSize, pRegionData); size = pRegionData->rdh.nCount; x_offset = wndPtr->rectWindow.left - data->whole_rect.left; @@ -1624,12 +1641,9 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) } #endif /* HAVE_LIBXSHAPE */ + WIN_ReleasePtr( wndPtr ); if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE ); - ret = TRUE; - - done: - WIN_ReleaseWndPtr(wndPtr); - return ret; + return TRUE; } diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec index 2c3efaf04a3..25ee1f97726 100644 --- a/dlls/x11drv/x11drv.spec +++ b/dlls/x11drv/x11drv.spec @@ -78,7 +78,6 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics @ cdecl CreateWindow(long ptr long) X11DRV_CreateWindow @ cdecl DestroyWindow(long) X11DRV_DestroyWindow @ cdecl GetDC(long long long long) X11DRV_GetDC -@ cdecl EnableWindow(long long) X11DRV_EnableWindow @ cdecl ForceWindowRaise(long) X11DRV_ForceWindowRaise @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx @ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC diff --git a/include/user.h b/include/user.h index fb5603dfa72..baf99dbafcf 100644 --- a/include/user.h +++ b/include/user.h @@ -38,7 +38,9 @@ enum wine_internal_message WM_WINE_DESTROYWINDOW = 0x80000000, WM_WINE_SETWINDOWPOS, WM_WINE_SHOWWINDOW, - WM_WINE_SETPARENT + WM_WINE_SETPARENT, + WM_WINE_SETWINDOWLONG, + WM_WINE_ENABLEWINDOW }; /* internal SendInput codes (FIXME) */ @@ -79,7 +81,6 @@ typedef struct tagUSER_DRIVER { BOOL (*pCreateWindow)(HWND,CREATESTRUCTA*,BOOL); BOOL (*pDestroyWindow)(HWND); BOOL (*pGetDC)(HWND,HDC,HRGN,DWORD); - BOOL (*pEnableWindow)(HWND,BOOL); void (*pForceWindowRaise)(HWND); DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD); BOOL (*pScrollDC)(HDC,INT,INT,const RECT*,const RECT*,HRGN,LPRECT); @@ -87,7 +88,7 @@ typedef struct tagUSER_DRIVER { void (*pSetFocus)(HWND); HWND (*pSetParent)(HWND,HWND); BOOL (*pSetWindowPos)(WINDOWPOS *); - BOOL (*pSetWindowRgn)(HWND,HRGN,BOOL); + int (*pSetWindowRgn)(HWND,HRGN,BOOL); HICON (*pSetWindowIcon)(HWND,HICON,BOOL); void (*pSetWindowStyle)(HWND,DWORD); BOOL (*pSetWindowText)(HWND,LPCWSTR); diff --git a/include/win.h b/include/win.h index 81c3df741da..6c8d5771bcd 100644 --- a/include/win.h +++ b/include/win.h @@ -89,6 +89,8 @@ 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 LONG WIN_SetStyle( 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 HWND WIN_FindWinToRepaint( HWND hwnd ); extern LRESULT WIN_DestroyWindow( HWND hwnd ); @@ -97,7 +99,6 @@ 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 ) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 25ba8813dd6..375667c1980 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1601,6 +1601,7 @@ struct link_window_request user_handle_t handle; user_handle_t parent; user_handle_t previous; + user_handle_t full_parent; }; @@ -1613,6 +1614,16 @@ struct destroy_window_request +struct set_window_owner_request +{ + struct request_header __header; + user_handle_t handle; + user_handle_t owner; + user_handle_t full_owner; +}; + + + struct get_window_info_request { struct request_header __header; @@ -1620,10 +1631,35 @@ struct get_window_info_request user_handle_t full_handle; void* pid; void* tid; + atom_t atom; }; +struct set_window_info_request +{ + struct request_header __header; + user_handle_t handle; + unsigned int flags; + unsigned int style; + unsigned int ex_style; + unsigned int id; + void* instance; + void* user_data; + unsigned int old_style; + unsigned int old_ex_style; + unsigned int old_id; + void* old_instance; + void* old_user_data; +}; +#define SET_WIN_STYLE 0x01 +#define SET_WIN_EXSTYLE 0x02 +#define SET_WIN_ID 0x04 +#define SET_WIN_INSTANCE 0x08 +#define SET_WIN_USERDATA 0x10 + + + struct get_window_parents_request { struct request_header __header; @@ -1858,7 +1894,9 @@ enum request REQ_create_window, REQ_link_window, REQ_destroy_window, + REQ_set_window_owner, REQ_get_window_info, + REQ_set_window_info, REQ_get_window_parents, REQ_get_window_children, REQ_get_window_tree, @@ -2001,7 +2039,9 @@ union generic_request struct create_window_request create_window; struct link_window_request link_window; struct destroy_window_request destroy_window; + struct set_window_owner_request set_window_owner; struct get_window_info_request get_window_info; + struct set_window_info_request set_window_info; struct get_window_parents_request get_window_parents; struct get_window_children_request get_window_children; struct get_window_tree_request get_window_tree; @@ -2014,6 +2054,6 @@ union generic_request struct get_window_properties_request get_window_properties; }; -#define SERVER_PROTOCOL_VERSION 60 +#define SERVER_PROTOCOL_VERSION 61 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 78955d9197f..be779ea8e99 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1434,6 +1434,7 @@ enum message_type user_handle_t parent; /* handle to the parent */ user_handle_t previous; /* previous child in Z-order */ @REPLY + user_handle_t full_parent; /* full handle of new parent */ @END @@ -1443,6 +1444,15 @@ enum message_type @END +/* Set a window owner */ +@REQ(set_window_owner) + user_handle_t handle; /* handle to the window */ + user_handle_t owner; /* new owner */ +@REPLY + user_handle_t full_owner; /* full handle of new owner */ +@END + + /* Get information from a window handle */ @REQ(get_window_info) user_handle_t handle; /* handle to the window */ @@ -1450,9 +1460,33 @@ enum message_type user_handle_t full_handle; /* full 32-bit handle */ void* pid; /* process owning the window */ void* tid; /* thread owning the window */ + atom_t atom; /* class atom */ @END +/* Set some information in a window */ +@REQ(set_window_info) + user_handle_t handle; /* handle to the window */ + unsigned int flags; /* flags for fields to set (see below) */ + unsigned int style; /* window style */ + unsigned int ex_style; /* window extended style */ + unsigned int id; /* window id */ + void* instance; /* creator instance */ + void* user_data; /* user-specific data */ +@REPLY + unsigned int old_style; /* old window style */ + unsigned int old_ex_style; /* old window extended style */ + unsigned int old_id; /* old window id */ + void* old_instance; /* old creator instance */ + void* old_user_data; /* old user-specific data */ +@END +#define SET_WIN_STYLE 0x01 +#define SET_WIN_EXSTYLE 0x02 +#define SET_WIN_ID 0x04 +#define SET_WIN_INSTANCE 0x08 +#define SET_WIN_USERDATA 0x10 + + /* Get a list of the window parents, up to the root of the tree */ @REQ(get_window_parents) user_handle_t handle; /* handle to the window */ diff --git a/server/request.h b/server/request.h index aae7aeae32f..2d1204fb4cf 100644 --- a/server/request.h +++ b/server/request.h @@ -191,7 +191,9 @@ DECL_HANDLER(get_named_pipe_info); DECL_HANDLER(create_window); DECL_HANDLER(link_window); DECL_HANDLER(destroy_window); +DECL_HANDLER(set_window_owner); DECL_HANDLER(get_window_info); +DECL_HANDLER(set_window_info); DECL_HANDLER(get_window_parents); DECL_HANDLER(get_window_children); DECL_HANDLER(get_window_tree); @@ -333,7 +335,9 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_create_window, (req_handler)req_link_window, (req_handler)req_destroy_window, + (req_handler)req_set_window_owner, (req_handler)req_get_window_info, + (req_handler)req_set_window_info, (req_handler)req_get_window_parents, (req_handler)req_get_window_children, (req_handler)req_get_window_tree, diff --git a/server/trace.c b/server/trace.c index 1d3330ed398..7c68db26aef 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1707,11 +1707,27 @@ static void dump_link_window_request( const struct link_window_request *req ) fprintf( stderr, " previous=%08x", req->previous ); } +static void dump_link_window_reply( const struct link_window_request *req ) +{ + fprintf( stderr, " full_parent=%08x", req->full_parent ); +} + static void dump_destroy_window_request( const struct destroy_window_request *req ) { fprintf( stderr, " handle=%08x", req->handle ); } +static void dump_set_window_owner_request( const struct set_window_owner_request *req ) +{ + fprintf( stderr, " handle=%08x,", req->handle ); + fprintf( stderr, " owner=%08x", req->owner ); +} + +static void dump_set_window_owner_reply( const struct set_window_owner_request *req ) +{ + fprintf( stderr, " full_owner=%08x", req->full_owner ); +} + static void dump_get_window_info_request( const struct get_window_info_request *req ) { fprintf( stderr, " handle=%08x", req->handle ); @@ -1721,7 +1737,28 @@ static void dump_get_window_info_reply( const struct get_window_info_request *re { fprintf( stderr, " full_handle=%08x,", req->full_handle ); fprintf( stderr, " pid=%p,", req->pid ); - fprintf( stderr, " tid=%p", req->tid ); + fprintf( stderr, " tid=%p,", req->tid ); + fprintf( stderr, " atom=%04x", req->atom ); +} + +static void dump_set_window_info_request( const struct set_window_info_request *req ) +{ + fprintf( stderr, " handle=%08x,", req->handle ); + fprintf( stderr, " flags=%08x,", req->flags ); + fprintf( stderr, " style=%08x,", req->style ); + fprintf( stderr, " ex_style=%08x,", req->ex_style ); + fprintf( stderr, " id=%08x,", req->id ); + fprintf( stderr, " instance=%p,", req->instance ); + fprintf( stderr, " user_data=%p", req->user_data ); +} + +static void dump_set_window_info_reply( const struct set_window_info_request *req ) +{ + fprintf( stderr, " old_style=%08x,", req->old_style ); + fprintf( stderr, " old_ex_style=%08x,", req->old_ex_style ); + fprintf( stderr, " old_id=%08x,", req->old_id ); + fprintf( stderr, " old_instance=%p,", req->old_instance ); + fprintf( stderr, " old_user_data=%p", req->old_user_data ); } static void dump_get_window_parents_request( const struct get_window_parents_request *req ) @@ -1970,7 +2007,9 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_window_request, (dump_func)dump_link_window_request, (dump_func)dump_destroy_window_request, + (dump_func)dump_set_window_owner_request, (dump_func)dump_get_window_info_request, + (dump_func)dump_set_window_info_request, (dump_func)dump_get_window_parents_request, (dump_func)dump_get_window_children_request, (dump_func)dump_get_window_tree_request, @@ -2107,9 +2146,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)dump_get_named_pipe_info_reply, (dump_func)dump_create_window_reply, + (dump_func)dump_link_window_reply, (dump_func)0, - (dump_func)0, + (dump_func)dump_set_window_owner_reply, (dump_func)dump_get_window_info_reply, + (dump_func)dump_set_window_info_reply, (dump_func)dump_get_window_parents_reply, (dump_func)dump_get_window_children_reply, (dump_func)dump_get_window_tree_reply, @@ -2248,7 +2289,9 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "create_window", "link_window", "destroy_window", + "set_window_owner", "get_window_info", + "set_window_info", "get_window_parents", "get_window_children", "get_window_tree", diff --git a/server/window.c b/server/window.c index 1559d44928c..c5333aa75d8 100644 --- a/server/window.c +++ b/server/window.c @@ -42,6 +42,11 @@ struct window atom_t atom; /* class atom */ rectangle_t window_rect; /* window rectangle */ rectangle_t client_rect; /* client rectangle */ + unsigned int style; /* window style */ + unsigned int ex_style; /* window extended style */ + unsigned int id; /* window id */ + void* instance; /* creator instance */ + void* user_data; /* user-specific data */ int prop_inuse; /* number of in-use window properties */ int prop_alloc; /* number of allocated window properties */ struct property *properties; /* window properties array */ @@ -81,7 +86,11 @@ static void link_window( struct window *win, struct window *parent, struct windo if (parent) { - win->parent = parent; + if (win->parent != parent) + { + win->owner = NULL; /* reset owner if changing parent */ + win->parent = parent; + } if ((win->prev = previous)) { if ((win->next = previous->next)) win->next->prev = win; @@ -261,6 +270,11 @@ static struct window *create_window( struct window *parent, struct window *owner win->first_unlinked = NULL; win->thread = current; win->atom = atom; + win->style = 0; + win->ex_style = 0; + win->id = 0; + win->instance = NULL; + win->user_data = NULL; win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; @@ -323,6 +337,12 @@ DECL_HANDLER(create_window) if (!(parent = get_window( req->parent ))) return; if (req->owner && !(owner = get_window( req->owner ))) return; + if (owner && owner->parent != parent) + { + /* owner must be a sibling of the new window */ + set_error( STATUS_ACCESS_DENIED ); + return; + } if (!(win = create_window( parent, owner, req->atom ))) return; req->handle = win->handle; } @@ -342,6 +362,7 @@ DECL_HANDLER(link_window) set_error( STATUS_INVALID_PARAMETER ); return; } + req->full_parent = parent ? parent->handle : 0; if (parent && req->previous) { if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */ @@ -376,6 +397,24 @@ DECL_HANDLER(destroy_window) } +/* set a window owner */ +DECL_HANDLER(set_window_owner) +{ + struct window *win = get_window( req->handle ); + struct window *owner = get_window( req->owner ); + + if (!win || !owner) return; + if (owner->parent != win->parent) + { + /* owner has to be a sibling of window */ + set_error( STATUS_ACCESS_DENIED ); + return; + } + win->owner = owner; + req->full_owner = owner->handle; +} + + /* get information from a window handle */ DECL_HANDLER(get_window_info) { @@ -388,13 +427,32 @@ DECL_HANDLER(get_window_info) req->full_handle = win->handle; if (win->thread) { - req->tid = get_thread_id( win->thread ); - req->pid = get_process_id( win->thread->process ); + req->tid = get_thread_id( win->thread ); + req->pid = get_process_id( win->thread->process ); + req->atom = win->atom; } } } +/* set some information in a window */ +DECL_HANDLER(set_window_info) +{ + struct window *win = get_window( req->handle ); + if (!win) return; + req->old_style = win->style; + req->old_ex_style = win->ex_style; + req->old_id = win->id; + req->old_instance = win->instance; + req->old_user_data = win->user_data; + if (req->flags & SET_WIN_STYLE) win->style = req->style; + if (req->flags & SET_WIN_EXSTYLE) win->ex_style = req->ex_style; + if (req->flags & SET_WIN_ID) win->id = req->id; + if (req->flags & SET_WIN_INSTANCE) win->instance = req->instance; + if (req->flags & SET_WIN_USERDATA) win->user_data = req->user_data; +} + + /* get a list of the window parents, up to the root of the tree */ DECL_HANDLER(get_window_parents) { diff --git a/windows/defwnd.c b/windows/defwnd.c index 69649cc48c1..af998c9eeb9 100644 --- a/windows/defwnd.c +++ b/windows/defwnd.c @@ -168,9 +168,7 @@ static void DEFWND_SetRedraw( HWND hwnd, WPARAM wParam ) { if( !bVisible ) { - wndPtr->dwStyle |= WS_VISIBLE; - if (USER_Driver.pSetWindowStyle) - USER_Driver.pSetWindowStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); + WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE ); DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow ); } } @@ -181,9 +179,7 @@ static void DEFWND_SetRedraw( HWND hwnd, WPARAM wParam ) RedrawWindow( hwnd, NULL, 0, wParam ); DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow ); - wndPtr->dwStyle &= ~WS_VISIBLE; - if (USER_Driver.pSetWindowStyle) - USER_Driver.pSetWindowStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE ); + WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); } WIN_ReleaseWndPtr( wndPtr ); } diff --git a/windows/win.c b/windows/win.c index dc85efcb9d7..0c8deea2d03 100644 --- a/windows/win.c +++ b/windows/win.c @@ -362,7 +362,6 @@ void WIN_UnlinkWindow( HWND hwnd ) */ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter ) { - BOOL ret; WND *wndPtr = WIN_GetPtr( hwnd ); if (!wndPtr) return; @@ -377,10 +376,17 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter ) req->handle = hwnd; req->parent = parent; req->previous = hwndInsertAfter; - ret = !SERVER_CALL_ERR(); + if (!SERVER_CALL()) + { + if (req->full_parent && req->full_parent != wndPtr->parent) + { + wndPtr->owner = 0; /* reset owner when changing parent */ + wndPtr->parent = req->full_parent; + } + } + } SERVER_END_REQ; - if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent); WIN_ReleasePtr( wndPtr ); } @@ -392,12 +398,102 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter ) */ void WIN_SetOwner( HWND hwnd, HWND owner ) { - WND *win = WIN_FindWndPtr( hwnd ); - if (win) + WND *win = WIN_GetPtr( hwnd ); + + if (!win) return; + if (win == WND_OTHER_PROCESS) { - win->owner = owner; - WIN_ReleaseWndPtr( win ); + if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd ); + return; } + SERVER_START_REQ( set_window_owner ) + { + req->handle = hwnd; + req->owner = owner; + if (!SERVER_CALL()) win->owner = req->full_owner; + } + SERVER_END_REQ; + WIN_ReleasePtr( win ); +} + + +/*********************************************************************** + * WIN_SetStyle + * + * Change the style of a window. + */ +LONG WIN_SetStyle( HWND hwnd, LONG style ) +{ + BOOL ok; + LONG ret = 0; + WND *win = WIN_GetPtr( hwnd ); + + if (!win) return 0; + if (win == WND_OTHER_PROCESS) + { + if (IsWindow(hwnd)) + ERR( "cannot set style %lx on other process window %x\n", style, hwnd ); + return 0; + } + if (style == win->dwStyle) + { + WIN_ReleasePtr( win ); + return style; + } + SERVER_START_REQ( set_window_info ) + { + req->handle = hwnd; + req->flags = SET_WIN_STYLE; + req->style = style; + if ((ok = !SERVER_CALL())) + { + ret = req->old_style; + win->dwStyle = style; + } + } + SERVER_END_REQ; + WIN_ReleasePtr( win ); + if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret ); + return ret; +} + + +/*********************************************************************** + * WIN_SetExStyle + * + * Change the extended style of a window. + */ +LONG WIN_SetExStyle( HWND hwnd, LONG style ) +{ + LONG ret = 0; + WND *win = WIN_GetPtr( hwnd ); + + if (!win) return 0; + if (win == WND_OTHER_PROCESS) + { + if (IsWindow(hwnd)) + ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd ); + return 0; + } + if (style == win->dwExStyle) + { + WIN_ReleasePtr( win ); + return style; + } + SERVER_START_REQ( set_window_info ) + { + req->handle = hwnd; + req->flags = SET_WIN_EXSTYLE; + req->ex_style = style; + if (!SERVER_CALL()) + { + ret = req->old_ex_style; + win->dwExStyle = style; + } + } + SERVER_END_REQ; + WIN_ReleasePtr( win ); + return ret; } @@ -603,11 +699,10 @@ LRESULT WIN_DestroyWindow( HWND hwnd ) wndPtr->hmemTaskQ = 0; if (!(wndPtr->dwStyle & WS_CHILD)) - if (wndPtr->wIDmenu) - { - DestroyMenu( wndPtr->wIDmenu ); - wndPtr->wIDmenu = 0; - } + { + HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 ); + if (menu) DestroyMenu( menu ); + } if (wndPtr->hSysMenu) { DestroyMenu( wndPtr->hSysMenu ); @@ -682,8 +777,7 @@ BOOL WIN_CreateDesktopWindow(void) pWndDesktop->hmemTaskQ = 0; pWndDesktop->hrgnUpdate = 0; pWndDesktop->hwndLastActive = hwndDesktop; - pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | - WS_CLIPSIBLINGS; + pWndDesktop->dwStyle = 0; pWndDesktop->dwExStyle = 0; pWndDesktop->clsStyle = clsStyle; pWndDesktop->dce = NULL; @@ -712,6 +806,7 @@ BOOL WIN_CreateDesktopWindow(void) SetRect( &rect, 0, 0, cs.cx, cs.cy ); WIN_SetRectangles( hwndDesktop, &rect, &rect ); + WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ); if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE; @@ -798,11 +893,9 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, struct tagCLASS *classPtr; WND *wndPtr; HWND hwnd, hwndLinkAfter, parent, owner; - POINT maxSize, maxPos, minTrack, maxTrack; INT wndExtra; DWORD clsStyle; WNDPROC winproc; - RECT rect; DCE *dce; BOOL unicode = (type == WIN_PROC_32W); @@ -924,8 +1017,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, TRACE("CBT-hook returned 0\n"); free_window_handle( hwnd ); CLASS_RemoveWindow( classPtr ); - hwnd = 0; - goto end; + WIN_ReleaseWndPtr(wndPtr); + return 0; } } @@ -940,6 +1033,16 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->flags |= WIN_NEED_SIZE; } } + SERVER_START_REQ( set_window_info ) + { + req->handle = hwnd; + req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE; + req->style = wndPtr->dwStyle; + req->ex_style = wndPtr->dwExStyle; + req->instance = (void *)wndPtr->hInstance; + SERVER_CALL(); + } + SERVER_END_REQ; /* Get class or window DC if needed */ @@ -947,28 +1050,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce; else wndPtr->dce = NULL; - /* Initialize the dimensions before sending WM_GETMINMAXINFO */ - - 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 */ - - if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) - { - WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack); - if (maxSize.x < cs->cx) cs->cx = maxSize.x; - if (maxSize.y < cs->cy) cs->cy = maxSize.y; - if (cs->cx < minTrack.x ) cs->cx = minTrack.x; - if (cs->cy < minTrack.y ) cs->cy = minTrack.y; - } - - if (cs->cx < 0) cs->cx = 0; - if (cs->cy < 0) cs->cy = 0; - - SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy ); - WIN_SetRectangles( hwnd, &rect, &rect ); - /* Set the window menu */ if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION ) @@ -988,41 +1069,35 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, } } } - else wndPtr->wIDmenu = (UINT)cs->hMenu; + else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu ); + WIN_ReleaseWndPtr( wndPtr ); if (!USER_Driver.pCreateWindow( hwnd, cs, unicode)) { - WARN("aborted by WM_xxCREATE!\n"); - WIN_ReleaseWndPtr( wndPtr ); WIN_DestroyWindow( hwnd ); - CLASS_RemoveWindow( classPtr ); return 0; } /* Notify the parent window only */ send_parent_notify( hwnd, WM_CREATE ); - if( !IsWindow(hwnd) ) - { - hwnd = 0; - goto end; - } + if (!IsWindow( hwnd )) return 0; if (cs->style & WS_VISIBLE) { /* in case WS_VISIBLE got set in the meantime */ - wndPtr->dwStyle &= ~WS_VISIBLE; + if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0; + WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE ); + WIN_ReleasePtr( wndPtr ); ShowWindow( hwnd, sw ); } /* Call WH_SHELL hook */ - if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) + if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 ); TRACE("created window %04x\n", hwnd); - end: - WIN_ReleaseWndPtr(wndPtr); return hwnd; } @@ -1524,27 +1599,31 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable ) { WND *wndPtr; BOOL retvalue; + LONG style; + HWND full_handle; + + if (!(full_handle = WIN_IsCurrentThread( hwnd ))) + return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 ); + + hwnd = full_handle; TRACE("( %x, %d )\n", hwnd, enable); - if (USER_Driver.pEnableWindow) - return USER_Driver.pEnableWindow( hwnd, enable ); + if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE; + style = wndPtr->dwStyle; + retvalue = ((style & WS_DISABLED) != 0); + WIN_ReleasePtr( wndPtr ); - if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE; - hwnd = wndPtr->hwndSelf; /* make it a full handle */ - - retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0); - - if (enable && (wndPtr->dwStyle & WS_DISABLED)) + if (enable && retvalue) { - wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */ + WIN_SetStyle( hwnd, style & ~WS_DISABLED ); SendMessageA( hwnd, WM_ENABLE, TRUE, 0 ); } - else if (!enable && !(wndPtr->dwStyle & WS_DISABLED)) + else if (!enable && !retvalue) { SendMessageA( hwnd, WM_CANCELMODE, 0, 0); - wndPtr->dwStyle |= WS_DISABLED; /* Disable window */ + WIN_SetStyle( hwnd, style | WS_DISABLED ); if (hwnd == GetFocus()) SetFocus( 0 ); /* A disabled window can't have the focus */ @@ -1554,7 +1633,6 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable ) SendMessageA( hwnd, WM_ENABLE, FALSE, 0 ); } - WIN_ReleaseWndPtr(wndPtr); return retvalue; } @@ -1588,22 +1666,32 @@ BOOL WINAPI IsWindowUnicode( HWND hwnd ) */ WORD WINAPI GetWindowWord( HWND hwnd, INT offset ) { - WORD retvalue; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return 0; if (offset >= 0) { - if (offset + sizeof(WORD) > wndPtr->cbWndExtra) + WORD retvalue = 0; + WND *wndPtr = WIN_GetPtr( hwnd ); + if (!wndPtr) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (wndPtr == WND_OTHER_PROCESS) + { + if (IsWindow( hwnd )) + FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd ); + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (offset > wndPtr->cbWndExtra - sizeof(WORD)) { WARN("Invalid offset %d\n", offset ); - retvalue = 0; + SetLastError( ERROR_INVALID_INDEX ); } else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset); - WIN_ReleaseWndPtr(wndPtr); + WIN_ReleasePtr( wndPtr ); return retvalue; } - WIN_ReleaseWndPtr(wndPtr); switch(offset) { case GWL_HWNDPARENT: @@ -1629,24 +1717,8 @@ WORD WINAPI GetWindowWord( HWND hwnd, INT offset ) WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval ) { WORD *ptr, retval; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return 0; - if (offset >= 0) - { - if (offset + sizeof(WORD) > wndPtr->cbWndExtra) - { - WARN("Invalid offset %d\n", offset ); - WIN_ReleaseWndPtr(wndPtr); - return 0; - } - ptr = (WORD *)(((char *)wndPtr->wExtra) + offset); - retval = *ptr; - *ptr = newval; - WIN_ReleaseWndPtr(wndPtr); - return retval; - } + WND * wndPtr; - WIN_ReleaseWndPtr(wndPtr); switch(offset) { case GWL_ID: @@ -1654,9 +1726,40 @@ WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval ) case GWL_HWNDPARENT: return SetWindowLongW( hwnd, offset, (UINT)newval ); default: + if (offset < 0) + { + WARN("Invalid offset %d\n", offset ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } + } + + wndPtr = WIN_GetPtr( hwnd ); + if (wndPtr == WND_OTHER_PROCESS) + { + if (IsWindow(hwnd)) + FIXME( "set %d <- %x not supported yet on other process window %x\n", + offset, newval, hwnd ); + wndPtr = NULL; + } + if (!wndPtr) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + + if (offset > wndPtr->cbWndExtra - sizeof(WORD)) + { WARN("Invalid offset %d\n", offset ); + WIN_ReleasePtr(wndPtr); + SetLastError( ERROR_INVALID_INDEX ); return 0; } + ptr = (WORD *)(((char *)wndPtr->wExtra) + offset); + retval = *ptr; + *ptr = newval; + WIN_ReleasePtr(wndPtr); + return retval; } @@ -1667,49 +1770,87 @@ WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval ) */ static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type ) { - LONG retvalue; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return 0; + LONG retvalue = 0; + WND *wndPtr; + + if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd ); + + if (!(wndPtr = WIN_GetPtr( hwnd ))) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + + if (wndPtr == WND_OTHER_PROCESS) + { + if (offset >= 0) + { + FIXME( "(%d) not supported on other process window %x\n", offset, hwnd ); + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (offset == GWL_WNDPROC) + { + SetLastError( ERROR_ACCESS_DENIED ); + return 0; + } + SERVER_START_REQ( set_window_info ) + { + req->handle = hwnd; + req->flags = 0; /* don't set anything, just retrieve */ + if (!SERVER_CALL_ERR()) + { + switch(offset) + { + case GWL_STYLE: retvalue = req->style; break; + case GWL_EXSTYLE: retvalue = req->ex_style; break; + case GWL_ID: retvalue = req->id; break; + case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break; + case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break; + default: + SetLastError( ERROR_INVALID_INDEX ); + break; + } + } + } + SERVER_END_REQ; + return retvalue; + } + + /* now we have a valid wndPtr */ + if (offset >= 0) { - if (offset + sizeof(LONG) > wndPtr->cbWndExtra) + if (offset > wndPtr->cbWndExtra - sizeof(LONG)) { WARN("Invalid offset %d\n", offset ); - retvalue = 0; - goto end; + WIN_ReleasePtr( wndPtr ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; } - retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset); /* Special case for dialog window procedure */ if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG)) - { retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type ); - goto end; - } - goto end; + else + retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset); + WIN_ReleasePtr( wndPtr ); + return retvalue; } + switch(offset) { - case GWL_USERDATA: retvalue = wndPtr->userdata; - goto end; - case GWL_STYLE: retvalue = wndPtr->dwStyle; - goto end; - case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; - goto end; - case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; - goto end; - case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, - type ); - goto end; - case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd); - goto end; - case GWL_HINSTANCE: retvalue = wndPtr->hInstance; - goto end; - default: - WARN("Unknown offset %d\n", offset ); + case GWL_USERDATA: retvalue = wndPtr->userdata; break; + case GWL_STYLE: retvalue = wndPtr->dwStyle; break; + case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break; + case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break; + case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break; + case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break; + default: + WARN("Unknown offset %d\n", offset ); + SetLastError( ERROR_INVALID_INDEX ); + break; } - retvalue = 0; -end: - WIN_ReleaseWndPtr(wndPtr); + WIN_ReleasePtr(wndPtr); return retvalue; } @@ -1721,99 +1862,148 @@ end: * * 0 is the failure code. However, in the case of failure SetLastError * must be set to distinguish between a 0 return value and a failure. - * - * FIXME: The error values for SetLastError may not be right. Can - * someone check with the real thing? */ static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval, WINDOWPROCTYPE type ) { - LONG *ptr, retval; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - STYLESTRUCT style; + LONG retval = 0; + WND *wndPtr; - TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type); + TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type ); - if (!wndPtr) + if (!WIN_IsCurrentThread( hwnd )) { - /* Is this the right error? */ - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return 0; + ERR("set %x %d %x\n", hwnd, offset, newval ); + return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval ); } + wndPtr = WIN_GetPtr( hwnd ); + if (offset >= 0) { - if (offset + sizeof(LONG) > wndPtr->cbWndExtra) + LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset); + if (offset > wndPtr->cbWndExtra - sizeof(LONG)) { WARN("Invalid offset %d\n", offset ); - - /* Is this the right error? */ - SetLastError( ERROR_OUTOFMEMORY ); - - retval = 0; - goto end; + WIN_ReleasePtr( wndPtr ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; } - ptr = (LONG *)(((char *)wndPtr->wExtra) + offset); /* Special case for dialog window procedure */ if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG)) { retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type ); WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type, WIN_PROC_WINDOW ); - goto end; + WIN_ReleasePtr( wndPtr ); + return retval; } + retval = *ptr; + *ptr = newval; + WIN_ReleasePtr( wndPtr ); } - else switch(offset) + else { - case GWL_ID: - ptr = (DWORD*)&wndPtr->wIDmenu; - break; - case GWL_HINSTANCE: - ptr = (DWORD*)&wndPtr->hInstance; - break; - case GWL_USERDATA: - ptr = &wndPtr->userdata; - break; - case GWL_HWNDPARENT: - retval = SetParent( hwnd, (HWND)newval ); - goto end; - case GWL_WNDPROC: - retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); - WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, - type, WIN_PROC_WINDOW ); - goto end; - case GWL_STYLE: - retval = wndPtr->dwStyle; - style.styleOld = wndPtr->dwStyle; - style.styleNew = newval; - SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style); - wndPtr->dwStyle = style.styleNew; - if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval ); - SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style); - retval = style.styleOld; - goto end; + STYLESTRUCT style; + BOOL ok; + + /* first some special cases */ + switch( offset ) + { + case GWL_STYLE: case GWL_EXSTYLE: - style.styleOld = wndPtr->dwExStyle; - style.styleNew = newval; - SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style); - wndPtr->dwExStyle = style.styleNew; - SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style); - retval = style.styleOld; - goto end; - - default: + style.styleOld = wndPtr->dwStyle; + style.styleNew = newval; + WIN_ReleasePtr( wndPtr ); + SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style ); + if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0; + newval = style.styleNew; + break; + case GWL_HWNDPARENT: + WIN_ReleasePtr( wndPtr ); + return (LONG)SetParent( hwnd, (HWND)newval ); + case GWL_WNDPROC: + retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); + WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, + type, WIN_PROC_WINDOW ); + WIN_ReleasePtr( wndPtr ); + return retval; + case GWL_ID: + case GWL_HINSTANCE: + case GWL_USERDATA: + break; + default: + WIN_ReleasePtr( wndPtr ); WARN("Invalid offset %d\n", offset ); + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } - /* Don't think this is right error but it should do */ - SetLastError( ERROR_OUTOFMEMORY ); + SERVER_START_REQ( set_window_info ) + { + req->handle = hwnd; + switch(offset) + { + case GWL_STYLE: + req->flags = SET_WIN_STYLE; + req->style = newval; + break; + case GWL_EXSTYLE: + req->flags = SET_WIN_EXSTYLE; + req->ex_style = newval; + break; + case GWL_ID: + req->flags = SET_WIN_ID; + req->id = newval; + break; + case GWL_HINSTANCE: + req->flags = SET_WIN_INSTANCE; + req->instance = (void *)newval; + break; + case GWL_USERDATA: + req->flags = SET_WIN_USERDATA; + req->user_data = (void *)newval; + break; + } + if ((ok = !SERVER_CALL_ERR())) + { + switch(offset) + { + case GWL_STYLE: + wndPtr->dwStyle = newval; + retval = req->old_style; + break; + case GWL_EXSTYLE: + wndPtr->dwExStyle = newval; + retval = req->old_ex_style; + break; + case GWL_ID: + wndPtr->wIDmenu = newval; + retval = req->old_id; + break; + case GWL_HINSTANCE: + wndPtr->hInstance = newval; + retval = (HINSTANCE)req->old_instance; + break; + case GWL_USERDATA: + wndPtr->userdata = newval; + retval = (ULONG_PTR)req->old_user_data; + break; + } + } + } + SERVER_END_REQ; + WIN_ReleasePtr( wndPtr ); + + if (!ok) return 0; + + if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle) + USER_Driver.pSetWindowStyle( hwnd, retval ); + + if (offset == GWL_STYLE || offset == GWL_EXSTYLE) + SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style ); - retval = 0; - goto end; } - retval = *ptr; - *ptr = newval; -end: - WIN_ReleaseWndPtr(wndPtr); return retval; } @@ -1928,15 +2118,6 @@ LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval ) * it sends WM_STYLECHANGING before changing the settings * and WM_STYLECHANGED afterwards. * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST. - * - * BUGS - * - * GWL_STYLE does not dispatch WM_STYLE... messages. - * - * CONFORMANCE - * - * ECMA-234, Win32 - * */ LONG WINAPI SetWindowLongW( HWND hwnd, /* [in] window to alter */ @@ -2089,13 +2270,33 @@ HWND WINAPI GetParent( HWND hwnd ) WND *wndPtr; HWND retvalue = 0; - if ((wndPtr = WIN_FindWndPtr(hwnd))) + if (!(wndPtr = WIN_GetPtr( hwnd ))) { - if (wndPtr->dwStyle & WS_CHILD) - retvalue = wndPtr->parent; - else if (wndPtr->dwStyle & WS_POPUP) - retvalue = wndPtr->owner; - WIN_ReleaseWndPtr(wndPtr); + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (wndPtr == WND_OTHER_PROCESS) + { + LONG style = GetWindowLongW( hwnd, GWL_STYLE ); + if (style & (WS_POPUP | WS_CHILD)) + { + SERVER_START_REQ( get_window_tree ) + { + req->handle = hwnd; + if (!SERVER_CALL_ERR()) + { + if (style & WS_CHILD) retvalue = req->parent; + else retvalue = req->owner; + } + } + SERVER_END_REQ; + } + } + else + { + if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent; + else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner; + WIN_ReleasePtr( wndPtr ); } return retvalue; } @@ -2106,8 +2307,30 @@ HWND WINAPI GetParent( HWND hwnd ) */ HWND WINAPI GetAncestor( HWND hwnd, UINT type ) { + WND *win; HWND ret = 0; - size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE; + size_t size; + + for (;;) + { + if (!(win = WIN_GetPtr( hwnd ))) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */ + ret = win->parent; + WIN_ReleasePtr( win ); + if (type == GA_PARENT) return ret; + if (!ret || ret == GetDesktopWindow()) + { + ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */ + goto done; + } + hwnd = ret; /* restart with parent as hwnd */ + } + + size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE; SERVER_START_VAR_REQ( get_window_parents, size ) { @@ -2134,6 +2357,7 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type ) } SERVER_END_VAR_REQ; + done: if (ret && type == GA_ROOTOWNER) { for (;;) @@ -2148,16 +2372,28 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type ) /***************************************************************** - * WIN_SetParent - * - * Implementation of SetParent, runs in the thread owning the window. + * SetParent (USER32.@) */ -HWND WIN_SetParent( HWND hwnd, HWND parent ) +HWND WINAPI SetParent( HWND hwnd, HWND parent ) { WND *wndPtr; - HWND retvalue; + HWND retvalue, full_handle; BOOL was_visible; + 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 SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 ); + + hwnd = full_handle; + if (USER_Driver.pSetParent) return USER_Driver.pSetParent( hwnd, parent ); @@ -2196,34 +2432,6 @@ HWND WIN_SetParent( HWND hwnd, HWND parent ) } -/***************************************************************** - * 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.@) */ @@ -2305,13 +2513,21 @@ HWND WINAPI GetWindow( HWND hwnd, UINT rel ) { HWND retval = 0; - if (rel == GW_OWNER) /* special case: not fully supported in the server yet */ + if (rel == GW_OWNER) /* this one may be available locally */ { - WND *wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return 0; - retval = wndPtr->owner; - WIN_ReleaseWndPtr( wndPtr ); - return retval; + WND *wndPtr = WIN_GetPtr( hwnd ); + if (!wndPtr) + { + SetLastError( ERROR_INVALID_HANDLE ); + return 0; + } + if (wndPtr != WND_OTHER_PROCESS) + { + retval = wndPtr->owner; + WIN_ReleasePtr( wndPtr ); + return retval; + } + /* else fall through to server call */ } SERVER_START_REQ( get_window_tree ) @@ -2333,6 +2549,9 @@ HWND WINAPI GetWindow( HWND hwnd, UINT rel ) case GW_HWNDPREV: retval = req->prev_sibling; break; + case GW_OWNER: + retval = req->owner; + break; case GW_CHILD: retval = req->first_child; break; diff --git a/windows/winpos.c b/windows/winpos.c index 448e448eab3..f288fcbfaa3 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -215,15 +215,25 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) { int nRet = ERROR; - WND *wndPtr = WIN_FindWndPtr( hwnd ); - if (wndPtr) + WND *wndPtr = WIN_GetPtr( hwnd ); + + if (wndPtr == WND_OTHER_PROCESS) { - if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY ); - WIN_ReleaseWndPtr(wndPtr); + if (IsWindow( hwnd )) + FIXME( "not supported on other process window %x\n", hwnd ); + wndPtr = NULL; } + if (!wndPtr) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return ERROR; + } + if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY ); + WIN_ReleasePtr( wndPtr ); return nRet; } + /*********************************************************************** * SetWindowRgn (USER32.@) */ @@ -231,22 +241,31 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) { RECT rect; WND *wndPtr; - int ret = FALSE; + + if (hrgn) /* verify that region really exists */ + { + if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE; + } if (USER_Driver.pSetWindowRgn) return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw ); - if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE; + if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS) + { + if (IsWindow( hwnd )) + FIXME( "not supported on other process window %x\n", hwnd ); + wndPtr = NULL; + } + if (!wndPtr) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } if (wndPtr->hrgnWnd == hrgn) { - ret = TRUE; - goto done; - } - - if (hrgn) /* verify that region really exists */ - { - if (GetRgnBox( hrgn, &rect ) == ERROR) goto done; + WIN_ReleasePtr( wndPtr ); + return TRUE; } if (wndPtr->hrgnWnd) @@ -256,17 +275,14 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) wndPtr->hrgnWnd = 0; } wndPtr->hrgnWnd = hrgn; + WIN_ReleasePtr( wndPtr ); /* Size the window to the rectangle of the new region (if it isn't NULL) */ if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) ); - ret = TRUE; - - done: - WIN_ReleaseWndPtr(wndPtr); - return ret; + return TRUE; }