ListChildren from CW

Duane Clark dclark at akamail.com
Sun Jan 27 19:57:09 CST 2002


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.

-------------- next part --------------
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)
     {


More information about the wine-patches mailing list