This patch from Codeweavers attempts to implement the function X11DRV_ListChildren, but the server calls appear to have changed a bit since the time it was created. They are used in the function X11DRV_list_window_children. For one thing, SERVER_START_VAR_REQ no longer exists, and was replaced by SERVER_START_REQ, but there is more to it then that. Here it is anyway, in case someone wants to try to fix it. Modified files: dlls/user : user_main.c dlls/x11drv : winpos.c include : user.h windows : win.c Log message: Codeweavers Implementation of X11DRV_ListChildren.
Index: dlls/user/user_main.c =================================================================== RCS file: /home/wine/wine/dlls/user/user_main.c,v retrieving revision 1.39 diff -u -r1.39 user_main.c --- dlls/user/user_main.c 2002/01/04 18:27:43 1.39 +++ dlls/user/user_main.c 2002/01/27 23:52:29 @@ -97,6 +97,7 @@ GET_USER_FUNC(SetWindowText); GET_USER_FUNC(ShowWindow); GET_USER_FUNC(SysCommandSizeMove); + GET_USER_FUNC(ListChildren); return TRUE; } Index: dlls/x11drv/winpos.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/winpos.c,v retrieving revision 1.35 diff -u -r1.35 winpos.c --- dlls/x11drv/winpos.c 2001/12/17 22:09:18 1.35 +++ dlls/x11drv/winpos.c 2002/01/27 23:52:30 @@ -26,8 +26,12 @@ #include "nonclient.h" #include "message.h" +#include "wine/server.h" + #include "debugtools.h" +#include <stdlib.h> + DEFAULT_DEBUG_CHANNEL(x11drv); #define SWP_AGG_NOGEOMETRYCHANGE \ @@ -54,6 +58,7 @@ #define ON_BOTTOM_BORDER(hit) \ (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT)) +extern XContext winContext; /*********************************************************************** * clip_children @@ -1453,6 +1458,167 @@ done: HeapFree( GetProcessHeap(), 0, list ); return hwndInsertAfter; +} + +struct childlist +{ + HWND hWnd; + int pos; + int index; +}; + +static int childlist_compare(const void *ap, const void *bp) +{ + const struct childlist *a = ap, *b = bp; + + if(!a->hWnd) + return -1; + if(!b->hWnd) + return 1; + if(a->pos < b->pos ) + return 1; + if(a->pos == b->pos ) + return 0; + return -1; +} + + +/******************************************************************* + * X11DRV_list_window_children + * + * Build an array of the children of a given window. The array must be + * freed with HeapFree. Returns NULL when no windows are found. + */ +static HWND *X11DRV_list_window_children( HWND hwnd, ATOM atom, DWORD tid, int *pcount ) +{ + HWND *list = NULL; + + SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE ) + { + req->parent = hwnd; + req->atom = atom; + req->tid = (void *)tid; + if (!SERVER_CALL()) + { + user_handle_t *data = server_data_ptr(req); + int i, count = server_data_size(req) / sizeof(*data); + if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) )))) + { + for (i = 0; i < count; i++) list[i] = data[i]; + list[i] = 0; + } + *pcount = count; + } + } + SERVER_END_VAR_REQ; + return list; +} + + +HWND *X11DRV_ListChildren(HWND hWndParent, ATOM atom, DWORD tid) +{ + Window parent, *children = NULL; + HWND *list; + int i,j,n,count,total; + struct childlist *managed; + Display *display = thread_display(); + + /* find at least two managed windows */ + list = X11DRV_list_window_children( hWndParent, atom, tid, &count); + if (!list || (count<2) ) + return list; + + managed= HeapAlloc(GetProcessHeap(),0,count*sizeof(struct childlist)); + + /* find all the managed windows in the list */ + for (n=0, i=0; i<count; i++) + { + if ( (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_MANAGED) && + (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE) ) + { + managed[n].index = i; + managed[n++].hWnd = list[i]; + } + } + + /* if there's less than two managed windows, don't worry about the X Z-order */ + if (n<2) + { + HeapFree( GetProcessHeap(), 0, managed); + return list; + } + + TRACE("Checking %d managed windows\n",n); + + parent = __get_common_ancestor( display, X11DRV_get_whole_window(managed[0].hWnd), + X11DRV_get_whole_window(managed[1].hWnd), &children, &total ); + if( (parent==0) || (children==NULL) ) + { + ERR("Couldn't find common ancestor!\n"); + HeapFree( GetProcessHeap(), 0, managed); + return list; + } + + /* go through all managed windows in Wine z-order... */ + for (i=0; i<n; i++) + { + /* X child at index 0 is at the bottom, at index total-1 is at the top */ + Window w = __get_top_decoration( display, X11DRV_get_whole_window(managed[i].hWnd), parent ); + if (w) + managed[i].pos = __td_lookup( w, children, total ); + else + { + ERR("managed window with no top dressing %04x\n",managed[i].hWnd); + managed[i].pos = 0; + } + } + TSXFree( children ); + + qsort(managed, n, sizeof (struct childlist), childlist_compare); + +#if 0 + DPRINTF("X11 Z-Order:\n"); + for(i=0; i<n; i++) + { + RECT rect={0,0,0,0}; + CHAR name[80]; + DWORD style = GetWindowLongW(managed[i].hWnd,GWL_STYLE); + WIN_GetRectangles(managed[i].hWnd,&rect,NULL); + GetWindowTextA(managed[i].hWnd,name,sizeof name); + DPRINTF("%d %c %04x (%d,%d-%d,%d) %s\n", managed[i].pos, (style&WS_VISIBLE)?'X':' ', + managed[i].hWnd,rect.left,rect.top,rect.right,rect.bottom,name); + } +#endif + + /* Now insert the managed windows back into the list according to the X Z-order */ + for(i=0; i<n; i++) + list[managed[i].index]=0; + j=0; + for(i=0; i<count; i++) + { + if(list[i]==0) + list[i]=managed[j++].hWnd; + } + if(j!=n) + FIXME("Aiee: problem!\n"); + + HeapFree( GetProcessHeap(), 0, managed); + +#if 0 + for(i=0; list && list[i]; i++) + { + RECT rect={0,0,0,0}; + CHAR name[80]; + DWORD style = GetWindowLongW(list[i],GWL_STYLE); + WIN_GetRectangles(list[i],&rect,NULL); + GetWindowTextA(list[i],name,sizeof name); + DPRINTF("%c %04x (%d,%d-%d,%d) %s\n", + (style&WS_VISIBLE)?'X':' ', + list[i],rect.left,rect.top,rect.right,rect.bottom,name); + } +#endif + + return list; } Index: include/user.h =================================================================== RCS file: /home/wine/wine/include/user.h,v retrieving revision 1.36 diff -u -r1.36 user.h --- include/user.h 2002/01/04 18:27:45 1.36 +++ include/user.h 2002/01/27 23:52:31 @@ -90,6 +90,7 @@ BOOL (*pSetWindowText)(HWND,LPCWSTR); BOOL (*pShowWindow)(HWND,INT); void (*pSysCommandSizeMove)(HWND,WPARAM); + HWND *(*pListChildren)(HWND, ATOM, DWORD); } USER_DRIVER; extern USER_DRIVER USER_Driver; Index: windows/win.c =================================================================== RCS file: /home/wine/wine/windows/win.c,v retrieving revision 1.176 diff -u -r1.176 win.c --- windows/win.c 2002/01/22 00:50:07 1.176 +++ windows/win.c 2002/01/27 23:52:33 @@ -848,6 +848,19 @@ } } } + else + { + /* neither x nor cx are default. Check the y values . + * In the trace we see Outlook using cy set to CW_USEDEFAULT + * when opening the address book. + */ + if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) { + RECT r; + FIXME("Strange use of CW_USEDEFAULT in nHeight\n"); + SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0); + cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y; + } + } } /*********************************************************************** @@ -985,6 +998,8 @@ owner = 0; if (cs->hwndParent) { + if (cs->hwndParent == HWND_MESSAGE) + cs->hwndParent = GetDesktopWindow(); /* Make sure parent is valid */ if (!IsWindow( cs->hwndParent )) { @@ -1667,6 +1682,11 @@ { WIN_SetStyle( hwnd, style & ~WS_DISABLED ); SendMessageA( hwnd, WM_ENABLE, TRUE, 0 ); + /* GLA */ + if ((style & WS_VISIBLE) && !(style & WS_CHILD) && + (GetFocus() == 0)) { + SetFocus( hwnd ); + } } else if (!enable && !retvalue) {