(same as previous, but with the patch attached!) Hello world! Here's a implementation for Set/GetWindowRgn. Notice that it modifies configure.in and make_X11wrappers, so a few additional steps are needed to apply the patch. Here is the procedure cd <your_wine_sandbox_here> patch -p0 < WindowRgn.diff autoconf configure.in > configure ; chmod u+x configure cd include autoheader ../configure.in > config.h.in cd .. ./configure ./tools/make_X11wrappers make depend ; make --- Adds non-rectangular windows support to WINE. Functionality permits support for skin-enabled applications such as WinAMP, RealJukebox and any type of non-rectangular window you can think of. Changelog : - implementations of SetWindowsRgn and GetWindowRgn - GetDCEx updated with a fixme that shows up when applying a window region to a non-native window - X11DRV and TTYDRV updated with new API SetWindowRgn Modified file(s): - configure.in - tools/make_X11wrappers - tsx11/Makefile.in - tsx11/X11_calls - dlls/x11drv/x11drv_main.c - include/acconfig.h - include/ttydrv.h - include/x11drv.h - include/win.h - windows/winpos.c - windows/dce.c - windows/x11drv/init.c - windows/x11drv/wnd.c - windows/ttydrv/init.c - windows/ttydrv/wnd.c François Jacques Macadamian Technologies Inc.
Index: configure.in =================================================================== RCS file: /home/wine/wine/configure.in,v retrieving revision 1.130 diff -u -u -r1.130 configure.in --- configure.in 2000/06/23 20:15:35 1.130 +++ configure.in 2000/06/27 06:23:20 @@ -1,4 +1,4 @@ -dnl Process this file with autoconf to produce a configure script. +\dnl Process this file with autoconf to produce a configure script. dnl Author: Michael Patra <[EMAIL PROTECTED]> dnl <[EMAIL PROTECTED]> AC_REVISION([configure.in 1.00]) @@ -169,7 +169,17 @@ AC_MSG_WARN([Xshm extension not found!!]) ) - dnl *** Check for XFree86 DGA / DGA 2.0 extension + dnl *** Check for X shape extension + AC_CHECK_HEADERS(X11/Xlib.h X11/extensions/shape.h, + [ dnl *** If X11/extensions/shape.h exists... + AC_CHECK_LIB(Xext,XShapeQueryExtension, + AC_DEFINE(HAVE_LIBXSHAPE),, + $X_LIBS -lXext -lX11 $X_EXTRA_LIBS) + ], + AC_MSG_WARN([XShape extension found!!]) + ) + + dnl *** Check for XFree86 DGA / DGA 2.0 extension AC_CHECK_HEADERS(X11/extensions/xf86dga.h, [ dnl *** If X11/extensions/xf86dga.h exists, check dnl *** for XDGAQueryExtension()... Index: dlls/x11drv/x11drv_main.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/x11drv_main.c,v retrieving revision 1.16 diff -u -u -r1.16 x11drv_main.c --- dlls/x11drv/x11drv_main.c 2000/06/23 16:49:46 1.16 +++ dlls/x11drv/x11drv_main.c 2000/06/27 06:23:20 @@ -13,6 +13,7 @@ #include <X11/cursorfont.h> #include "ts_xlib.h" #include "ts_xutil.h" +#include "ts_shape.h" #include "winbase.h" #include "wine/winbase16.h" Index: include/acconfig.h =================================================================== RCS file: /home/wine/wine/include/acconfig.h,v retrieving revision 1.22 diff -u -u -r1.22 acconfig.h --- include/acconfig.h 2000/05/12 20:18:16 1.22 +++ include/acconfig.h 2000/06/27 06:23:20 @@ -24,6 +24,9 @@ /* Define if you have the X Shm extension */ #undef HAVE_LIBXXSHM +/* Define if you have the X Shape extension */ +#undef HAVE_LIBXSHAPE + /* Define if you have the Xxf86vm library */ #undef HAVE_LIBXXF86VM Index: include/ttydrv.h =================================================================== RCS file: /home/wine/wine/include/ttydrv.h,v retrieving revision 1.30 diff -u -u -r1.30 ttydrv.h --- include/ttydrv.h 2000/06/08 04:57:23 1.30 +++ include/ttydrv.h 2000/06/27 06:23:20 @@ -201,5 +201,6 @@ extern void TTYDRV_WND_SetDrawable(struct tagWND *wndPtr, struct tagDC *dc, WORD flags, BOOL bSetClipOrigin); extern BOOL TTYDRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value); extern BOOL TTYDRV_WND_IsSelfClipping(struct tagWND *wndPtr); +extern void TTYDRV_WND_SetWindowRgn(struct tagWND *wndPtr, HRGN hrgnWnd); #endif /* !defined(__WINE_TTYDRV_H) */ Index: include/win.h =================================================================== RCS file: /home/wine/wine/include/win.h,v retrieving revision 1.27 diff -u -u -r1.27 win.h --- include/win.h 2000/05/23 04:12:23 1.27 +++ include/win.h 2000/06/27 06:23:20 @@ -78,6 +78,7 @@ struct tagDCE *dce; /* Window DCE (if CS_OWNDC or CS_CLASSDC) */ HGLOBAL16 hmemTaskQ; /* Task queue global memory handle */ HRGN16 hrgnUpdate; /* Update region */ + HRGN hrgnWnd; /* window's region */ HWND hwndLastActive;/* Last active popup hwnd */ DWORD dwStyle; /* Window style (from CreateWindow) */ DWORD dwExStyle; /* Extended style (from CreateWindowEx) */ @@ -131,6 +132,7 @@ void (*pSetDrawable)(WND *, struct tagDC *, WORD, BOOL); BOOL (*pSetHostAttr)(WND *, INT haKey, INT value); BOOL (*pIsSelfClipping)(WND *); + void (*pSetWindowRgn)(WND *, const HRGN); } WND_DRIVER; extern WND_DRIVER *WND_Driver; Index: include/x11drv.h =================================================================== RCS file: /home/wine/wine/include/x11drv.h,v retrieving revision 1.52 diff -u -u -r1.52 x11drv.h --- include/x11drv.h 2000/06/08 04:57:23 1.52 +++ include/x11drv.h 2000/06/27 06:23:20 @@ -431,6 +431,7 @@ extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value); extern BOOL X11DRV_WND_IsSelfClipping(struct tagWND *wndPtr); extern void X11DRV_WND_DockWindow(struct tagWND *wndPtr); +extern void X11DRV_WND_SetWindowRgn(struct tagWND *wndPtr, HRGN hrgnWnd); extern int X11DRV_EVENT_PrepareShmCompletion( Drawable dw ); extern void X11DRV_EVENT_WaitShmCompletion( int compl ); Index: tools/make_X11wrappers =================================================================== RCS file: /home/wine/wine/tools/make_X11wrappers,v retrieving revision 1.14 diff -u -u -r1.14 make_X11wrappers --- tools/make_X11wrappers 2000/04/25 19:55:35 1.14 +++ tools/make_X11wrappers 2000/06/27 06:23:21 @@ -17,7 +17,7 @@ $X11_include_dir = "/usr/X11/include"; $outdir = "tsx11"; $wantfile = "$outdir/X11_calls"; -@dolist = ("Xlib", "Xresource", "Xutil", "xpm", "XShm", "xf86dga", "xf86dga2", "xf86vmode"); +@dolist = ("Xlib", "Xresource", "Xutil", "xpm", "XShm", "xf86dga", "xf86dga2", +"xf86vmode", "shape"); # First read list of wanted function names. @@ -80,6 +80,14 @@ $pre_file = "#include \"windef.h\"\n#ifdef HAVE_LIBXXF86VM\n#define XMD_H\n#include \"basetsd.h\"\n"; $post_file = "#endif /* defined(HAVE_LIBXXF86VM) */\n"; } + if($name eq "shape") { + $extensions_dir = "extensions/"; + $pre_file = "#ifdef HAVE_LIBXSHAPE\n#include <X11/IntrinsicP.h>\n"; + $post_file = "#endif /* defined(HAVE_LIBXSHAPE) */\n"; + $inc_name = "shape"; + } + + print OUTH <<END; /* @@ -154,6 +162,11 @@ "Display *, Drawable, char *, XShmSegmentInfo *, unsigned int, unsigned int, unsigned int", "Display *a0, Drawable a1, char *a2, XShmSegmentInfo *a3, unsigned int a4, unsigned int a5, unsigned int a6", "a0, a1, a2, a3, a4, a5, a6"); + } elsif($name eq "shape") { + output_fn("XShapeCombineRectangles", "void", + "Display *, Window, int, int, int, XRectangle*, int, int, int", + "Display *a0, Window a1, int a2, int a3, int a4, XRectangle* a5, +int a6, int a7, int a8", + "a0, a1, a2, a3, a4, a5, a6, a7, a8"); } elsif($name eq "xf86dga") { output_fn("XF86DGAQueryVersion",Bool, "Display*,int*,int*", Index: tsx11/Makefile.in =================================================================== RCS file: /home/wine/wine/tsx11/Makefile.in,v retrieving revision 1.3 diff -u -u -r1.3 Makefile.in --- tsx11/Makefile.in 1999/09/20 18:42:46 1.3 +++ tsx11/Makefile.in 2000/06/27 06:23:21 @@ -13,6 +13,7 @@ ts_xlib.c \ ts_xresource.c \ ts_xutil.c \ + ts_shape.c \ ts_xpm.c all: $(MODULE).o Index: tsx11/X11_calls =================================================================== RCS file: /home/wine/wine/tsx11/X11_calls,v retrieving revision 1.15 diff -u -u -r1.15 X11_calls --- tsx11/X11_calls 2000/06/02 20:36:29 1.15 +++ tsx11/X11_calls 2000/06/27 06:23:21 @@ -143,6 +143,7 @@ XSetWMProperties XSetWMProtocols XSetWMSizeHints +XShapeCombineRectangles XShmAttach XShmCreateImage XShmCreatePixmap Index: windows/dce.c =================================================================== RCS file: /home/wine/wine/windows/dce.c,v retrieving revision 1.36 diff -u -u -r1.36 dce.c --- windows/dce.c 2000/06/15 00:12:12 1.36 +++ windows/dce.c 2000/06/27 06:23:21 @@ -854,6 +854,10 @@ TRACE("no visrgn update %08x dce, hwnd [%04x]\n", (unsigned)dce, hwnd); /* apply additional region operation (if any) */ + if (wndPtr->hrgnWnd != 0 && !(wndPtr->flags & WIN_NATIVE)) + { + FIXME("Clipping of window region on non-native windows not implemented!"); + } if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) ) { Index: windows/winpos.c =================================================================== RCS file: /home/wine/wine/windows/winpos.c,v retrieving revision 1.62 diff -u -u -r1.62 winpos.c --- windows/winpos.c 2000/06/14 21:16:18 1.62 +++ windows/winpos.c 2000/06/27 06:23:21 @@ -6,6 +6,7 @@ */ #include <string.h> +#include "winerror.h" #include "windef.h" #include "wingdi.h" #include "wine/winuser16.h" @@ -272,35 +273,144 @@ /*********************************************************************** * GetWindowRgn */ -BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) - +int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) { - RECT rect; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return (ERROR); - - FIXME("GetWindowRgn: doesn't really do regions\n"); + int nRet = ERROR; + HRGN hCurrRgn = 0; + WND * wndPtr = WIN_FindWndPtr( hwnd ); - memset (&rect, 0, sizeof(rect)); - - GetWindowRect ( hwnd, &rect ); - - FIXME("Check whether a valid region here\n"); - - SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom ); + if (!wndPtr) return (ERROR); + hCurrRgn = wndPtr->hrgnWnd; + if (!hrgn) + { + SetLastError(ERROR_ALREADY_EXISTS); + nRet = ERROR; + } + else if (!hCurrRgn) + { + SetLastError(ERROR_INVALID_WINDOW_HANDLE); + nRet = ERROR; + } + else if (hrgn == hCurrRgn) + { + SetLastError(ERROR_INVALID_HANDLE); + nRet = ERROR; + } + else + { + int nRectCount = NULLREGION; + + nRectCount = CombineRgn(hrgn, hCurrRgn, hCurrRgn, RGN_COPY); + + switch (nRectCount) + { + case 0: + nRet = NULLREGION; + break; + + case 1: + nRet = SIMPLEREGION; + break; + + default: + nRet = COMPLEXREGION; + } + + SetLastError(ERROR_SUCCESS); + } + WIN_ReleaseWndPtr(wndPtr); - return (SIMPLEREGION); + return (nRet); } /*********************************************************************** * SetWindowRgn */ INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw) - { + HRGN tempRgn = 0; + RECT tempRect; + + WND * wndPtr = WIN_FindWndPtr(hwnd); + + if (!wndPtr) return(0); + + /* a region exists for this window */ + if (hrgn != 0 && hrgn == wndPtr->hrgnWnd) + { + /* can't replace actual region with same region + since we're now owner of that region + */ + SetLastError(ERROR_INVALID_WINDOW_HANDLE); + return(0); + } + + if (wndPtr->hrgnWnd) + { + /* delete previous region */ + DeleteObject(wndPtr->hrgnWnd); + wndPtr->hrgnWnd = 0; + } + + /* we'd like to set it back to 0 */ + if (hrgn == 0) + { + GetWindowRect(hwnd, &tempRect); + tempRgn = CreateRectRgnIndirect(&tempRect); + hrgn = tempRgn; + } + else + { + /* verify that region really exists */ + DWORD dwRet = 0; + + dwRet = GetRgnBox(hrgn, &tempRect); + if (dwRet == 0) + { + /* invalid region handle */ + SetLastError(ERROR_INVALID_WINDOW_HANDLE); + return(0); + } + + wndPtr->hrgnWnd = hrgn; + } + + /* valid region handle */ + if (FALSE == bRedraw) + { + SetWindowPos(hwnd, + NULL, + tempRect.left, + tempRect.top, + tempRect.right - tempRect.left, + tempRect.bottom - tempRect.top, + SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOREDRAW | +SWP_NOZORDER); + } + else + { + SetWindowPos(hwnd, + NULL, + tempRect.left, + tempRect.top, + tempRect.right - tempRect.left, + tempRect.bottom - tempRect.top, + SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER); + } + if ( wndPtr->flags & WIN_NATIVE ) + { + wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn); + } + if (tempRgn) + { + DeleteObject(tempRgn); + tempRgn = 0; + } + + SetLastError(ERROR_SUCCESS); + + WIN_ReleaseWndPtr(wndPtr); - FIXME("SetWindowRgn: stub\n"); return TRUE; } Index: windows/ttydrv/init.c =================================================================== RCS file: /home/wine/wine/windows/ttydrv/init.c,v retrieving revision 1.16 diff -u -u -r1.16 init.c --- windows/ttydrv/init.c 2000/03/25 17:30:14 1.16 +++ windows/ttydrv/init.c 2000/06/27 06:23:21 @@ -39,7 +39,8 @@ TTYDRV_WND_ScrollWindow, TTYDRV_WND_SetDrawable, TTYDRV_WND_SetHostAttr, - TTYDRV_WND_IsSelfClipping + TTYDRV_WND_IsSelfClipping, + TTYDRV_WND_SetWindowRgn }; Index: windows/x11drv/init.c =================================================================== RCS file: /home/wine/wine/windows/x11drv/init.c,v retrieving revision 1.19 diff -u -u -r1.19 init.c --- windows/x11drv/init.c 2000/04/25 19:55:36 1.19 +++ windows/x11drv/init.c 2000/06/27 06:23:21 @@ -39,7 +39,8 @@ X11DRV_WND_SurfaceCopy, X11DRV_WND_SetDrawable, X11DRV_WND_SetHostAttr, - X11DRV_WND_IsSelfClipping + X11DRV_WND_IsSelfClipping, + X11DRV_WND_SetWindowRgn }; Index: windows/x11drv/wnd.c =================================================================== RCS file: /home/wine/wine/windows/x11drv/wnd.c,v retrieving revision 1.49 diff -u -u -r1.49 wnd.c --- windows/x11drv/wnd.c 2000/06/25 12:53:28 1.49 +++ windows/x11drv/wnd.c 2000/06/27 06:23:21 @@ -12,6 +12,7 @@ #include "ts_xlib.h" #include "ts_xutil.h" +#include "ts_shape.h" #include <stdlib.h> #include <string.h> @@ -989,3 +990,74 @@ ); } + +/*********************************************************************** + * X11DRV_WND_SetWindowRgn + * + * Assign specified region to window (for non-rectangular windows) + */ +void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd) +{ + Window win = X11DRV_WND_GetXWindow(wndPtr); + + if (0 != win) + { + DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL); + PRGNDATA pRegionData = (PRGNDATA) HeapAlloc(SystemHeap, 0, dwBufferSize); + DWORD dwRegionSize = 0; + + int op = ShapeSet; + int dest_kind = ShapeBounding; + + /* no x or y offset */ + int x_off = 0; + int y_off = 0; + + /* 0 = unsorted */ + int ordering = 0; + + GetRegionData(hrgnWnd, dwBufferSize, pRegionData); + dwRegionSize = pRegionData->rdh.nCount; + + { + /* convert region's "Windows rectangles" to XRectangles */ + XRectangle aXRect[dwRegionSize]; + XRectangle* pCurrRect = aXRect; + RECT* pRect = (RECT*) pRegionData->Buffer; + + for (; pRect < ((RECT*) pRegionData->Buffer) + dwRegionSize ; ++pRect, +++pCurrRect) + { + pCurrRect->x = pRect->left; + pCurrRect->y = pRect->top; + pCurrRect->height = pRect->bottom - pRect->top; + pCurrRect->width = pRect->right - pRect->left; + + TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, +Width=%04d.\n", + pRect - (RECT*) pRegionData->Buffer, + dwRegionSize, + pCurrRect->x, + pCurrRect->y, + pCurrRect->height, + pCurrRect->width); + } + + /* shape = non-rectangular windows (X11/extensions) */ + TSXShapeCombineRectangles( display, + win, + dest_kind, + x_off, + y_off, + aXRect , + pCurrRect - aXRect, + op, + ordering); + TSXFlush(display); + } + HeapFree(SystemHeap, 0, pRegionData); + } + else + { + WARN("wndPtr hasn't any associated X window!\n"); + } + return; +}