Fixed a number of bugs in the handling of window parent and owner and
added a regression test (based on the work of Bill Medland).
This commit is contained in:
parent
e70d08be31
commit
7dafa61700
|
@ -3,4 +3,5 @@ class.ok
|
||||||
sysparams.ok
|
sysparams.ok
|
||||||
testlist.c
|
testlist.c
|
||||||
user32_test.exe.spec.c
|
user32_test.exe.spec.c
|
||||||
|
win.ok
|
||||||
wsprintf.ok
|
wsprintf.ok
|
||||||
|
|
|
@ -8,6 +8,7 @@ IMPORTS = user32 gdi32 advapi32
|
||||||
CTESTS = \
|
CTESTS = \
|
||||||
class.c \
|
class.c \
|
||||||
sysparams.c \
|
sysparams.c \
|
||||||
|
win.c \
|
||||||
wsprintf.c
|
wsprintf.c
|
||||||
|
|
||||||
@MAKE_TEST_RULES@
|
@MAKE_TEST_RULES@
|
||||||
|
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*
|
||||||
|
* Unit tests for window handling
|
||||||
|
*
|
||||||
|
* Copyright 2002 Bill Medland
|
||||||
|
* Copyright 2002 Alexandre Julliard
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
static HWND (WINAPI *pGetAncestor)(HWND,UINT);
|
||||||
|
|
||||||
|
static HWND hwndMain, hwndMain2;
|
||||||
|
|
||||||
|
/* check the values returned by the various parent/owner functions on a given window */
|
||||||
|
static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
|
||||||
|
HWND gw_owner, HWND ga_root, HWND ga_root_owner )
|
||||||
|
{
|
||||||
|
HWND res;
|
||||||
|
|
||||||
|
if (pGetAncestor)
|
||||||
|
{
|
||||||
|
res = pGetAncestor( hwnd, GA_PARENT );
|
||||||
|
ok( res == ga_parent, "Wrong result for GA_PARENT %x expected %x", res, ga_parent );
|
||||||
|
}
|
||||||
|
res = GetWindowLongW( hwnd, GWL_HWNDPARENT );
|
||||||
|
ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %x expected %x", res, gwl_parent );
|
||||||
|
res = GetParent( hwnd );
|
||||||
|
ok( res == get_parent, "Wrong result for GetParent %x expected %x", res, get_parent );
|
||||||
|
res = GetWindow( hwnd, GW_OWNER );
|
||||||
|
ok( res == gw_owner, "Wrong result for GW_OWNER %x expected %x", res, gw_owner );
|
||||||
|
if (pGetAncestor)
|
||||||
|
{
|
||||||
|
res = pGetAncestor( hwnd, GA_ROOT );
|
||||||
|
ok( res == ga_root, "Wrong result for GA_ROOT %x expected %x", res, ga_root );
|
||||||
|
res = pGetAncestor( hwnd, GA_ROOTOWNER );
|
||||||
|
ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %x expected %x", res, ga_root_owner );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static HWND create_tool_window( LONG style, HWND parent )
|
||||||
|
{
|
||||||
|
HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
|
||||||
|
0, 0, 100, 100, parent, 0, 0, NULL );
|
||||||
|
ok( ret != 0, "Creation failed" );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test parent and owner values for various combinations */
|
||||||
|
static void test_parent_owner(void)
|
||||||
|
{
|
||||||
|
LONG style;
|
||||||
|
HWND test, owner, ret;
|
||||||
|
HWND desktop = GetDesktopWindow();
|
||||||
|
HWND child = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
|
||||||
|
trace( "main window %x main2 %x desktop %x child %x\n", hwndMain, hwndMain2, desktop, child );
|
||||||
|
|
||||||
|
/* child without parent, should fail */
|
||||||
|
test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
|
||||||
|
WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
|
||||||
|
ok( !test, "WS_CHILD without parent created" );
|
||||||
|
|
||||||
|
/* desktop window */
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
style = GetWindowLongW( desktop, GWL_STYLE );
|
||||||
|
ok( !SetWindowLongW( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded" );
|
||||||
|
ok( !SetWindowLongW( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded" );
|
||||||
|
ok( GetWindowLongW( desktop, GWL_STYLE ) == style, "Desktop style changed" );
|
||||||
|
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %x\n", test );
|
||||||
|
check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP|WS_CHILD );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_CHILD );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of desktop */
|
||||||
|
test = create_tool_window( WS_CHILD, desktop );
|
||||||
|
trace( "created child of desktop %x\n", test );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of child */
|
||||||
|
test = create_tool_window( WS_CHILD, child );
|
||||||
|
trace( "created child of child %x\n", test );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %x\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned top-level window */
|
||||||
|
test = create_tool_window( 0, hwndMain );
|
||||||
|
trace( "created owned top-level %x\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created popup %x\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, hwndMain );
|
||||||
|
trace( "created owned popup %x\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
|
||||||
|
SetWindowLongW( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* top-level window owned by child (same as owned by top-level) */
|
||||||
|
test = create_tool_window( 0, child );
|
||||||
|
trace( "created top-level owned by child %x\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by desktop (same as not owned) */
|
||||||
|
test = create_tool_window( WS_POPUP, desktop );
|
||||||
|
trace( "created popup owned by desktop %x\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by child (same as owned by top-level) */
|
||||||
|
test = create_tool_window( WS_POPUP, child );
|
||||||
|
trace( "created popup owned by child %x\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup with WS_CHILD (same as WS_POPUP only) */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
|
||||||
|
trace( "created WS_CHILD popup %x\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup with WS_CHILD (same as WS_POPUP only) */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
|
||||||
|
trace( "created owned WS_CHILD popup %x\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/******************** parent changes *************************/
|
||||||
|
trace( "testing parent changes\n" );
|
||||||
|
|
||||||
|
/* desktop window */
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, hwndMain2 );
|
||||||
|
ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop" );
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop" );
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %x\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, hwndMain2 );
|
||||||
|
ok( ret == hwndMain, "GWL_HWNDPARENT return value %x expected %x", ret, hwndMain );
|
||||||
|
check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %x expected %x", ret, hwndMain2 );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, desktop );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
|
||||||
|
/* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, child );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %x expected %x", ret, 0 );
|
||||||
|
check_parents( test, desktop, child, desktop, child, test, desktop );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %x\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, hwndMain2 );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %x expected %x", ret, 0 );
|
||||||
|
check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %x expected %x", ret, hwndMain2 );
|
||||||
|
check_parents( test, desktop, child, 0, child, test, test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created popup %x\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, hwndMain2 );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %x expected %x", ret, 0 );
|
||||||
|
check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %x expected %x", ret, hwndMain2 );
|
||||||
|
check_parents( test, desktop, child, child, child, test, hwndMain );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %x\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, desktop );
|
||||||
|
ok( ret == hwndMain, "SetParent return value %x expected %x", ret, hwndMain );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %x expected %x", ret, desktop );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
|
||||||
|
ret = SetParent( test, hwndMain2 );
|
||||||
|
ok( ret == child, "SetParent return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %x\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %x expected %x", ret, desktop );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, hwndMain2 );
|
||||||
|
trace( "created owned popup %x\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %x expected %x", ret, desktop );
|
||||||
|
check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, hwndMain );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %x expected %x", ret, child );
|
||||||
|
check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/**************** test owner destruction *******************/
|
||||||
|
|
||||||
|
/* owned child popup */
|
||||||
|
owner = create_tool_window( 0, 0 );
|
||||||
|
test = create_tool_window( WS_POPUP, owner );
|
||||||
|
trace( "created owner %x and popup %x\n", owner, test );
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %x expected %x", ret, desktop );
|
||||||
|
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||||
|
/* window is now child of 'child' but owned by 'owner' */
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( IsWindow(test), "Window %x destroyed by owner destruction", test );
|
||||||
|
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||||
|
ok( !IsWindow(owner), "Owner %x not destroyed", owner );
|
||||||
|
DestroyWindow(test);
|
||||||
|
|
||||||
|
/* owned top-level popup */
|
||||||
|
owner = create_tool_window( 0, 0 );
|
||||||
|
test = create_tool_window( WS_POPUP, owner );
|
||||||
|
trace( "created owner %x and popup %x\n", owner, test );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( !IsWindow(test), "Window %x not destroyed by owner destruction", test );
|
||||||
|
|
||||||
|
/* top-level popup owned by child */
|
||||||
|
owner = create_tool_window( WS_CHILD, hwndMain2 );
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created owner %x and popup %x\n", owner, test );
|
||||||
|
ret = (HWND)SetWindowLongW( test, GWL_HWNDPARENT, owner );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %x expected %x", ret, 0 );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( IsWindow(test), "Window %x destroyed by owner destruction", test );
|
||||||
|
ok( !IsWindow(owner), "Owner %x not destroyed", owner );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||||
|
DestroyWindow(test);
|
||||||
|
|
||||||
|
/* final cleanup */
|
||||||
|
DestroyWindow(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL RegisterWindowClasses(void)
|
||||||
|
{
|
||||||
|
WNDCLASSA cls;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = DefWindowProcA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, IDC_ARROWA);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "MainWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = DefWindowProcA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, IDC_ARROWA);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "ToolWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST(win)
|
||||||
|
{
|
||||||
|
pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
|
||||||
|
|
||||||
|
if (!RegisterWindowClasses()) assert(0);
|
||||||
|
|
||||||
|
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
|
||||||
|
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||||
|
WS_MAXIMIZEBOX | WS_POPUP,
|
||||||
|
100, 100, 200, 200,
|
||||||
|
0, 0, 0, NULL);
|
||||||
|
hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
|
||||||
|
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||||
|
WS_MAXIMIZEBOX | WS_POPUP,
|
||||||
|
100, 100, 200, 200,
|
||||||
|
0, 0, 0, NULL);
|
||||||
|
assert( hwndMain );
|
||||||
|
assert( hwndMain2 );
|
||||||
|
|
||||||
|
test_parent_owner();
|
||||||
|
}
|
|
@ -102,7 +102,7 @@ extern HWND WIN_IsCurrentProcess( HWND hwnd );
|
||||||
extern HWND WIN_IsCurrentThread( HWND hwnd );
|
extern HWND WIN_IsCurrentThread( HWND hwnd );
|
||||||
extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
|
extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
|
||||||
extern void WIN_UnlinkWindow( HWND hwnd );
|
extern void WIN_UnlinkWindow( HWND hwnd );
|
||||||
extern void WIN_SetOwner( HWND hwnd, HWND owner );
|
extern HWND WIN_SetOwner( HWND hwnd, HWND owner );
|
||||||
extern LONG WIN_SetStyle( HWND hwnd, LONG style );
|
extern LONG WIN_SetStyle( HWND hwnd, LONG style );
|
||||||
extern LONG WIN_SetExStyle( HWND hwnd, LONG style );
|
extern LONG WIN_SetExStyle( HWND hwnd, LONG style );
|
||||||
extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
|
extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
|
||||||
|
|
|
@ -2491,6 +2491,7 @@ struct set_window_owner_reply
|
||||||
{
|
{
|
||||||
struct reply_header __header;
|
struct reply_header __header;
|
||||||
user_handle_t full_owner;
|
user_handle_t full_owner;
|
||||||
|
user_handle_t prev_owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3210,6 +3211,6 @@ union generic_reply
|
||||||
struct get_window_properties_reply get_window_properties_reply;
|
struct get_window_properties_reply get_window_properties_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 82
|
#define SERVER_PROTOCOL_VERSION 83
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -1751,6 +1751,7 @@ enum message_type
|
||||||
user_handle_t owner; /* new owner */
|
user_handle_t owner; /* new owner */
|
||||||
@REPLY
|
@REPLY
|
||||||
user_handle_t full_owner; /* full handle of new owner */
|
user_handle_t full_owner; /* full handle of new owner */
|
||||||
|
user_handle_t prev_owner; /* full handle of previous owner */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1993,7 +1993,8 @@ static void dump_set_window_owner_request( const struct set_window_owner_request
|
||||||
|
|
||||||
static void dump_set_window_owner_reply( const struct set_window_owner_reply *req )
|
static void dump_set_window_owner_reply( const struct set_window_owner_reply *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " full_owner=%08x", req->full_owner );
|
fprintf( stderr, " full_owner=%08x,", req->full_owner );
|
||||||
|
fprintf( stderr, " prev_owner=%08x", req->prev_owner );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_window_info_request( const struct get_window_info_request *req )
|
static void dump_get_window_info_request( const struct get_window_info_request *req )
|
||||||
|
|
|
@ -53,7 +53,7 @@ enum property_type
|
||||||
struct window
|
struct window
|
||||||
{
|
{
|
||||||
struct window *parent; /* parent window */
|
struct window *parent; /* parent window */
|
||||||
struct window *owner; /* owner of this window */
|
user_handle_t owner; /* owner of this window */
|
||||||
struct window *first_child; /* first child in Z-order */
|
struct window *first_child; /* first child in Z-order */
|
||||||
struct window *last_child; /* last child in Z-order */
|
struct window *last_child; /* last child in Z-order */
|
||||||
struct window *first_unlinked; /* first child not linked in the Z-order list */
|
struct window *first_unlinked; /* first child not linked in the Z-order list */
|
||||||
|
@ -110,11 +110,7 @@ static void link_window( struct window *win, struct window *parent, struct windo
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
if (win->parent != parent)
|
win->parent = parent;
|
||||||
{
|
|
||||||
win->owner = NULL; /* reset owner if changing parent */
|
|
||||||
win->parent = parent;
|
|
||||||
}
|
|
||||||
if ((win->prev = previous))
|
if ((win->prev = previous))
|
||||||
{
|
{
|
||||||
if ((win->next = previous->next)) win->next->prev = win;
|
if ((win->next = previous->next)) win->next->prev = win;
|
||||||
|
@ -241,16 +237,6 @@ static void destroy_window( struct window *win )
|
||||||
while (win->first_child) destroy_window( win->first_child );
|
while (win->first_child) destroy_window( win->first_child );
|
||||||
while (win->first_unlinked) destroy_window( win->first_unlinked );
|
while (win->first_unlinked) destroy_window( win->first_unlinked );
|
||||||
|
|
||||||
/* reset siblings owner */
|
|
||||||
if (win->parent)
|
|
||||||
{
|
|
||||||
struct window *ptr;
|
|
||||||
for (ptr = win->parent->first_child; ptr; ptr = ptr->next)
|
|
||||||
if (ptr->owner == win) ptr->owner = NULL;
|
|
||||||
for (ptr = win->parent->first_unlinked; ptr; ptr = ptr->next)
|
|
||||||
if (ptr->owner == win) ptr->owner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (win->thread->queue)
|
if (win->thread->queue)
|
||||||
{
|
{
|
||||||
if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
|
if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
|
||||||
|
@ -276,7 +262,7 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
win->parent = parent;
|
win->parent = parent;
|
||||||
win->owner = owner;
|
win->owner = owner ? owner->handle : 0;
|
||||||
win->first_child = NULL;
|
win->first_child = NULL;
|
||||||
win->last_child = NULL;
|
win->last_child = NULL;
|
||||||
win->first_unlinked = NULL;
|
win->first_unlinked = NULL;
|
||||||
|
@ -390,6 +376,7 @@ DECL_HANDLER(create_window)
|
||||||
{
|
{
|
||||||
if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
|
if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
|
||||||
top_window->thread = NULL; /* no thread owns the desktop */
|
top_window->thread = NULL; /* no thread owns the desktop */
|
||||||
|
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||||
}
|
}
|
||||||
reply->handle = top_window->handle;
|
reply->handle = top_window->handle;
|
||||||
}
|
}
|
||||||
|
@ -400,9 +387,9 @@ DECL_HANDLER(create_window)
|
||||||
if (!(parent = get_window( req->parent ))) return;
|
if (!(parent = get_window( req->parent ))) return;
|
||||||
if (req->owner && !(owner = get_window( req->owner ))) return;
|
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||||
if (owner == top_window) owner = NULL;
|
if (owner == top_window) owner = NULL;
|
||||||
else if (owner && owner->parent != parent)
|
else if (owner && parent != top_window)
|
||||||
{
|
{
|
||||||
/* owner must be a sibling of the new window */
|
/* an owned window must be created as top-level */
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -464,17 +451,17 @@ DECL_HANDLER(destroy_window)
|
||||||
DECL_HANDLER(set_window_owner)
|
DECL_HANDLER(set_window_owner)
|
||||||
{
|
{
|
||||||
struct window *win = get_window( req->handle );
|
struct window *win = get_window( req->handle );
|
||||||
struct window *owner = get_window( req->owner );
|
struct window *owner = NULL;
|
||||||
|
|
||||||
if (!win || !owner) return;
|
if (!win) return;
|
||||||
if (owner->parent != win->parent)
|
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||||
|
if (win == top_window)
|
||||||
{
|
{
|
||||||
/* owner has to be a sibling of window */
|
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
win->owner = owner;
|
reply->prev_owner = win->owner;
|
||||||
reply->full_owner = owner->handle;
|
reply->full_owner = win->owner = owner ? owner->handle : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -502,7 +489,13 @@ DECL_HANDLER(get_window_info)
|
||||||
DECL_HANDLER(set_window_info)
|
DECL_HANDLER(set_window_info)
|
||||||
{
|
{
|
||||||
struct window *win = get_window( req->handle );
|
struct window *win = get_window( req->handle );
|
||||||
|
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
|
if (req->flags && win == top_window)
|
||||||
|
{
|
||||||
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
return;
|
||||||
|
}
|
||||||
reply->old_style = win->style;
|
reply->old_style = win->style;
|
||||||
reply->old_ex_style = win->ex_style;
|
reply->old_ex_style = win->ex_style;
|
||||||
reply->old_id = win->id;
|
reply->old_id = win->id;
|
||||||
|
@ -578,7 +571,7 @@ DECL_HANDLER(get_window_tree)
|
||||||
{
|
{
|
||||||
struct window *parent = win->parent;
|
struct window *parent = win->parent;
|
||||||
reply->parent = parent->handle;
|
reply->parent = parent->handle;
|
||||||
reply->owner = win->owner ? win->owner->handle : 0;
|
reply->owner = win->owner;
|
||||||
reply->next_sibling = win->next ? win->next->handle : 0;
|
reply->next_sibling = win->next ? win->next->handle : 0;
|
||||||
reply->prev_sibling = win->prev ? win->prev->handle : 0;
|
reply->prev_sibling = win->prev ? win->prev->handle : 0;
|
||||||
reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;
|
reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;
|
||||||
|
|
117
windows/win.c
117
windows/win.c
|
@ -422,11 +422,7 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||||
req->previous = hwndInsertAfter;
|
req->previous = hwndInsertAfter;
|
||||||
if (!wine_server_call( req ))
|
if (!wine_server_call( req ))
|
||||||
{
|
{
|
||||||
if (reply->full_parent && reply->full_parent != wndPtr->parent)
|
if (reply->full_parent) wndPtr->parent = reply->full_parent;
|
||||||
{
|
|
||||||
wndPtr->owner = 0; /* reset owner when changing parent */
|
|
||||||
wndPtr->parent = reply->full_parent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -440,24 +436,30 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||||
*
|
*
|
||||||
* Change the owner of a window.
|
* Change the owner of a window.
|
||||||
*/
|
*/
|
||||||
void WIN_SetOwner( HWND hwnd, HWND owner )
|
HWND WIN_SetOwner( HWND hwnd, HWND owner )
|
||||||
{
|
{
|
||||||
WND *win = WIN_GetPtr( hwnd );
|
WND *win = WIN_GetPtr( hwnd );
|
||||||
|
HWND ret = 0;
|
||||||
|
|
||||||
if (!win) return;
|
if (!win) return 0;
|
||||||
if (win == WND_OTHER_PROCESS)
|
if (win == WND_OTHER_PROCESS)
|
||||||
{
|
{
|
||||||
if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
|
if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
SERVER_START_REQ( set_window_owner )
|
SERVER_START_REQ( set_window_owner )
|
||||||
{
|
{
|
||||||
req->handle = hwnd;
|
req->handle = hwnd;
|
||||||
req->owner = owner;
|
req->owner = owner;
|
||||||
if (!wine_server_call( req )) win->owner = reply->full_owner;
|
if (!wine_server_call( req ))
|
||||||
|
{
|
||||||
|
win->owner = reply->full_owner;
|
||||||
|
ret = reply->prev_owner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
WIN_ReleasePtr( win );
|
WIN_ReleasePtr( win );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -758,22 +760,17 @@ BOOL WIN_CreateDesktopWindow(void)
|
||||||
pWndDesktop->parent = 0;
|
pWndDesktop->parent = 0;
|
||||||
pWndDesktop->owner = 0;
|
pWndDesktop->owner = 0;
|
||||||
pWndDesktop->class = class;
|
pWndDesktop->class = class;
|
||||||
pWndDesktop->hInstance = 0;
|
|
||||||
pWndDesktop->text = NULL;
|
pWndDesktop->text = NULL;
|
||||||
pWndDesktop->hmemTaskQ = 0;
|
pWndDesktop->hmemTaskQ = 0;
|
||||||
pWndDesktop->hrgnUpdate = 0;
|
pWndDesktop->hrgnUpdate = 0;
|
||||||
pWndDesktop->hwndLastActive = hwndDesktop;
|
pWndDesktop->hwndLastActive = hwndDesktop;
|
||||||
pWndDesktop->dwStyle = 0;
|
|
||||||
pWndDesktop->dwExStyle = 0;
|
|
||||||
pWndDesktop->clsStyle = clsStyle;
|
pWndDesktop->clsStyle = clsStyle;
|
||||||
pWndDesktop->dce = NULL;
|
pWndDesktop->dce = NULL;
|
||||||
pWndDesktop->pVScroll = NULL;
|
pWndDesktop->pVScroll = NULL;
|
||||||
pWndDesktop->pHScroll = NULL;
|
pWndDesktop->pHScroll = NULL;
|
||||||
pWndDesktop->wIDmenu = 0;
|
|
||||||
pWndDesktop->helpContext = 0;
|
pWndDesktop->helpContext = 0;
|
||||||
pWndDesktop->flags = 0;
|
pWndDesktop->flags = 0;
|
||||||
pWndDesktop->hSysMenu = 0;
|
pWndDesktop->hSysMenu = 0;
|
||||||
pWndDesktop->userdata = 0;
|
|
||||||
pWndDesktop->winproc = winproc;
|
pWndDesktop->winproc = winproc;
|
||||||
pWndDesktop->cbWndExtra = wndExtra;
|
pWndDesktop->cbWndExtra = wndExtra;
|
||||||
|
|
||||||
|
@ -792,7 +789,19 @@ BOOL WIN_CreateDesktopWindow(void)
|
||||||
|
|
||||||
SetRect( &rect, 0, 0, cs.cx, cs.cy );
|
SetRect( &rect, 0, 0, cs.cx, cs.cy );
|
||||||
WIN_SetRectangles( hwndDesktop, &rect, &rect );
|
WIN_SetRectangles( hwndDesktop, &rect, &rect );
|
||||||
WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
|
|
||||||
|
SERVER_START_REQ( set_window_info )
|
||||||
|
{
|
||||||
|
req->handle = hwndDesktop;
|
||||||
|
req->flags = 0; /* don't set anything, just retrieve */
|
||||||
|
wine_server_call( req );
|
||||||
|
pWndDesktop->dwStyle = reply->old_style;
|
||||||
|
pWndDesktop->dwExStyle = reply->old_ex_style;
|
||||||
|
pWndDesktop->hInstance = (ULONG_PTR)reply->old_instance;
|
||||||
|
pWndDesktop->userdata = (ULONG_PTR)reply->old_user_data;
|
||||||
|
pWndDesktop->wIDmenu = reply->old_id;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
|
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE ))
|
||||||
{
|
{
|
||||||
|
@ -1033,10 +1042,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
||||||
WARN("Bad parent %04x\n", cs->hwndParent );
|
WARN("Bad parent %04x\n", cs->hwndParent );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
|
if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
|
||||||
else owner = GetAncestor( cs->hwndParent, GA_ROOT );
|
parent = WIN_GetFullHandle(cs->hwndParent);
|
||||||
|
else
|
||||||
|
owner = GetAncestor( cs->hwndParent, GA_ROOT );
|
||||||
}
|
}
|
||||||
else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
|
else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
|
||||||
{
|
{
|
||||||
WARN("No parent for child window\n" );
|
WARN("No parent for child window\n" );
|
||||||
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
|
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
|
||||||
|
@ -1864,7 +1875,12 @@ static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
|
||||||
LONG retvalue = 0;
|
LONG retvalue = 0;
|
||||||
WND *wndPtr;
|
WND *wndPtr;
|
||||||
|
|
||||||
if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
|
if (offset == GWL_HWNDPARENT)
|
||||||
|
{
|
||||||
|
HWND parent = GetAncestor( hwnd, GA_PARENT );
|
||||||
|
if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
|
||||||
|
return (LONG)parent;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(wndPtr = WIN_GetPtr( hwnd )))
|
if (!(wndPtr = WIN_GetPtr( hwnd )))
|
||||||
{
|
{
|
||||||
|
@ -1991,6 +2007,12 @@ static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
|
||||||
}
|
}
|
||||||
|
|
||||||
wndPtr = WIN_GetPtr( hwnd );
|
wndPtr = WIN_GetPtr( hwnd );
|
||||||
|
if (wndPtr->hwndSelf == GetDesktopWindow())
|
||||||
|
{
|
||||||
|
/* can't change anything on the desktop window */
|
||||||
|
SetLastError( ERROR_ACCESS_DENIED );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
{
|
{
|
||||||
|
@ -2033,8 +2055,16 @@ static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
|
||||||
newval = style.styleNew;
|
newval = style.styleNew;
|
||||||
break;
|
break;
|
||||||
case GWL_HWNDPARENT:
|
case GWL_HWNDPARENT:
|
||||||
WIN_ReleasePtr( wndPtr );
|
if (wndPtr->parent == GetDesktopWindow())
|
||||||
return (LONG)SetParent( hwnd, (HWND)newval );
|
{
|
||||||
|
WIN_ReleasePtr( wndPtr );
|
||||||
|
return (LONG)WIN_SetOwner( hwnd, (HWND)newval );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WIN_ReleasePtr( wndPtr );
|
||||||
|
return (LONG)SetParent( hwnd, (HWND)newval );
|
||||||
|
}
|
||||||
case GWL_WNDPROC:
|
case GWL_WNDPROC:
|
||||||
retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
|
retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
|
||||||
WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
|
WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
|
||||||
|
@ -2436,8 +2466,8 @@ HWND WINAPI GetParent( HWND hwnd )
|
||||||
req->handle = hwnd;
|
req->handle = hwnd;
|
||||||
if (!wine_server_call_err( req ))
|
if (!wine_server_call_err( req ))
|
||||||
{
|
{
|
||||||
if (style & WS_CHILD) retvalue = reply->parent;
|
if (style & WS_POPUP) retvalue = reply->owner;
|
||||||
else retvalue = reply->owner;
|
else if (style & WS_CHILD) retvalue = reply->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -2445,8 +2475,8 @@ HWND WINAPI GetParent( HWND hwnd )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
|
if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
|
||||||
else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
|
else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
|
||||||
WIN_ReleasePtr( wndPtr );
|
WIN_ReleasePtr( wndPtr );
|
||||||
}
|
}
|
||||||
return retvalue;
|
return retvalue;
|
||||||
|
@ -2461,8 +2491,9 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type )
|
||||||
WND *win;
|
WND *win;
|
||||||
HWND *list, ret = 0;
|
HWND *list, ret = 0;
|
||||||
|
|
||||||
if (type == GA_PARENT)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
case GA_PARENT:
|
||||||
if (!(win = WIN_GetPtr( hwnd )))
|
if (!(win = WIN_GetPtr( hwnd )))
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||||
|
@ -2482,28 +2513,30 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type )
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
}
|
}
|
||||||
return ret;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(list = WIN_ListParents( hwnd ))) return 0;
|
case GA_ROOT:
|
||||||
|
if (!(list = WIN_ListParents( hwnd ))) return 0;
|
||||||
|
|
||||||
if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
|
if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int count = 2;
|
int count = 2;
|
||||||
while (list[count]) count++;
|
while (list[count]) count++;
|
||||||
ret = list[count - 2]; /* get the one before the desktop */
|
ret = list[count - 2]; /* get the one before the desktop */
|
||||||
}
|
}
|
||||||
HeapFree( GetProcessHeap(), 0, list );
|
HeapFree( GetProcessHeap(), 0, list );
|
||||||
|
break;
|
||||||
|
|
||||||
if (ret && type == GA_ROOTOWNER)
|
case GA_ROOTOWNER:
|
||||||
{
|
if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
HWND owner = GetWindow( ret, GW_OWNER );
|
HWND parent = GetParent( ret );
|
||||||
if (!owner) break;
|
if (!parent) break;
|
||||||
ret = owner;
|
ret = parent;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue