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