summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2014-08-16 12:36:51 +0100
committerJon TURNEY <jon.turney@dronecode.org.uk>2014-08-16 12:36:51 +0100
commit8a90494207db7e0c9b16fc614699892e2fad8d44 (patch)
treef9fbbb08393ee289ad68f087172d4a7a29ffd371
parent8b36e1ec8dd9f53e9f4e10422c2100844e9e549c (diff)
parentc0956ea714279c2bd487a8b6c011e52005b9c606 (diff)
Merge branch 'cygwin-patches-for-1.16' into HEADxserver-cygwin-1.16.0-1
-rw-r--r--.gitignore1
-rw-r--r--composite/compwindow.c2
-rw-r--r--configure.ac21
-rw-r--r--dix/dispatch.c2
-rw-r--r--dix/main.c5
-rw-r--r--dix/stubmain.c2
-rw-r--r--dix/window.c3
-rw-r--r--glx/glxcmds.c11
-rw-r--r--glx/glxcontext.h2
-rw-r--r--glx/glxdriswrast.c34
-rw-r--r--glx/glxext.c6
-rw-r--r--glx/glxext.h1
-rw-r--r--glx/glxscreens.c16
-rw-r--r--glx/indirect_dispatch.c109
-rw-r--r--glx/indirect_dispatch.h24
-rw-r--r--glx/indirect_dispatch_swap.c149
-rw-r--r--glx/indirect_size_get.c28
-rw-r--r--glx/indirect_size_get.h3
-rw-r--r--glx/indirect_table.c27
-rw-r--r--glx/rensize.c2
-rw-r--r--hw/dmx/doc/dmx.xml2
-rwxr-xr-xhw/xfree86/sdksyms.sh4
-rw-r--r--hw/xquartz/quartz.c2
-rw-r--r--hw/xwin/InitInput.c1
-rw-r--r--hw/xwin/InitOutput.c223
-rw-r--r--hw/xwin/Makefile.am54
-rwxr-xr-xhw/xwin/XWin.exe.manifest14
-rw-r--r--hw/xwin/XWin.rc3
-rw-r--r--hw/xwin/glx/.gitignore5
-rwxr-xr-xhw/xwin/glx/gen_gl_wrappers.py13
-rw-r--r--hw/xwin/glx/glwindows.h5
-rw-r--r--hw/xwin/glx/indirect.c70
-rw-r--r--hw/xwin/glx/winpriv.c39
-rw-r--r--hw/xwin/man/XWin.man22
-rw-r--r--hw/xwin/man/XWinrc.man29
-rw-r--r--hw/xwin/system.XWinrc10
-rw-r--r--hw/xwin/win.h30
-rw-r--r--hw/xwin/winauth.c9
-rw-r--r--hw/xwin/winclipboard/Makefile.am25
-rw-r--r--hw/xwin/winclipboard/debug.c52
-rw-r--r--hw/xwin/winclipboard/internal.h (renamed from hw/xwin/winclipboard.h)91
-rw-r--r--hw/xwin/winclipboard/textconv.c (renamed from hw/xwin/winclipboardtextconv.c)29
-rw-r--r--hw/xwin/winclipboard/thread.c (renamed from hw/xwin/winclipboardthread.c)374
-rw-r--r--hw/xwin/winclipboard/winclipboard.h38
-rw-r--r--hw/xwin/winclipboard/wndproc.c (renamed from hw/xwin/winclipboardwndproc.c)351
-rw-r--r--hw/xwin/winclipboard/xevents.c (renamed from hw/xwin/winclipboardxevents.c)367
-rw-r--r--hw/xwin/winclipboard/xwinclip.c134
-rw-r--r--hw/xwin/winclipboard/xwinclip.man64
-rw-r--r--hw/xwin/winclipboardinit.c150
-rw-r--r--hw/xwin/winclipboardwrappers.c226
-rw-r--r--hw/xwin/winconfig.c5
-rw-r--r--hw/xwin/winconfig.h3
-rw-r--r--hw/xwin/wincursor.c306
-rw-r--r--hw/xwin/windialogs.c7
-rw-r--r--hw/xwin/windisplay.c64
-rw-r--r--hw/xwin/windisplay.h34
-rw-r--r--hw/xwin/winengine.c15
-rw-r--r--hw/xwin/winerror.c10
-rw-r--r--hw/xwin/winglobals.c15
-rw-r--r--hw/xwin/winglobals.h4
-rw-r--r--hw/xwin/winkeybd.c290
-rw-r--r--hw/xwin/winmouse.c94
-rw-r--r--hw/xwin/winmsg.c29
-rw-r--r--hw/xwin/winmsg.h23
-rw-r--r--hw/xwin/winmultiwindowclass.h28
-rw-r--r--hw/xwin/winmultiwindowicons.c568
-rw-r--r--hw/xwin/winmultiwindowicons.h4
-rw-r--r--hw/xwin/winmultiwindowwindow.c327
-rw-r--r--hw/xwin/winmultiwindowwm.c215
-rw-r--r--hw/xwin/winmultiwindowwndproc.c95
-rw-r--r--hw/xwin/winprefs.c155
-rw-r--r--hw/xwin/winprefs.h3
-rw-r--r--hw/xwin/winprefslex.l6
-rw-r--r--hw/xwin/winprefsyacc.y91
-rw-r--r--hw/xwin/winprocarg.c159
-rw-r--r--hw/xwin/winrandr.c2
-rw-r--r--hw/xwin/winresource.h1
-rw-r--r--hw/xwin/winscrinit.c20
-rw-r--r--hw/xwin/winshadddnl.c4
-rw-r--r--hw/xwin/wintrayicon.c19
-rw-r--r--hw/xwin/winwin32rootless.c1
-rw-r--r--hw/xwin/winwin32rootlesswndproc.c1
-rw-r--r--hw/xwin/winwindow.h1
-rw-r--r--hw/xwin/winwndproc.c13
-rw-r--r--hw/xwin/wmutil/Makefile.am24
-rw-r--r--hw/xwin/wmutil/cursor_convert.c351
-rw-r--r--hw/xwin/wmutil/cursor_convert.h54
-rw-r--r--hw/xwin/wmutil/icon_convert.c567
-rw-r--r--hw/xwin/wmutil/icon_convert.h34
-rw-r--r--hw/xwin/wmutil/keyboard.c308
-rw-r--r--hw/xwin/wmutil/keyboard.h39
-rw-r--r--hw/xwin/wmutil/mouse.c111
-rw-r--r--hw/xwin/wmutil/mouse.h36
-rw-r--r--hw/xwin/wmutil/scancodes.h (renamed from hw/xwin/winkeynames.h)18
-rw-r--r--hw/xwin/wmutil/winvkmap.h (renamed from hw/xwin/winkeybd.h)19
-rw-r--r--include/dixmain.h32
-rw-r--r--include/extinit.h2
-rw-r--r--include/os.h4
-rw-r--r--include/scrnintstr.h5
-rw-r--r--man/Xserver.man3
-rw-r--r--mi/miexpose.c28
-rw-r--r--mi/mioverlay.c12
-rw-r--r--mi/miscrinit.c1
-rw-r--r--mi/miwindow.c4
-rw-r--r--miext/rootless/rootlessCommon.h1
-rw-r--r--miext/rootless/rootlessScreen.c3
-rw-r--r--miext/rootless/rootlessWindow.c35
-rw-r--r--miext/rootless/rootlessWindow.h1
-rw-r--r--os/Makefile.am2
-rw-r--r--os/backtrace.c70
-rw-r--r--os/connection.c1
-rw-r--r--os/log.c7
-rw-r--r--os/osinit.c86
-rw-r--r--os/utils.c42
-rw-r--r--pseudoramiX/pseudoramiX.h2
-rw-r--r--randr/rrxinerama.c5
-rw-r--r--xkb/ddxLoad.c15
117 files changed, 4833 insertions, 2585 deletions
diff --git a/.gitignore b/.gitignore
index dc56b4651..6303095d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,4 @@ core
doltcompile
doltlibtool
xserver.ent
+test-driver
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 9a6b2dae8..b6bf1e2b1 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -104,7 +104,7 @@ compRepaintBorder(ClientPtr pClient, void *closure)
RegionNull(&exposed);
RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
- miPaintWindow(pWindow, &exposed, PW_BORDER);
+ (*pWindow->drawable.pScreen->PaintWindow)(pWindow, &exposed, PW_BORDER);
RegionUninit(&exposed);
}
return TRUE;
diff --git a/configure.ac b/configure.ac
index 1c327fd59..64af69fed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,3 +1,4 @@
+
dnl Copyright © 2003-2007 Keith Packard, Daniel Stone
dnl
dnl Permission is hereby granted, free of charge, to any person obtaining a
@@ -83,6 +84,16 @@ AC_PROG_YACC
AC_SYS_LARGEFILE
XORG_PROG_RAWCPP
+dnl we really need yacc and lex to build tarballs made by cygport directly from a git tag not 'make dist'
+AC_PATH_PROG(YACC_INST, $YACC)
+if test -z "$YACC_INST"; then
+ AC_MSG_ERROR([yacc not found])
+fi
+AC_PATH_PROG(LEX_INST, $LEX)
+if test -z "$LEX_INST"; then
+ AC_MSG_ERROR([lex not found])
+fi
+
# Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow
# easier overrides at build time.
XSERVER_CFLAGS='$(CWARNFLAGS)'
@@ -1994,11 +2005,13 @@ if test "x$XORG" = xyes; then
gnu*)
XORG_OS_SUBDIR="hurd"
;;
+ cygwin*)
+ XORG_OS_SUBDIR="stub"
+ ;;
*)
XORG_OS_SUBDIR="stub"
AC_MSG_NOTICE([m4_text_wrap(m4_join([ ],
- [Your OS is unknown. Xorg currently only supports Linux,],
- [Free/Open/Net/DragonFlyBSD, Solaris/OpenSolaris, & GNU Hurd.],
+ [Your OS is unknown.],
[If you are interested in porting Xorg to your platform,],
[please email xorg@lists.freedesktop.org.]))])
;;
@@ -2138,7 +2151,7 @@ if test "x$XWIN" = xyes; then
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
AC_CHECK_TOOL(WINDRES, windres)
- PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau])
+ PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-image xcb-icccm])
if test "x$WINDOWSWM" = xauto; then
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
@@ -2594,6 +2607,8 @@ hw/xnest/man/Makefile
hw/xwin/Makefile
hw/xwin/glx/Makefile
hw/xwin/man/Makefile
+hw/xwin/wmutil/Makefile
+hw/xwin/winclipboard/Makefile
hw/xquartz/Makefile
hw/xquartz/GL/Makefile
hw/xquartz/bundle/Makefile
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 4f830f7f4..1bce62492 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -224,7 +224,7 @@ UpdateCurrentTimeIf(void)
#define SMART_SCHEDULE_DEFAULT_INTERVAL 5
#define SMART_SCHEDULE_MAX_SLICE 15
-#if defined(WIN32) && !defined(__CYGWIN__)
+#if defined(WIN32) || defined(__CYGWIN__)
Bool SmartScheduleDisable = TRUE;
#else
Bool SmartScheduleDisable = FALSE;
diff --git a/dix/main.c b/dix/main.c
index 7427e08ca..7644c9413 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -110,6 +110,7 @@ Equipment Corporation.
#else
#include "dixevents.h" /* InitEvents() */
#endif
+#include "dixmain.h"
#ifdef DPMSExtension
#include <X11/extensions/dpmsconst.h>
@@ -159,8 +160,6 @@ dix_main(int argc, char *argv[], char *envp[])
DPMSPowerLevel = 0;
#endif
InitBlockAndWakeupHandlers();
- /* Perform any operating system dependent initializations you'd like */
- OsInit();
if (serverGeneration == 1) {
CreateWellKnownSockets();
for (i = 1; i < MAXCLIENTS; i++)
@@ -172,6 +171,8 @@ dix_main(int argc, char *argv[], char *envp[])
}
else
ResetWellKnownSockets();
+ /* Perform any operating system dependent initializations you'd like */
+ OsInit();
clients[0] = serverClient;
currentMaxClients = 1;
diff --git a/dix/stubmain.c b/dix/stubmain.c
index 7efb4b8e7..b521677d2 100644
--- a/dix/stubmain.c
+++ b/dix/stubmain.c
@@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE.
******************************************************************/
-int dix_main(int argc, char *argv[], char *envp[]);
+#include "dixmain.h"
/*
A default implementation of main, which can be overridden by the DDX
diff --git a/dix/window.c b/dix/window.c
index f4acdc889..f2d24c484 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -122,7 +122,6 @@ Equipment Corporation.
#endif
#include "dixevents.h"
#include "globals.h"
-#include "mi.h" /* miPaintWindow */
#ifdef COMPOSITE
#include "compint.h"
#endif
@@ -1471,7 +1470,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
RegionNull(&exposed);
RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
- miPaintWindow(pWin, &exposed, PW_BORDER);
+ (*pWin->drawable.pScreen->PaintWindow)(pWin, &exposed, PW_BORDER);
RegionUninit(&exposed);
}
return error;
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 2fc3f4cc8..e390aa6a9 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -213,6 +213,13 @@ __glXdirectContextCreate(__GLXscreen * screen,
return context;
}
+void
+FlushContext(__GLXcontext * cx)
+{
+ glFlush();
+ cx->hasUnflushedCommands = GL_FALSE;
+}
+
/**
* Create a GL context with the given properties. This routine is used
* to implement \c glXCreateContext, \c glXCreateNewContext, and
@@ -413,7 +420,9 @@ __glXDisp_DestroyContext(__GLXclientState * cl, GLbyte * pc)
&glxc, &err))
return err;
- FreeResourceByType(req->context, __glXContextRes, FALSE);
+ glxc->idExists = GL_FALSE;
+ if (!glxc->currentClient)
+ FreeResourceByType(req->context, __glXContextRes, FALSE);
return Success;
}
diff --git a/glx/glxcontext.h b/glx/glxcontext.h
index 677898a67..c7cca0b56 100644
--- a/glx/glxcontext.h
+++ b/glx/glxcontext.h
@@ -138,4 +138,6 @@ extern __GLXcontext *__glXdirectContextCreate(__GLXscreen * screen,
__GLXconfig * modes,
__GLXcontext * shareContext);
+extern void FlushContext(__GLXcontext * cx);
+
#endif /* !__GLX_context_h__ */
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index c30ce9aed..8917f2e4b 100644
--- a/glx/glxdriswrast.c
+++ b/glx/glxdriswrast.c
@@ -71,6 +71,8 @@ struct __GLXDRIscreen {
const __DRIcopySubBufferExtension *copySubBuffer;
const __DRItexBufferExtension *texBuffer;
const __DRIconfig **driConfigs;
+
+ unsigned char glx_enable_bits[__GLX_EXT_BYTES];
};
struct __GLXDRIcontext {
@@ -396,16 +398,30 @@ initializeExtensions(__GLXDRIscreen * screen)
extensions = screen->core->getExtensions(screen->driScreen);
+ /* GLX_MESA_copy_sub_buffer is always enabled. */
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
+
for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_SGI_make_current_read");
+
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
+ }
+
if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
screen->copySubBuffer =
(const __DRIcopySubBufferExtension *) extensions[i];
- /* GLX_MESA_copy_sub_buffer is always enabled. */
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_MESA_copy_sub_buffer");
+
+ LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
}
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
/* GLX_EXT_texture_from_pixmap is always enabled. */
+ LogMessage(X_INFO, "AIGLX: enabled GLX_EXT_texture_from_pixmap\n");
}
/* Ignore unknown extensions */
@@ -420,6 +436,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
{
const char *driverName = "swrast";
__GLXDRIscreen *screen;
+ size_t buffer_size;
screen = calloc(1, sizeof *screen);
if (screen == NULL)
@@ -431,6 +448,8 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
screen->base.swapInterval = NULL;
screen->base.pScreen = pScreen;
+ __glXInitExtensionEnableBits(screen->glx_enable_bits);
+
screen->driver = glxProbeDriver(driverName,
(void **) &screen->core,
__DRI_CORE, 1,
@@ -459,6 +478,19 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
__glXScreenInit(&screen->base, pScreen);
+ /* The first call simply determines the length of the extension string.
+ * This allows us to allocate some memory to hold the extension string,
+ * but it requires that we call __glXGetExtensionString a second time.
+ */
+ buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
+ if (buffer_size > 0) {
+ free(screen->base.GLXextensions);
+
+ screen->base.GLXextensions = xnfalloc(buffer_size);
+ (void) __glXGetExtensionString(screen->glx_enable_bits,
+ screen->base.GLXextensions);
+ }
+
screen->base.GLXmajor = 1;
screen->base.GLXminor = 4;
diff --git a/glx/glxext.c b/glx/glxext.c
index c2de3cedd..d472b93f5 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -66,6 +66,7 @@ static DevPrivateKeyRec glxClientPrivateKeyRec;
** Forward declarations.
*/
static int __glXDispatch(ClientPtr);
+static GLboolean __glXFreeContext(__GLXcontext * cx);
/*
** Called when the extension is reset.
@@ -134,6 +135,7 @@ DrawableGone(__GLXdrawable * glxPriv, XID xid)
if (c->currentClient &&
(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
/* just force a re-bind the next time through */
+ FlushContext(c);
(*c->loseCurrent) (c);
lastGLContext = NULL;
}
@@ -186,7 +188,7 @@ __glXRemoveFromContextList(__GLXcontext * cx)
/*
** Free a context.
*/
-GLboolean
+static GLboolean
__glXFreeContext(__GLXcontext * cx)
{
if (cx->idExists || cx->currentClient)
@@ -291,7 +293,7 @@ glxClientCallback(CallbackListPtr *list, void *closure, void *data)
c->loseCurrent(c);
lastGLContext = NULL;
c->currentClient = NULL;
- __glXFreeContext(c);
+ FreeResourceByType(c, __glXContextRes, FALSE);
}
}
diff --git a/glx/glxext.h b/glx/glxext.h
index 3f2dee696..cde0e1519 100644
--- a/glx/glxext.h
+++ b/glx/glxext.h
@@ -51,7 +51,6 @@
#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1
#endif
-extern GLboolean __glXFreeContext(__GLXcontext * glxc);
extern void __glXFlushContextCache(void);
extern Bool __glXAddContext(__GLXcontext * cx);
diff --git a/glx/glxscreens.c b/glx/glxscreens.c
index 78769f401..ac2e43e95 100644
--- a/glx/glxscreens.c
+++ b/glx/glxscreens.c
@@ -160,20 +160,6 @@ static const char GLServerExtensions[] =
*/
unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION;
unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION;
-static char GLXServerExtensions[] =
- "GLX_ARB_multisample "
- "GLX_EXT_visual_info "
- "GLX_EXT_visual_rating "
- "GLX_EXT_import_context "
- "GLX_EXT_texture_from_pixmap "
- "GLX_OML_swap_method "
- "GLX_SGI_make_current_read "
-#ifndef __APPLE__
- "GLX_SGIS_multisample "
-#endif
- "GLX_SGIX_fbconfig "
- "GLX_SGIX_pbuffer "
- "GLX_MESA_copy_sub_buffer ";
static Bool
glxCloseScreen(ScreenPtr pScreen)
@@ -329,7 +315,7 @@ __glXScreenInit(__GLXscreen * pGlxScreen, ScreenPtr pScreen)
pGlxScreen->pScreen = pScreen;
pGlxScreen->GLextensions = strdup(GLServerExtensions);
- pGlxScreen->GLXextensions = strdup(GLXServerExtensions);
+ pGlxScreen->GLXextensions = strdup("");
/* All GLX providers must support all of the functionality required for at
* least GLX 1.2. If the provider supports a higher version, the GLXminor
diff --git a/glx/indirect_dispatch.c b/glx/indirect_dispatch.c
index 329b2e61e..7b125b4ce 100644
--- a/glx/indirect_dispatch.c
+++ b/glx/indirect_dispatch.c
@@ -4020,6 +4020,99 @@ __glXDisp_DrawBuffers(GLbyte * pc)
DrawBuffers(n, (const GLenum *) (pc + 4));
}
+int
+__glXDisp_GetVertexAttribdv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBDVPROC GetVertexAttribdv =
+ __glGetProcAddress("glGetVertexAttribdv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = *(GLenum *) (pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribdv_size(pname);
+ GLdouble answerBuffer[200];
+ GLdouble *params =
+ __glXGetAnswerBuffer(cl, compsize * 8, answerBuffer,
+ sizeof(answerBuffer), 8);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribdv(*(GLuint *) (pc + 0), pname, params);
+ __glXSendReply(cl->client, params, compsize, 8, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
+int
+__glXDisp_GetVertexAttribfv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv =
+ __glGetProcAddress("glGetVertexAttribfv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = *(GLenum *) (pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribfv_size(pname);
+ GLfloat answerBuffer[200];
+ GLfloat *params =
+ __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer,
+ sizeof(answerBuffer), 4);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribfv(*(GLuint *) (pc + 0), pname, params);
+ __glXSendReply(cl->client, params, compsize, 4, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
+int
+__glXDisp_GetVertexAttribiv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv =
+ __glGetProcAddress("glGetVertexAttribiv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = *(GLenum *) (pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribiv_size(pname);
+ GLint answerBuffer[200];
+ GLint *params =
+ __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer,
+ sizeof(answerBuffer), 4);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribiv(*(GLuint *) (pc + 0), pname, params);
+ __glXSendReply(cl->client, params, compsize, 4, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
void
__glXDisp_VertexAttrib1dv(GLbyte * pc)
{
@@ -5100,3 +5193,19 @@ __glXDisp_ActiveStencilFaceEXT(GLbyte * pc)
__glGetProcAddress("glActiveStencilFaceEXT");
ActiveStencilFaceEXT(*(GLenum *) (pc + 0));
}
+
+void
+__glXDisp_BindFramebufferEXT(GLbyte * pc)
+{
+ PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT =
+ __glGetProcAddress("glBindFramebufferEXT");
+ BindFramebufferEXT(*(GLenum *) (pc + 0), *(GLuint *) (pc + 4));
+}
+
+void
+__glXDisp_BindRenderbufferEXT(GLbyte * pc)
+{
+ PFNGLBINDRENDERBUFFEREXTPROC BindRenderbufferEXT =
+ __glGetProcAddress("glBindRenderbufferEXT");
+ BindRenderbufferEXT(*(GLenum *) (pc + 0), *(GLuint *) (pc + 4));
+}
diff --git a/glx/indirect_dispatch.h b/glx/indirect_dispatch.h
index e6e3fdacf..7969e322f 100644
--- a/glx/indirect_dispatch.h
+++ b/glx/indirect_dispatch.h
@@ -116,6 +116,10 @@ extern _X_HIDDEN void __glXDisp_LightModeliv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_LightModeliv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_VertexAttribs1dvNV(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_VertexAttribs1dvNV(GLbyte * pc);
+extern _X_HIDDEN int __glXDisp_GetVertexAttribfv(struct __GLXclientStateRec *,
+ GLbyte *);
+extern _X_HIDDEN int __glXDispSwap_GetVertexAttribfv(struct __GLXclientStateRec
+ *, GLbyte *);
extern _X_HIDDEN void __glXDisp_Normal3bv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_Normal3bv(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_VendorPrivate(struct __GLXclientStateRec *,
@@ -413,6 +417,10 @@ extern _X_HIDDEN void __glXDisp_TexGenfv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_TexGenfv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_VertexAttrib4dvNV(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_VertexAttrib4dvNV(GLbyte * pc);
+extern _X_HIDDEN int __glXDisp_GetVertexAttribiv(struct __GLXclientStateRec *,
+ GLbyte *);
+extern _X_HIDDEN int __glXDispSwap_GetVertexAttribiv(struct __GLXclientStateRec
+ *, GLbyte *);
extern _X_HIDDEN void __glXDisp_DrawBuffers(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_DrawBuffers(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_CreateContextWithConfigSGIX(struct
@@ -552,6 +560,8 @@ extern _X_HIDDEN void __glXDisp_MultiTexCoord1sv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_MultiTexCoord1sv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_RasterPos3sv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_RasterPos3sv(GLbyte * pc);
+extern _X_HIDDEN void __glXDisp_BindFramebufferEXT(GLbyte * pc);
+extern _X_HIDDEN void __glXDispSwap_BindFramebufferEXT(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_PushAttrib(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_PushAttrib(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_DestroyPbuffer(struct __GLXclientStateRec *,
@@ -676,6 +686,8 @@ extern _X_HIDDEN int __glXDisp_GetTexParameteriv(struct __GLXclientStateRec *,
GLbyte *);
extern _X_HIDDEN int __glXDispSwap_GetTexParameteriv(struct __GLXclientStateRec
*, GLbyte *);
+extern _X_HIDDEN void __glXDisp_VertexAttribs4dvNV(GLbyte * pc);
+extern _X_HIDDEN void __glXDispSwap_VertexAttribs4dvNV(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_VertexAttrib3sv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_VertexAttrib3sv(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_IsQuery(struct __GLXclientStateRec *, GLbyte *);
@@ -776,8 +788,6 @@ extern _X_HIDDEN void __glXDisp_ColorMaterial(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_ColorMaterial(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_VertexAttribs1svNV(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_VertexAttribs1svNV(GLbyte * pc);
-extern _X_HIDDEN void __glXDisp_VertexAttrib1fvNV(GLbyte * pc);
-extern _X_HIDDEN void __glXDispSwap_VertexAttrib1fvNV(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_GetSeparableFilter(struct __GLXclientStateRec *,
GLbyte *);
extern _X_HIDDEN int __glXDispSwap_GetSeparableFilter(struct __GLXclientStateRec
@@ -803,6 +813,10 @@ extern _X_HIDDEN int __glXDispSwap_RenderLarge(struct __GLXclientStateRec *,
GLbyte *);
extern _X_HIDDEN void __glXDisp_PolygonOffset(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_PolygonOffset(GLbyte * pc);
+extern _X_HIDDEN int __glXDisp_GetVertexAttribdv(struct __GLXclientStateRec *,
+ GLbyte *);
+extern _X_HIDDEN int __glXDispSwap_GetVertexAttribdv(struct __GLXclientStateRec
+ *, GLbyte *);
extern _X_HIDDEN void __glXDisp_Normal3dv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_Normal3dv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_Lightf(GLbyte * pc);
@@ -960,6 +974,8 @@ extern _X_HIDDEN void __glXDisp_CopyTexImage1D(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_CopyTexImage1D(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_RasterPos2dv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_RasterPos2dv(GLbyte * pc);
+extern _X_HIDDEN void __glXDisp_VertexAttrib1fvNV(GLbyte * pc);
+extern _X_HIDDEN void __glXDispSwap_VertexAttrib1fvNV(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_Fogiv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_Fogiv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_EndQuery(GLbyte * pc);
@@ -1010,6 +1026,8 @@ extern _X_HIDDEN void __glXDisp_MultiTexCoord1iv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_MultiTexCoord1iv(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_Vertex2fv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_Vertex2fv(GLbyte * pc);
+extern _X_HIDDEN void __glXDisp_BindRenderbufferEXT(GLbyte * pc);
+extern _X_HIDDEN void __glXDispSwap_BindRenderbufferEXT(GLbyte * pc);
extern _X_HIDDEN void __glXDisp_Vertex3sv(GLbyte * pc);
extern _X_HIDDEN void __glXDispSwap_Vertex3sv(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_GetQueryObjectiv(struct __GLXclientStateRec *,
@@ -1156,8 +1174,6 @@ extern _X_HIDDEN int __glXDisp_GetConvolutionFilterEXT(struct
extern _X_HIDDEN int __glXDispSwap_GetConvolutionFilterEXT(struct
__GLXclientStateRec
*, GLbyte *);
-extern _X_HIDDEN void __glXDisp_VertexAttribs4dvNV(GLbyte * pc);
-extern _X_HIDDEN void __glXDispSwap_VertexAttribs4dvNV(GLbyte * pc);
extern _X_HIDDEN int __glXDisp_GetTexGenfv(struct __GLXclientStateRec *,
GLbyte *);
extern _X_HIDDEN int __glXDispSwap_GetTexGenfv(struct __GLXclientStateRec *,
diff --git a/glx/indirect_dispatch_swap.c b/glx/indirect_dispatch_swap.c
index 647d0c985..7bcb35385 100644
--- a/glx/indirect_dispatch_swap.c
+++ b/glx/indirect_dispatch_swap.c
@@ -3835,8 +3835,8 @@ __glXDispSwap_MultiTexCoord1dv(GLbyte * pc)
#endif
glMultiTexCoord1dvARB((GLenum) bswap_ENUM(pc + 8),
- (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0),
- 1));
+ (const GLdouble *)
+ bswap_64_array((uint64_t *) (pc + 0), 1));
}
void
@@ -3859,8 +3859,8 @@ void
__glXDispSwap_MultiTexCoord1sv(GLbyte * pc)
{
glMultiTexCoord1svARB((GLenum) bswap_ENUM(pc + 0),
- (const GLshort *) bswap_16_array((uint16_t *) (pc + 4),
- 1));
+ (const GLshort *)
+ bswap_16_array((uint16_t *) (pc + 4), 1));
}
void
@@ -3874,8 +3874,8 @@ __glXDispSwap_MultiTexCoord2dv(GLbyte * pc)
#endif
glMultiTexCoord2dvARB((GLenum) bswap_ENUM(pc + 16),
- (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0),
- 2));
+ (const GLdouble *)
+ bswap_64_array((uint64_t *) (pc + 0), 2));
}
void
@@ -3898,8 +3898,8 @@ void
__glXDispSwap_MultiTexCoord2sv(GLbyte * pc)
{
glMultiTexCoord2svARB((GLenum) bswap_ENUM(pc + 0),
- (const GLshort *) bswap_16_array((uint16_t *) (pc + 4),
- 2));
+ (const GLshort *)
+ bswap_16_array((uint16_t *) (pc + 4), 2));
}
void
@@ -3913,8 +3913,8 @@ __glXDispSwap_MultiTexCoord3dv(GLbyte * pc)
#endif
glMultiTexCoord3dvARB((GLenum) bswap_ENUM(pc + 24),
- (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0),
- 3));
+ (const GLdouble *)
+ bswap_64_array((uint64_t *) (pc + 0), 3));
}
void
@@ -3937,8 +3937,8 @@ void
__glXDispSwap_MultiTexCoord3sv(GLbyte * pc)
{
glMultiTexCoord3svARB((GLenum) bswap_ENUM(pc + 0),
- (const GLshort *) bswap_16_array((uint16_t *) (pc + 4),
- 3));
+ (const GLshort *)
+ bswap_16_array((uint16_t *) (pc + 4), 3));
}
void
@@ -3952,8 +3952,8 @@ __glXDispSwap_MultiTexCoord4dv(GLbyte * pc)
#endif
glMultiTexCoord4dvARB((GLenum) bswap_ENUM(pc + 32),
- (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0),
- 4));
+ (const GLdouble *)
+ bswap_64_array((uint64_t *) (pc + 0), 4));
}
void
@@ -3976,8 +3976,8 @@ void
__glXDispSwap_MultiTexCoord4sv(GLbyte * pc)
{
glMultiTexCoord4svARB((GLenum) bswap_ENUM(pc + 0),
- (const GLshort *) bswap_16_array((uint16_t *) (pc + 4),
- 4));
+ (const GLshort *)
+ bswap_16_array((uint16_t *) (pc + 4), 4));
}
void
@@ -4436,6 +4436,105 @@ __glXDispSwap_DrawBuffers(GLbyte * pc)
DrawBuffers(n, (const GLenum *) bswap_32_array((uint32_t *) (pc + 4), 0));
}
+int
+__glXDispSwap_GetVertexAttribdv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBDVPROC GetVertexAttribdv =
+ __glGetProcAddress("glGetVertexAttribdv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx =
+ __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = (GLenum) bswap_ENUM(pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribdv_size(pname);
+ GLdouble answerBuffer[200];
+ GLdouble *params =
+ __glXGetAnswerBuffer(cl, compsize * 8, answerBuffer,
+ sizeof(answerBuffer), 8);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribdv((GLuint) bswap_CARD32(pc + 0), pname, params);
+ (void) bswap_64_array((uint64_t *) params, compsize);
+ __glXSendReplySwap(cl->client, params, compsize, 8, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
+int
+__glXDispSwap_GetVertexAttribfv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv =
+ __glGetProcAddress("glGetVertexAttribfv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx =
+ __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = (GLenum) bswap_ENUM(pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribfv_size(pname);
+ GLfloat answerBuffer[200];
+ GLfloat *params =
+ __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer,
+ sizeof(answerBuffer), 4);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribfv((GLuint) bswap_CARD32(pc + 0), pname, params);
+ (void) bswap_32_array((uint32_t *) params, compsize);
+ __glXSendReplySwap(cl->client, params, compsize, 4, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
+int
+__glXDispSwap_GetVertexAttribiv(__GLXclientState * cl, GLbyte * pc)
+{
+ PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv =
+ __glGetProcAddress("glGetVertexAttribiv");
+ xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
+ int error;
+ __GLXcontext *const cx =
+ __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+ if (cx != NULL) {
+ const GLenum pname = (GLenum) bswap_ENUM(pc + 4);
+
+ const GLuint compsize = __glGetVertexAttribiv_size(pname);
+ GLint answerBuffer[200];
+ GLint *params =
+ __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer,
+ sizeof(answerBuffer), 4);
+
+ if (params == NULL)
+ return BadAlloc;
+ __glXClearErrorOccured();
+
+ GetVertexAttribiv((GLuint) bswap_CARD32(pc + 0), pname, params);
+ (void) bswap_32_array((uint32_t *) params, compsize);
+ __glXSendReplySwap(cl->client, params, compsize, 4, GL_FALSE, 0);
+ error = Success;
+ }
+
+ return error;
+}
+
void
__glXDispSwap_VertexAttrib1dv(GLbyte * pc)
{
@@ -5669,3 +5768,21 @@ __glXDispSwap_ActiveStencilFaceEXT(GLbyte * pc)
__glGetProcAddress("glActiveStencilFaceEXT");
ActiveStencilFaceEXT((GLenum) bswap_ENUM(pc + 0));
}
+
+void
+__glXDispSwap_BindFramebufferEXT(GLbyte * pc)
+{
+ PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT =
+ __glGetProcAddress("glBindFramebufferEXT");
+ BindFramebufferEXT((GLenum) bswap_ENUM(pc + 0),
+ (GLuint) bswap_CARD32(pc + 4));
+}
+
+void
+__glXDispSwap_BindRenderbufferEXT(GLbyte * pc)
+{
+ PFNGLBINDRENDERBUFFEREXTPROC BindRenderbufferEXT =
+ __glGetProcAddress("glBindRenderbufferEXT");
+ BindRenderbufferEXT((GLenum) bswap_ENUM(pc + 0),
+ (GLuint) bswap_CARD32(pc + 4));
+}
diff --git a/glx/indirect_size_get.c b/glx/indirect_size_get.c
index f87931193..a55957b79 100644
--- a/glx/indirect_size_get.c
+++ b/glx/indirect_size_get.c
@@ -603,7 +603,11 @@ __glGetBooleanv_size(GLenum e)
case GL_OCCLUSION_TEST_RESULT_HP:
case GL_LIGHT_MODEL_COLOR_CONTROL:
case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB:
+/* case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:*/
case GL_RESET_NOTIFICATION_STRATEGY_ARB:
+/* case GL_MAX_DEBUG_GROUP_STACK_DEPTH: */
+/* case GL_DEBUG_GROUP_STACK_DEPTH: */
+/* case GL_MAX_LABEL_LENGTH: */
case GL_CURRENT_FOG_COORD:
case GL_FOG_COORDINATE_ARRAY_TYPE:
case GL_FOG_COORDINATE_ARRAY_STRIDE:
@@ -749,8 +753,11 @@ __glGetBooleanv_size(GLenum e)
/* case GL_MAX_SAMPLES_EXT:*/
case GL_MAX_SERVER_WAIT_TIMEOUT:
case GL_MAX_DEBUG_MESSAGE_LENGTH_ARB:
+/* case GL_MAX_DEBUG_MESSAGE_LENGTH:*/
case GL_MAX_DEBUG_LOGGED_MESSAGES_ARB:
+/* case GL_MAX_DEBUG_LOGGED_MESSAGES:*/
case GL_DEBUG_LOGGED_MESSAGES_ARB:
+/* case GL_DEBUG_LOGGED_MESSAGES:*/
case GL_RASTER_POSITION_UNCLIPPED_IBM:
return 1;
case GL_SMOOTH_POINT_SIZE_RANGE:
@@ -928,7 +935,9 @@ __glGetPointerv_size(GLenum e)
{
switch (e) {
case GL_DEBUG_CALLBACK_FUNCTION_ARB:
+/* case GL_DEBUG_CALLBACK_FUNCTION:*/
case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
+/* case GL_DEBUG_CALLBACK_USER_PARAM:*/
return 1;
default:
return 0;
@@ -1105,6 +1114,23 @@ __glGetQueryiv_size(GLenum e)
}
_X_INTERNAL PURE FASTCALL GLint
+__glGetVertexAttribdv_size(GLenum e)
+{
+ switch (e) {
+ case GL_VERTEX_PROGRAM_ARB:
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
+ case GL_CURRENT_VERTEX_ATTRIB_ARB:
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+_X_INTERNAL PURE FASTCALL GLint
__glGetProgramivARB_size(GLenum e)
{
switch (e) {
@@ -1216,5 +1242,7 @@ ALIAS(Fogiv, Fogfv)
ALIAS(GetMinmaxParameteriv, GetMinmaxParameterfv)
ALIAS(PointParameteriv, PointParameterfv)
ALIAS(GetQueryObjectuiv, GetQueryObjectiv)
+ ALIAS(GetVertexAttribfv, GetVertexAttribdv)
+ ALIAS(GetVertexAttribiv, GetVertexAttribdv)
#undef PURE
#undef FASTCALL
diff --git a/glx/indirect_size_get.h b/glx/indirect_size_get.h
index 9b6203669..2358e249b 100644
--- a/glx/indirect_size_get.h
+++ b/glx/indirect_size_get.h
@@ -83,6 +83,9 @@ extern _X_INTERNAL PURE FASTCALL GLint __glGetMinmaxParameteriv_size(GLenum);
extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryObjectiv_size(GLenum);
extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryObjectuiv_size(GLenum);
extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryiv_size(GLenum);
+extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribdv_size(GLenum);
+extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribfv_size(GLenum);
+extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribiv_size(GLenum);
extern _X_INTERNAL PURE FASTCALL GLint __glGetProgramivARB_size(GLenum);
extern _X_INTERNAL PURE FASTCALL GLint
__glGetFramebufferAttachmentParameteriv_size(GLenum);
diff --git a/glx/indirect_table.c b/glx/indirect_table.c
index 33e3d6a22..8061e17fb 100644
--- a/glx/indirect_table.c
+++ b/glx/indirect_table.c
@@ -636,8 +636,10 @@ static const void *Render_function_table[408][2] = {
/* [ 232] = 232 */ {__glXDisp_EndQuery, __glXDispSwap_EndQuery},
/* [ 233] = 233 */ {__glXDisp_DrawBuffers, __glXDispSwap_DrawBuffers},
/* [ 234] = 234 */ {__glXDisp_ClampColor, __glXDispSwap_ClampColor},
- /* [ 235] = 235 */ {NULL, NULL},
- /* [ 236] = 236 */ {NULL, NULL},
+ /* [ 235] = 235 */ {__glXDisp_BindRenderbuffer,
+ __glXDispSwap_BindRenderbuffer},
+ /* [ 236] = 236 */ {__glXDisp_BindFramebuffer,
+ __glXDispSwap_BindFramebuffer},
/* [ 237] = 237 */ {__glXDisp_FramebufferTextureLayer,
__glXDispSwap_FramebufferTextureLayer},
/* [ 238] = 238 */ {NULL, NULL},
@@ -903,14 +905,14 @@ static const void *Render_function_table[408][2] = {
/* [ 401] = 4313 */ {NULL, NULL},
/* [ 402] = 4314 */ {NULL, NULL},
/* [ 403] = 4315 */ {NULL, NULL},
- /* [ 404] = 4316 */ {__glXDisp_BindRenderbuffer,
- __glXDispSwap_BindRenderbuffer},
+ /* [ 404] = 4316 */ {__glXDisp_BindRenderbufferEXT,
+ __glXDispSwap_BindRenderbufferEXT},
/* [ 405] = 4317 */ {__glXDisp_DeleteRenderbuffers,
__glXDispSwap_DeleteRenderbuffers},
/* [ 406] = 4318 */ {__glXDisp_RenderbufferStorage,
__glXDispSwap_RenderbufferStorage},
- /* [ 407] = 4319 */ {__glXDisp_BindFramebuffer,
- __glXDispSwap_BindFramebuffer},
+ /* [ 407] = 4319 */ {__glXDisp_BindFramebufferEXT,
+ __glXDispSwap_BindFramebufferEXT},
};
static const int_fast16_t Render_size_table[408][2] = {
@@ -1149,8 +1151,8 @@ static const int_fast16_t Render_size_table[408][2] = {
/* [232] = 232 */ {8, ~0},
/* [233] = 233 */ {8, 36},
/* [234] = 234 */ {12, ~0},
- /* [235] = 235 */ {0, ~0},
- /* [236] = 236 */ {0, ~0},
+ /* [235] = 235 */ {12, ~0},
+ /* [236] = 236 */ {12, ~0},
/* [237] = 237 */ {24, ~0},
/* [238] = 238 */ {0, ~0},
/* [239] = 239 */ {0, ~0},
@@ -1697,9 +1699,12 @@ static const void *VendorPriv_function_table[104][2] = {
/* [ 26] = 1298 */ {NULL, NULL},
/* [ 27] = 1299 */ {NULL, NULL},
/* [ 28] = 1300 */ {NULL, NULL},
- /* [ 29] = 1301 */ {NULL, NULL},
- /* [ 30] = 1302 */ {NULL, NULL},
- /* [ 31] = 1303 */ {NULL, NULL},
+ /* [ 29] = 1301 */ {__glXDisp_GetVertexAttribdv,
+ __glXDispSwap_GetVertexAttribdv},
+ /* [ 30] = 1302 */ {__glXDisp_GetVertexAttribfv,
+ __glXDispSwap_GetVertexAttribfv},
+ /* [ 31] = 1303 */ {__glXDisp_GetVertexAttribiv,
+ __glXDispSwap_GetVertexAttribiv},
/* [ 32] = 1304 */ {__glXDisp_IsProgramARB, __glXDispSwap_IsProgramARB},
/* [ 33] = 1305 */ {__glXDisp_GetProgramLocalParameterfvARB,
__glXDispSwap_GetProgramLocalParameterfvARB},
diff --git a/glx/rensize.c b/glx/rensize.c
index bcc3a53ad..a78e60c8f 100644
--- a/glx/rensize.c
+++ b/glx/rensize.c
@@ -226,12 +226,14 @@ __glXImageSize(GLenum format, GLenum type, GLenum target,
case GL_INTENSITY:
elementsPerGroup = 1;
break;
+ case GL_RG:
case GL_422_EXT:
case GL_422_REV_EXT:
case GL_422_AVERAGE_EXT:
case GL_422_REV_AVERAGE_EXT:
case GL_DEPTH_STENCIL_NV:
case GL_DEPTH_STENCIL_MESA:
+ case GL_YCBCR_422_APPLE:
case GL_YCBCR_MESA:
case GL_LUMINANCE_ALPHA:
elementsPerGroup = 2;
diff --git a/hw/dmx/doc/dmx.xml b/hw/dmx/doc/dmx.xml
index 6d7df4133..c6c8544ff 100644
--- a/hw/dmx/doc/dmx.xml
+++ b/hw/dmx/doc/dmx.xml
@@ -1268,7 +1268,7 @@ default routine is chosen during GC validation.
<para>Note that some pointers to functions that draw to the screen are
stored in the Screen structure. They include GetImage(), GetSpans(),
-CopyWindow() and RestoreAreas().
+PaintWindow(), CopyWindow() and RestoreAreas().
</para>
</sect3>
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index d9a44788c..97abc8542 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -316,8 +316,8 @@ topdir=$1
shift
LC_ALL=C
export LC_ALL
-${CPP:-cpp} "$@" sdksyms.c > /dev/null || exit $?
-${CPP:-cpp} "$@" sdksyms.c | ${AWK:-awk} -v topdir=$topdir '
+${CPP:-cpp} "$@" -DSDKSYMS sdksyms.c > /dev/null || exit $?
+${CPP:-cpp} "$@" -DSDKSYMS sdksyms.c | ${AWK:-awk} -v topdir=$topdir '
BEGIN {
sdk = 0;
print("/*");
diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index d7229cecb..b0d42b7da 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -300,7 +300,7 @@ QuartzUpdateScreens(void)
quartzProcs->UpdateScreen(pScreen);
/* miPaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */
- miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
+ pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
/* Tell RandR about the new size, so new connections get the correct info */
RRScreenSizeNotify(pScreen);
diff --git a/hw/xwin/InitInput.c b/hw/xwin/InitInput.c
index 38203c906..3e9ee41e6 100644
--- a/hw/xwin/InitInput.c
+++ b/hw/xwin/InitInput.c
@@ -39,7 +39,6 @@
#ifdef XWIN_CLIPBOARD
int winProcEstablishConnection(ClientPtr /* client */ );
-int winProcSetSelectionOwner(ClientPtr /* client */ );
#endif
/*
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index 6b5c38d92..6a75723c5 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -35,12 +35,10 @@ from The Open Group.
#include "winmsg.h"
#include "winconfig.h"
#include "winprefs.h"
-#ifdef XWIN_CLIPBOARD
-#include "X11/Xlocale.h"
-#endif
#ifdef DPMSExtension
#include "dpmsproc.h"
#endif
+#include <locale.h>
#ifdef __CYGWIN__
#include <mntent.h>
#endif
@@ -58,7 +56,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
HANDLE hToken,
DWORD dwFlags, LPTSTR pszPath);
#endif
+#include "winmonitors.h"
+#include "pseudoramiX/pseudoramiX.h"
+
#include "glx_extinit.h"
+#include "dixmain.h"
#ifdef XWIN_GLX_WINDOWS
#include "glx/glwindows.h"
#endif
@@ -66,27 +68,12 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
/*
* References to external symbols
*/
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
-extern pthread_t g_ptClipboardProc;
-extern HWND g_hwndClipboard;
-extern Bool g_fClipboard;
-#endif
+extern Bool noRRXineramaExtension;
/*
* Function prototypes
*/
-#ifdef XWIN_CLIPBOARD
-static void
- winClipboardShutdown(void);
-#endif
-
-static Bool
- winCheckDisplayNumber(void);
-
void
winLogCommandLine(int argc, char *argv[]);
@@ -100,6 +87,11 @@ Bool
const char *winGetBaseDir(void);
#endif
+static void winCheckMount(void);
+
+extern Bool XSupportsLocale(void);
+extern Status XInitThreads(void);
+
/*
* For the depth 24 pixmap we default to 32 bits per pixel, but
* we change this pixmap format later if we detect that the display
@@ -125,31 +117,6 @@ static PixmapFormatRec g_PixmapFormats[] = {
const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown(void)
-{
- /* Close down clipboard resources */
- if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
- /* Synchronously destroy the clipboard window */
- if (g_hwndClipboard != NULL) {
- SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
- /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
- }
- else
- return;
-
- /* Wait for the clipboard thread to exit */
- pthread_join(g_ptClipboardProc, NULL);
-
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
-
- winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
- }
-}
-#endif
-
static const ExtensionModule xwinExtensions[] = {
#ifdef GLXEXT
{ GlxExtensionInit, "GLX", &noGlxExtension },
@@ -206,6 +173,8 @@ main(int argc, char *argv[], char *envp[])
ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn);
}
+ winCheckMount();
+
return dix_main(argc, argv, envp);
}
@@ -292,6 +261,8 @@ AbortDDX(enum ExitCode error)
}
#ifdef __CYGWIN__
+extern Bool nolock;
+
/* hasmntopt is currently not implemented for cygwin */
static const char *
winCheckMntOpt(const struct mntent *mnt, const char *opt)
@@ -316,6 +287,9 @@ winCheckMntOpt(const struct mntent *mnt, const char *opt)
return NULL;
}
+/*
+ Check mounts and issue warnings/activate workarounds as needed
+ */
static void
winCheckMount(void)
{
@@ -325,6 +299,7 @@ winCheckMount(void)
enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
level = none, curlevel;
BOOL binary = TRUE;
+ BOOL fat = TRUE;
mnt = setmntent("/etc/mtab", "r");
if (mnt == NULL) {
@@ -363,6 +338,11 @@ winCheckMount(void)
binary = FALSE;
else
binary = TRUE;
+
+ if (strcmp(ent->mnt_type, "vfat") == 0)
+ fat = TRUE;
+ else
+ fat = FALSE;
}
if (endmntent(mnt) != 1) {
@@ -372,6 +352,12 @@ winCheckMount(void)
if (!binary)
winMsg(X_WARNING, "/tmp mounted in textmode\n");
+
+ if (fat) {
+ winMsg(X_WARNING,
+ "/tmp mounted on FAT filesystem, activating -nolock\n");
+ nolock = TRUE;
+ }
}
#else
static void
@@ -771,7 +757,7 @@ winUseMsg(void)
ErrorF("-engine engine_type_id\n"
"\tOverride the server's automatically selected engine type:\n"
"\t\t1 - Shadow GDI\n"
- "\t\t2 - Shadow DirectDraw\n"
+ "\t\t2 - Shadow DirectDraw - obsolete\n"
"\t\t4 - Shadow DirectDraw4 Non-Locking\n"
#ifdef XWIN_PRIMARYFB
"\t\t8 - Primary DirectDraw - obsolete\n"
@@ -783,7 +769,7 @@ winUseMsg(void)
ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
- ErrorF("-hostintitle\n"
+ ErrorF("-[no]hostintitle\n"
"\tIn multiwindow mode, add remote host names to window titles.\n");
ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
@@ -954,14 +940,6 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
"Exiting.\n");
}
- /* Check for duplicate invocation on same display number. */
- if (serverGeneration == 1 && !winCheckDisplayNumber()) {
- if (g_fSilentDupError)
- g_fSilentFatalError = TRUE;
- FatalError("InitOutput - Duplicate invocation on display "
- "number: %s. Exiting.\n", display);
- }
-
#ifdef XWIN_XF86CONFIG
/* Try to read the xorg.conf-style configuration file */
if (!winReadConfigfile())
@@ -1013,6 +991,61 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
}
}
+ /*
+ Unless full xinerama has been explicitly enabled, register all native screens with pseudoramiX
+ */
+ if (!noPanoramiXExtension)
+ noPseudoramiXExtension = TRUE;
+
+ if ((g_ScreenInfo[0].fMultipleMonitors) && !noPseudoramiXExtension)
+ {
+ int pass;
+
+ noRRXineramaExtension = TRUE;
+
+ PseudoramiXExtensionInit();
+
+ /* Add primary monitor on pass 0, other monitors on pass 1, to ensure
+ the primary monitor is first in XINERAMA list */
+ for (pass = 0; pass < 2; pass++)
+ {
+ int iMonitor;
+
+ for (iMonitor = 1; ; iMonitor++)
+ {
+ struct GetMonitorInfoData data;
+ QueryMonitor(iMonitor, &data);
+ if (data.bMonitorSpecifiedExists)
+ {
+ MONITORINFO mi;
+ mi.cbSize = sizeof(MONITORINFO);
+
+ if (GetMonitorInfo(data.monitorHandle, &mi))
+ {
+ /* pass == 1 XOR primary monitor flags is set */
+ if ((!(pass == 1)) != (!(mi.dwFlags & MONITORINFOF_PRIMARY)))
+ {
+ /*
+ Note the screen origin in a normalized coordinate space where (0,0) is at the top left
+ of the native virtual desktop area
+ */
+ data.monitorOffsetX = data.monitorOffsetX - GetSystemMetrics(SM_XVIRTUALSCREEN);
+ data.monitorOffsetY = data.monitorOffsetY - GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ winDebug ("InitOutput - screen %d added at virtual desktop coordinate (%d,%d) (pseudoramiX) \n",
+ iMonitor-1, data.monitorOffsetX, data.monitorOffsetY);
+
+ PseudoramiXAddScreen(data.monitorOffsetX, data.monitorOffsetY,
+ data.monitorWidth, data.monitorHeight);
+ }
+ }
+ }
+ else
+ break;
+ }
+ }
+ }
+
#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
/* Generate a cookie used by internal clients for authorization */
@@ -1021,11 +1054,24 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
/* Perform some one time initialization */
if (1 == serverGeneration) {
+ /* Allow multiple threads to access Xlib */
+ if (XInitThreads() == 0) {
+ ErrorF("XInitThreads failed.\n");
+ }
+
/*
* setlocale applies to all threads in the current process.
* Apply locale specified in LANG environment variable.
*/
- setlocale(LC_ALL, "");
+ if (!setlocale(LC_ALL, "")) {
+ ErrorF("setlocale failed.\n");
+ }
+
+ /* See if X supports the current locale */
+ if (XSupportsLocale() == FALSE) {
+ ErrorF("Warning: Locale not supported by X, falling back to 'C' locale.\n");
+ setlocale(LC_ALL, "C");
+ }
}
#endif
@@ -1033,70 +1079,3 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
winDebug("InitOutput - Returning.\n");
#endif
}
-
-/*
- * winCheckDisplayNumber - Check if another instance of Cygwin/X is
- * already running on the same display number. If no one exists,
- * make a mutex to prevent new instances from running on the same display.
- *
- * return FALSE if the display number is already used.
- */
-
-static Bool
-winCheckDisplayNumber(void)
-{
- int nDisp;
- HANDLE mutex;
- char name[MAX_PATH];
- char *pszPrefix = '\0';
- OSVERSIONINFO osvi = { 0 };
-
- /* Check display range */
- nDisp = atoi(display);
- if (nDisp < 0 || nDisp > 65535) {
- ErrorF("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
- return FALSE;
- }
-
- /* Set first character of mutex name to null */
- name[0] = '\0';
-
- /* Get operating system version information */
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- GetVersionEx(&osvi);
-
- /* Want a mutex shared among all terminals on NT > 4.0 */
- if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5) {
- pszPrefix = "Global\\";
- }
-
- /* Setup Cygwin/X specific part of name */
- snprintf(name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
-
- /* Windows automatically releases the mutex when this process exits */
- mutex = CreateMutex(NULL, FALSE, name);
- if (!mutex) {
- LPVOID lpMsgBuf;
-
- /* Display a fancy error message */
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL);
- ErrorF("winCheckDisplayNumber - CreateMutex failed: %s\n",
- (LPSTR) lpMsgBuf);
- LocalFree(lpMsgBuf);
-
- return FALSE;
- }
- if (GetLastError() == ERROR_ALREADY_EXISTS) {
- ErrorF("winCheckDisplayNumber - "
- PROJECT_NAME " is already running on display %d\n", nDisp);
- return FALSE;
- }
-
- return TRUE;
-}
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 4ee963227..7c1375714 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -3,19 +3,16 @@ bin_PROGRAMS = XWin
if XWIN_CLIPBOARD
SRCS_CLIPBOARD = \
winclipboardinit.c \
- winclipboardtextconv.c \
- winclipboardthread.c \
- winclipboardwndproc.c \
- winclipboardwrappers.c \
- winclipboardxevents.c
+ winclipboardwrappers.c
DEFS_CLIPBOARD = -DXWIN_CLIPBOARD
+CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
endif
if XWIN_GLX_WINDOWS
GLX_DIR = glx
DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS
XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la
-XWIN_GLX_LINK_FLAGS = -lopengl32
+XWIN_GLX_SYS_LIBS = -lopengl32
endif
if XWIN_MULTIWINDOW
@@ -27,7 +24,8 @@ SRCS_MULTIWINDOW = \
propertystore.h \
winSetAppUserModelID.c
DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW
-MULTIWINDOW_LIBS = -lshlwapi -lole32
+MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32
+MULTIWINDOW_LIBS = $(top_builddir)/hw/xwin/wmutil/libXWinWMUtil.la
endif
if XWIN_MULTIWINDOWEXTWM
@@ -110,12 +108,9 @@ SRCS = InitInput.c \
winwindow.c \
winwndproc.c \
ddraw.h \
- winclipboard.h \
winconfig.h \
win.h \
winglobals.h \
- winkeybd.h \
- winkeynames.h \
winlayouts.h \
winmessages.h \
winmonitors.h \
@@ -126,6 +121,8 @@ SRCS = InitInput.c \
winprefs.h \
winresource.h \
winwindow.h \
+ windisplay.c \
+ windisplay.h \
XWin.rc \
$(top_srcdir)/mi/miinitext.c \
$(SRCS_CLIPBOARD) \
@@ -150,16 +147,37 @@ XWin_SOURCES = $(SRCS)
AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless
XWIN_SYS_LIBS += -ldxguid
-XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la \
- $(top_builddir)/Xext/libXextdpmsstubs.la \
- $(top_builddir)/Xi/libXistubs.la
-XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
-XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
+
+XWIN_LIBS += \
+ $(top_builddir)/pseudoramiX/libPseudoramiX.la \
+ $(top_builddir)/Xext/libXextdpmsstubs.la \
+ $(top_builddir)/Xi/libXistubs.la
+
+XWin_DEPENDENCIES = \
+ $(MULTIWINDOW_LIBS) \
+ $(MULTIWINDOWEXTWM_LIBS) \
+ $(XWIN_GLX_LIBS) \
+ $(XWIN_LIBS) \
+ $(CLIPBOARD_LIBS) \
+ $(XSERVER_LIBS)
+
+XWin_LDADD = \
+ $(MULTIWINDOW_LIBS) \
+ $(MULTIWINDOWEXTWM_LIBS) \
+ $(XWIN_GLX_LIBS) \
+ $(XWIN_LIBS) \
+ $(CLIPBOARD_LIBS) \
+ $(XSERVER_LIBS) \
+ $(XWIN_GLX_SYS_LIBS) \
+ $(XSERVER_SYS_LIBS) \
+ $(XWIN_SYS_LIBS) \
+ $(MULTIWINDOW_SYS_LIBS)
+
XWin_LDFLAGS = -mwindows -Wl,--disable-stdcall-fixup $(LD_EXPORT_SYMBOLS_FLAG)
.rc.o:
- $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include
+ $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include -DHOST_TRIPLET=\"$(host)\"
XWin.o: XWin.rc XWin.exe.manifest X.ico
@@ -191,5 +209,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) .
-DIST_SUBDIRS = man glx .
+SUBDIRS = man $(GLX_DIR) wmutil winclipboard .
+DIST_SUBDIRS = man glx wmutil winclipboard .
diff --git a/hw/xwin/XWin.exe.manifest b/hw/xwin/XWin.exe.manifest
index 477334fb3..ea0e138f5 100755
--- a/hw/xwin/XWin.exe.manifest
+++ b/hw/xwin/XWin.exe.manifest
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
- <description>The XWin X Windows server for Cygwin.</description>
+ <description>The XWin X Windows server</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
@@ -18,4 +18,16 @@
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ </application>
+ </compatibility>
</assembly>
diff --git a/hw/xwin/XWin.rc b/hw/xwin/XWin.rc
index a142f3070..e74a9a5ef 100644
--- a/hw/xwin/XWin.rc
+++ b/hw/xwin/XWin.rc
@@ -46,7 +46,7 @@ FONT 8, "MS Shell Dlg 2"
BEGIN
CONTROL IDI_XWIN, IDC_STATIC, "Static", SS_ICON, 8, 8, 32, 32
LTEXT XVENDORNAMESHORT " X Server ", IDC_STATIC, 36, 8, 220, 8
- LTEXT VENDOR_MAN_VERSION, IDC_STATIC, 36, 18, 220, 8
+ LTEXT VENDOR_MAN_VERSION " (" HOST_TRIPLET ")", IDC_STATIC, 36, 18, 220, 8
LTEXT BUILDERSTRING, IDC_STATIC, 36, 28, 220, 8
LTEXT "This software is licensed under the terms of the MIT/X11 License.", IDC_STATIC, 36, 48, 220, 20
CONTROL __VENDORDWEBSUPPORT__, ID_ABOUT_WEBSITE, "Button",
@@ -93,6 +93,7 @@ BEGIN
POPUP "TRAYICON_MENU"
BEGIN
MENUITEM "&Hide Root Window", ID_APP_HIDE_ROOT
+ MENUITEM "Clipboard may use &PRIMARY selection", ID_APP_MONITOR_PRIMARY
MENUITEM "&About...", ID_APP_ABOUT
MENUITEM SEPARATOR
MENUITEM "E&xit...", ID_APP_EXIT
diff --git a/hw/xwin/glx/.gitignore b/hw/xwin/glx/.gitignore
index 062fd8573..9684410ac 100644
--- a/hw/xwin/glx/.gitignore
+++ b/hw/xwin/glx/.gitignore
@@ -1,3 +1,6 @@
# ignore generated files
-generated_gl_wrappers.c
+diag.txt
+generated_gl_shim.c
+generated_gl_thunks.c
+generated_gl_thunks.def
generated_wgl_wrappers.c
diff --git a/hw/xwin/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py
index cdbba638a..69ab1efa9 100755
--- a/hw/xwin/glx/gen_gl_wrappers.py
+++ b/hw/xwin/glx/gen_gl_wrappers.py
@@ -100,13 +100,16 @@ reg = Registry()
tree = etree.parse(regFilename)
reg.loadElementTree(tree)
-allVersions = '.*'
+if shim:
+ versions = '1\.[012]'
+else:
+ versions = '.*'
genOpts = CGeneratorOptions(
apiname = prefix,
profile = 'compatibility',
- versions = allVersions,
- emitversions = allVersions,
+ versions = versions,
+ emitversions = versions,
defaultExtensions = prefix, # Default extensions for GL
protectFile = protect,
protectFeature = protect,
@@ -257,7 +260,7 @@ class ThunkOutputGenerator(OutputGenerator):
pass
def beginFeature(self, interface, emit):
OutputGenerator.beginFeature(self, interface, emit)
- self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1')
+ self.OldVersion = (self.featureName in ['GL_VERSION_1_0', 'GL_VERSION_1_1'])
def endFeature(self):
OutputGenerator.endFeature(self)
def genType(self, typeinfo, name):
@@ -355,7 +358,7 @@ class ShimOutputGenerator(OutputGenerator):
pass
def beginFeature(self, interface, emit):
OutputGenerator.beginFeature(self, interface, emit)
- self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1') or self.featureName.startswith('GL_VERSION_1_2') or self.featureName.startswith('GL_ARB_imaging') or self.featureName.startswith('GL_ARB_multitexture') or self.featureName.startswith('GL_ARB_texture_compression')
+ self.OldVersion = (self.featureName in ['GL_VERSION_1_0', 'GL_VERSION_1_1', 'GL_VERSION_1_2', 'GL_ARB_imaging', 'GL_ARB_multitexture', 'GL_ARB_texture_compression'])
def endFeature(self):
OutputGenerator.endFeature(self)
def genType(self, typeinfo, name):
diff --git a/hw/xwin/glx/glwindows.h b/hw/xwin/glx/glwindows.h
index 4f859b498..34ff24c24 100644
--- a/hw/xwin/glx/glwindows.h
+++ b/hw/xwin/glx/glwindows.h
@@ -28,6 +28,9 @@
* DEALINGS IN THE SOFTWARE.
*/
+#ifndef GLWINDOWS_H
+#define GLWINDOWS_H
+
#include <GL/gl.h>
typedef struct {
@@ -53,3 +56,5 @@ int glWinSelectImplementation(int native);
#define GLWIN_TRACE_MSG(a, ...)
#define GLWIN_DEBUG_MSG(a, ...)
#endif
+
+#endif
diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c
index 9bfaac03d..454173666 100644
--- a/hw/xwin/glx/indirect.c
+++ b/hw/xwin/glx/indirect.c
@@ -155,6 +155,14 @@ struct __GLXWinConfig {
int pixelFormatIndex;
};
+typedef struct {
+ int notOpenGL;
+ int rgbaFloat;
+ int unsignedRgbaFloat;
+ int unknownPixelType;
+ int unaccelerated;
+} PixelFormatRejectStats;
+
/* ---------------------------------------------------------------------- */
/*
* Various debug helpers
@@ -340,13 +348,16 @@ swap_method_name(int mthd)
}
static void
-fbConfigsDump(unsigned int n, __GLXconfig * c)
+fbConfigsDump(unsigned int n, __GLXconfig * c, PixelFormatRejectStats *rejects)
{
LogMessage(X_INFO, "%d fbConfigs\n", n);
+ LogMessage(X_INFO, "ignored pixel formats: %d not OpenGL, %d RBGA float, %d RGBA unsigned float, %d unknown pixel type, %d unaccelerated\n",
+ rejects->notOpenGL, rejects->rgbaFloat, rejects->unsignedRgbaFloat,
+ rejects->unknownPixelType, rejects->unaccelerated);
if (g_iLogVerbose < 3)
return;
- ErrorF("%d fbConfigs\n", n);
+
ErrorF
("pxf vis fb render Ste aux accum MS drawable Group/\n");
ErrorF
@@ -425,7 +436,8 @@ static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
static void glxWinCreateConfigs(HDC dc, glxWinScreen * screen);
-static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen);
+static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen,
+ PixelFormatRejectStats * rejects);
static int fbConfigToPixelFormat(__GLXconfig * mode,
PIXELFORMATDESCRIPTOR * pfdret,
int drawableTypeOverride);
@@ -531,6 +543,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
HWND hwnd;
HDC hdc;
HGLRC hglrc;
+ PixelFormatRejectStats rejects;
GLWIN_DEBUG_MSG("glxWinScreenProbe");
@@ -704,8 +717,9 @@ glxWinScreenProbe(ScreenPtr pScreen)
screen->base.pScreen = pScreen;
// Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs
+ memset(&rejects, 0, sizeof(rejects));
if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) {
- glxWinCreateConfigsExt(hdc, screen);
+ glxWinCreateConfigsExt(hdc, screen, &rejects);
/*
Some graphics drivers appear to advertise WGL_ARB_pixel_format,
@@ -718,6 +732,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
}
if (screen->base.numFBConfigs <= 0) {
+ memset(&rejects, 0, sizeof(rejects));
glxWinCreateConfigs(hdc, screen);
screen->has_WGL_ARB_pixel_format = FALSE;
}
@@ -738,9 +753,6 @@ glxWinScreenProbe(ScreenPtr pScreen)
__glXScreenInit(&screen->base, pScreen);
- // Override the GL extensions string set by __glXScreenInit()
- screen->base.GLextensions = strdup(gl_extensions);
-
// Generate the GLX extensions string (overrides that set by __glXScreenInit())
{
unsigned int buffer_size =
@@ -781,7 +793,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
DestroyWindow(hwnd);
// dump out fbConfigs now fbConfigIds and visualIDs have been assigned
- fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs);
+ fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs, &rejects);
/* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
screen->RealizeWindow = pScreen->RealizeWindow;
@@ -893,13 +905,6 @@ glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable * base)
("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)",
base, draw->drawContext, draw->drawContext->ctx);
- /*
- draw->drawContext->base.drawPriv will not be set if the context is not current anymore,
- but if it is, it should point to this drawable....
- */
- assert((draw->drawContext->base.drawPriv == NULL) ||
- (draw->drawContext->base.drawPriv == base));
-
dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd);
if (dc == NULL)
return GL_FALSE;
@@ -1123,7 +1128,6 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
fbConfigToPixelFormatIndex(hdc, gc->base.config,
drawableTypeOverride, winScreen);
if (pixelFormat == 0) {
- ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
return FALSE;
}
@@ -1306,7 +1310,7 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
glxWinScreen *winScreen;
int pixelFormat;
- // XXX: which DC are supposed to use???
+ // XXX: which DC are we supposed to use???
HDC screenDC = GetDC(NULL);
if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) {
@@ -1319,10 +1323,8 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
pixelFormat =
fbConfigToPixelFormatIndex(screenDC, gc->base.config,
- GLX_DRAWABLE_PBUFFER, winScreen);
+ GLX_PBUFFER_BIT, winScreen);
if (pixelFormat == 0) {
- ErrorF("wglChoosePixelFormat error: %s\n",
- glxWinErrorMessage());
return;
}
@@ -1761,7 +1763,7 @@ fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode,
SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
if (mode->swapMethod == GLX_SWAP_COPY_OML)
- SET_ATTR_VALUE(WGL_SWAP_COPY_ARB, TRUE);
+ SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_COPY_ARB);
// XXX: this should probably be the other way around, but that messes up drawableTypeOverride
if (mode->visualRating == GLX_SLOW_VISUAL_EXT)
@@ -1926,6 +1928,8 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen)
/* EXT_visual_rating / GLX 1.2 */
if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
+ continue;
}
else {
// PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
@@ -2060,7 +2064,7 @@ getAttrValue(const int attrs[], int values[], unsigned int num, int attr,
// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
//
static void
-glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
+glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, PixelFormatRejectStats * rejects)
{
GLXWinConfig *c, *result, *prev = NULL;
int i = 0;
@@ -2172,6 +2176,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) {
+ rejects->notOpenGL++;
GLWIN_DEBUG_MSG
("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping",
i + 1);
@@ -2208,11 +2213,13 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
break;
case WGL_TYPE_RGBA_FLOAT_ARB:
+ rejects->rgbaFloat++;
GLWIN_DEBUG_MSG
("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i + 1);
continue;
case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
+ rejects->unsignedRgbaFloat++;
GLWIN_DEBUG_MSG
("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping",
i + 1);
@@ -2225,6 +2232,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
break;
default:
+ rejects->unknownPixelType++;
ErrorF
("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n",
ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
@@ -2265,7 +2273,10 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
case WGL_NO_ACCELERATION_ARB:
+ rejects->unaccelerated++;
c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
+ continue;
break;
case WGL_GENERIC_ACCELERATION_ARB:
@@ -2337,11 +2348,16 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
/* SGIX_pbuffer / GLX 1.3 */
if (screen->has_WGL_ARB_pbuffer) {
- c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
- c->base.maxPbufferHeight =
- ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
- c->base.maxPbufferPixels =
- ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
+ // mesa libGL "can't handle the truth" about max pbuffer size.
+ // We must report 0, which exactly matches what it expects
+ //
+ // ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
+ // ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
+ // ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
+ //
+ c->base.maxPbufferWidth = 0;
+ c->base.maxPbufferHeight = 0;
+ c->base.maxPbufferPixels = 0;
}
else {
c->base.maxPbufferWidth = -1;
diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c
index 4f6e4ffd5..4604f4495 100644
--- a/hw/xwin/glx/winpriv.c
+++ b/hw/xwin/glx/winpriv.c
@@ -14,6 +14,41 @@
void
winCreateWindowsWindow(WindowPtr pWin);
+static void
+winCreateWindowsWindowHierarchy(WindowPtr pWin)
+{
+ winWindowPriv(pWin);
+
+ winDebug("winCreateWindowsWindowHierarchy - pWin:%08x XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ if (!pWin)
+ return;
+
+ /* stop recursion at root window */
+ if (pWin == pWin->drawable.pScreen->root)
+ return;
+
+ /* recursively ensure parent window exists */
+ if (pWin->parent)
+ winCreateWindowsWindowHierarchy(pWin->parent);
+
+ /* ensure this window exists */
+ if (pWinPriv->hWnd == NULL) {
+ winCreateWindowsWindow(pWin);
+
+ /* ... and if it's already been mapped, make sure it's visible */
+ if (pWin->mapped) {
+ /* Display the window without activating it */
+ if (pWin->drawable.class != InputOnly)
+ ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE);
+
+ /* Send first paint message */
+ UpdateWindow(pWinPriv->hWnd);
+ }
+ }
+}
+
/**
* Return size and handles of a window.
* If pWin is NULL, then the information for the root window is requested.
@@ -50,8 +85,8 @@ winGetWindowInfo(WindowPtr pWin)
}
if (pWinPriv->hWnd == NULL) {
- winCreateWindowsWindow(pWin);
- ErrorF("winGetWindowInfo: forcing window to exist...\n");
+ winDebug("winGetWindowInfo: forcing window to exist\n");
+ winCreateWindowsWindowHierarchy(pWin);
}
if (pWinPriv->hWnd != NULL) {
diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man
index c71f6a154..5f2d2eabc 100644
--- a/hw/xwin/man/XWin.man
+++ b/hw/xwin/man/XWin.man
@@ -76,6 +76,9 @@ preceeding \fB\-screen\fP parameter.
.B \-[no]multimonitors or \-[no]multiplemonitors
Create a screen 0 that covers all monitors [the primary monitor] on a system with
multiple monitors.
+Fake XINERAMA data is created describing the individual monitors,
+(This is similar to the 'merged framebuffer' or 'pseudo-xinerama' mode provided by
+some drivers for the xorg X server).
This option is currently enabled by default in \fB\-multiwindow\fP mode.
.TP 8
.B "\-screen \fIscreen_number\fP [\fIW\fP \fIH\fP [\fIX\fP \fIY\fP] | [[\fIW\fPx\fIH\fP[+\fIX\fP+\fIY\fP]][@\fIM\fP]] ] "
@@ -167,14 +170,15 @@ on its own is equivalent to \fB\-resize=randr\fP
.SH OPTIONS FOR MULTIWINDOW MODE
.TP 8
-.B \-hostintitle
+.B \-[no]hostintitle
Add the host name to the window title for X applications which are running
on remote hosts, when that information is available and it's useful to do so.
+The default is enabled.
.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
.TP 8
.B \-[no]clipboard
-Enables [disables] the integration between the Cygwin/X clipboard and
+Enables [disables] the integration between the X11 clipboard and
\fIWindows\fP clipboard. The default is enabled.
.TP 8
.B "\-emulate3buttons [\fItimeout\fP]"
@@ -200,6 +204,10 @@ prevents the \fIWindows\fP mouse cursor from being drawn on top of the X
cursor.
This parameter has no effect unless \fB-swcursor\fP is also specified.
.TP 8
+.B \-[no]primary
+Clipboard integration may [will not] use the PRIMARY selection.
+The default is enabled.
+.TP 8
.B \-swcursor
Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead.
.TP 8
@@ -235,14 +243,12 @@ clipping region is then used to do a single bit block transfer that is
constrained to the updated area by the clipping region. There is some
overhead involved in creating, installing, destroying, and removing
the clipping region, thus there may not be much benefit for a small
-number of boxes (less than 10). It is even possible that this
+number of boxes. It is even possible that this
functionality does not provide a benefit at any number of boxes; we
can only determine the usefulness of this feature through testing.
This option probably has limited effect on current \fIWindows\fP versions
as they already perform GDI batching.
-This parameter works in conjunction with engines 1, 2, and 4 (Shadow
-GDI, Shadow DirectDraw, and Shadow DirectDraw Non-Locking,
-respectively).
+This parameter only has any effect when a Shadow drawing engine is selected.
.TP 8
.B "\-engine \fIengine_type_id\fP"
This option, which is intended for Cygwin/X developers,
@@ -258,11 +264,11 @@ The engine type ids are:
.IP 1 4
Shadow GDI
.IP 2 4
-Shadow DirectDraw
+Shadow DirectDraw (obsolete, disabled)
.IP 4 4
Shadow DirectDraw Non-Locking
.IP 8 4
-Primary DirectDraw (unsupported, obsolete)
+Primary DirectDraw (unsupported, obsolete, disabled)
.IP 16 4
Native GDI (unsupported, experimental and barely functional)
.RE
diff --git a/hw/xwin/man/XWinrc.man b/hw/xwin/man/XWinrc.man
index 71d8dad23..0f641e92f 100644
--- a/hw/xwin/man/XWinrc.man
+++ b/hw/xwin/man/XWinrc.man
@@ -54,6 +54,35 @@ There are four kinds of instructions: miscellaneous, menu, icon and style.
.SH Miscellaneous instruction
.TP 8
+.B DPI \fIresolution\fP
+Sets the resolution for all screens, in dots per inch. To be used when
+the server cannot determine the screen size(s) from the hardware.
+
+.TP 8
+.B XKBLayout \fIlayout\fP
+.TP 8
+.B XKBModel \fImodel\fP
+.TP 8
+.B XKBOptions \fIoption\fP
+.TP 8
+.B XKBRules \fIrule\fP
+.TP 8
+.B XKBVariant \fIvariant\fp
+These options configure the xkeyboard extension to load a particular
+keyboard map as the X server starts. The behavior is similar to the
+\fIsetxkbmap\fP(1) program.
+
+See the \fIxkeyboard-config\fP(__miscmansuffix__) manual page for a list of
+keyboard configurations.
+
+Alternatively, you can use \fIsetxkbmap\fP(1) program after \fIXWin\fP
+is running.
+
+The default is to select a keyboard configuration matching your current
+layout as reported by \fIWindows\fP, if known, or the default X server
+configuration if no matching keyboard configuration was found.
+
+.TP 8
.B DEBUG \fIString\fP
The \fIString\fP is printed to the XWin log file.
diff --git a/hw/xwin/system.XWinrc b/hw/xwin/system.XWinrc
index f0771c610..f572bf301 100644
--- a/hw/xwin/system.XWinrc
+++ b/hw/xwin/system.XWinrc
@@ -89,9 +89,17 @@ menu apps {
}
menu root {
+ "Applications" menu apps
// Comments fit here, too...
+
+ SEPARATOR
+ FAQ EXEC "cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html"
+ "User's Guide" EXEC "cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html"
+ SEPARATOR
+ "View logfile" EXEC "xterm -title $XWINLOGFILE -e less +F $XWINLOGFILE"
+ SEPARATOR
+
"Reload .XWinrc" RELOAD
- "Applications" menu apps
SEParATOR
}
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index a738a5940..24e58490b 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -793,7 +793,7 @@ Bool
winInitClipboard(void);
void
- winFixClipboardChain(void);
+ winClipboardShutdown(void);
#endif
/*
@@ -917,9 +917,6 @@ void
*/
int
- winTranslateKey(WPARAM wParam, LPARAM lParam);
-
-int
winKeybdProc(DeviceIntPtr pDeviceInt, int iState);
void
@@ -928,20 +925,6 @@ void
void
winRestoreModeKeyStates(void);
-Bool
- winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam);
-
-void
- winKeybdReleaseKeys(void);
-
-void
- winSendKeyEvent(DWORD dwKey, Bool fDown);
-
-BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
-
-void
- winFixShiftKeys(int iScanCode);
-
/*
* winkeyhook.c
*/
@@ -981,14 +964,7 @@ int
winMouseProc(DeviceIntPtr pDeviceInt, int iState);
int
- winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown);
-
-void
- winMouseButtonsSendEvent(int iEventType, int iButton);
-
-int
-
-winMouseButtonsHandle(ScreenPtr pScreen,
+ winMouseButtonsHandle(ScreenPtr pScreen,
int iEventType, int iButton, WPARAM wParam);
void
@@ -1232,6 +1208,8 @@ int
LRESULT CALLBACK
winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK
+winChildWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
#endif
/*
diff --git a/hw/xwin/winauth.c b/hw/xwin/winauth.c
index 7efa1c00f..098ea451b 100644
--- a/hw/xwin/winauth.c
+++ b/hw/xwin/winauth.c
@@ -38,6 +38,15 @@
#include "securitysrv.h"
#include "os/osdep.h"
+/* Need to get this from Xlib.h */
+extern void XSetAuthorization(
+ char * /* name */,
+ int /* namelen */,
+ char * /* data */,
+ int /* datalen */
+);
+
+
/*
* Constants
*/
diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
new file mode 100644
index 000000000..b1c95f4ef
--- /dev/null
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -0,0 +1,25 @@
+noinst_LTLIBRARIES = libXWinclipboard.la
+
+libXWinclipboard_la_SOURCES = \
+ winclipboard.h \
+ textconv.c \
+ thread.c \
+ wndproc.c \
+ xevents.c
+
+libXWinclipboard_la_CFLAGS = -DHAVE_XWIN_CONFIG_H \
+ $(DIX_CFLAGS) \
+ $(XWINMODULES_CFLAGS)
+
+libXWinclipboard_la_LDFLAGS = -static -no-undefined
+
+bin_PROGRAMS = xwinclip
+
+xwinclip_SOURCES = xwinclip.c debug.c
+
+xwinclip_CFLAGS = $(XWINMODULES_CFLAGS)
+
+xwinclip_LDADD = libXWinclipboard.la $(XWINMODULES_LIBS) -lgdi32
+
+include $(top_srcdir)/manpages.am
+appman_PRE = xwinclip.man
diff --git a/hw/xwin/winclipboard/debug.c b/hw/xwin/winclipboard/debug.c
new file mode 100644
index 000000000..78ab6d902
--- /dev/null
+++ b/hw/xwin/winclipboard/debug.c
@@ -0,0 +1,52 @@
+//
+// Copyright © Jon TURNEY 2013
+//
+// This file is part of xwinclip.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if 1
+int
+winDebug(const char *format, ...)
+{
+ int count;
+ va_list ap;
+ va_start(ap, format);
+ count = fprintf(stderr, "xwinclip: ");
+ count += vfprintf(stderr, format, ap);
+ va_end(ap);
+ return count;
+}
+#endif
+
+int
+ErrorF(const char *format, ...)
+{
+ int count;
+ va_list ap;
+ va_start(ap, format);
+ count = vfprintf(stderr, format, ap);
+ va_end(ap);
+ return count;
+}
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard/internal.h
index cb7769510..c6bde84af 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -1,5 +1,4 @@
-#ifndef _WINCLIPBOARD_H_
-#define _WINCLIPBOARD_H_
+
/*
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
*
@@ -30,65 +29,29 @@
* Authors: Harold L Hunt II
*/
-/* Standard library headers */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef __CYGWIN__
-#include <sys/select.h>
-#else
-#include <X11/Xwinsock.h>
-#endif
-#include <fcntl.h>
-#include <setjmp.h>
-#include <pthread.h>
+#ifndef WINCLIPBOARD_INTERNAL_H
+#define WINCLIPBOARD_INTERNAL_H
/* X headers */
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xlocale.h>
+#include <X11/Xlib.h>
/* Windows headers */
#include <X11/Xwindows.h>
-/* Clipboard module constants */
-#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
-#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
-#ifdef HAS_DEVWINDOWS
-#define WIN_MSG_QUEUE_FNAME "/dev/windows"
-#endif
-#define WIN_CONNECT_RETRIES 40
-#define WIN_CONNECT_DELAY 4
-#define WIN_JMP_OKAY 0
-#define WIN_JMP_ERROR_IO 2
-#define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER"
#define WIN_XEVENTS_SUCCESS 0
-#define WIN_XEVENTS_CONVERT 2
-#define WIN_XEVENTS_NOTIFY 3
-#define WIN_CLIPBOARD_RETRIES 40
-#define WIN_CLIPBOARD_DELAY 1
+#define WIN_XEVENTS_FAILED 1
+#define WIN_XEVENTS_NOTIFY_DATA 3
+#define WIN_XEVENTS_NOTIFY_TARGETS 4
#define WM_WM_REINIT (WM_USER + 1)
+#define WM_WM_QUIT (WM_USER + 2)
/*
* References to external symbols
*/
-extern char *display;
extern void winDebug(const char *format, ...);
-extern void winErrorFVerb(int verb, const char *format, ...);
-
-/*
- * winclipboardinit.c
- */
-
-Bool
- winInitClipboard(void);
-
-HWND winClipboardCreateMessagingWindow(void);
+extern void ErrorF(const char *format, ...);
/*
* winclipboardtextconv.c
@@ -104,23 +67,51 @@ void
* winclipboardthread.c
*/
-void *winClipboardProc(void *);
+
+typedef struct
+{
+ Atom atomClipboard;
+ Atom atomLocalProperty;
+ Atom atomUTF8String;
+ Atom atomCompoundText;
+ Atom atomTargets;
+} ClipboardAtoms;
/*
* winclipboardwndproc.c
*/
-BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+Bool winClipboardFlushWindowsMessageQueue(HWND hwnd);
LRESULT CALLBACK
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+typedef struct
+{
+ Display *pClipboardDisplay;
+ Window iClipboardWindow;
+ ClipboardAtoms *atoms;
+} ClipboardWindowCreationParams;
+
/*
* winclipboardxevents.c
*/
-int
+typedef struct
+{
+ Bool fUseUnicode;
+ Atom *targetList;
+} ClipboardConversionData;
+int
winClipboardFlushXEvents(HWND hwnd,
- int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+ Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atom);
+
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms);
+
+void
+winClipboardInitMonitoredSelections(void);
+
#endif
diff --git a/hw/xwin/winclipboardtextconv.c b/hw/xwin/winclipboard/textconv.c
index fd405a02e..2870a9b8a 100644
--- a/hw/xwin/winclipboardtextconv.c
+++ b/hw/xwin/winclipboard/textconv.c
@@ -31,14 +31,18 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
-#include "win.h"
-#include <stdio.h>
-#include <stdlib.h>
-void
- winClipboardDOStoUNIX(char *pszSrc, int iLength);
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
+#include <stdlib.h>
+#include "internal.h"
/*
* Convert \r\n to \n
@@ -48,11 +52,14 @@ void
*/
void
-winClipboardDOStoUNIX(char *pszSrc, int iLength)
+winClipboardDOStoUNIX(char *pszData, int iLength)
{
+ char *pszSrc = pszData;
char *pszDest = pszSrc;
char *pszEnd = pszSrc + iLength;
+ winDebug("DOXtoUNIX() - Original data:'%s'\n", pszData);
+
/* Loop until the last character */
while (pszSrc < pszEnd) {
/* Copy the current source character to current destination character */
@@ -68,6 +75,8 @@ winClipboardDOStoUNIX(char *pszSrc, int iLength)
/* Move the terminating null */
*pszDest = '\0';
+
+ winDebug("DOStoUNIX() - Final string:'%s'\n", pszData);
}
/*
@@ -101,8 +110,10 @@ winClipboardUNIXtoDOS(char **ppszData, int iLength)
}
/* Return if no naked \n's */
- if (iNewlineCount == 0)
+ if (iNewlineCount == 0) {
+ winDebug("UNIXtoDOS () - no conversion necessary\n");
return;
+ }
/* Allocate a new string */
pszDestBegin = pszDest = malloc(iLength + iNewlineCount + 1);
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboard/thread.c
index 33595be7f..88af88f78 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -35,41 +35,62 @@
#else
#define HAS_WINSOCK 1
#endif
-#include <sys/types.h>
-#include <signal.h>
-#include "winclipboard.h"
-#ifdef __CYGWIN__
-#include <errno.h>
-#endif
-#include "misc.h"
/*
- * References to external symbols
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
*/
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardStarted;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <pthread.h>
+#include <sys/param.h> // for MAX() macro
+
+#ifdef HAS_WINSOCK
+#include <X11/Xwinsock.h>
+#else
+#include <errno.h>
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+#include "winclipboard.h"
+#include "internal.h"
+
+#define WIN_CONNECT_RETRIES 40
+#define WIN_CONNECT_DELAY 4
+
+#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
+#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
+#ifdef HAS_DEVWINDOWS
+#define WIN_MSG_QUEUE_FNAME "/dev/windows"
+#endif
/*
* Global variables
*/
+static HWND g_hwndClipboard = NULL;
static jmp_buf g_jmpEntry;
-static int clipboardRestarts = 0;
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
static pthread_t g_winClipboardProcThread;
-Bool g_fUseUnicode = FALSE;
+int xfixes_event_base;
+int xfixes_error_base;
/*
* Local function prototypes
*/
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
+
static int
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -77,13 +98,15 @@ static int
winClipboardIOErrorHandler(Display * pDisplay);
/*
- * Main thread function
+ * Create X11 and Win32 messaging windows, and run message processing loop
+ *
+ * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
*/
-void *
-winClipboardProc(void *pvNotUsed)
+Bool
+winClipboardProc(Bool fUseUnicode, char *szDisplay)
{
- Atom atomClipboard;
+ ClipboardAtoms atoms;
int iReturn;
HWND hwnd = NULL;
int iConnectionNumber = 0;
@@ -97,100 +120,41 @@ winClipboardProc(void *pvNotUsed)
int iMaxDescriptor;
Display *pDisplay = NULL;
Window iWindow = None;
- int iRetries;
- Bool fUseUnicode;
- char szDisplay[512];
int iSelectError;
+ Bool fShutdown = FALSE;
winDebug("winClipboardProc - Hello\n");
- ++clipboardRestarts;
-
- /* Do we use Unicode clipboard? */
- fUseUnicode = g_fUnicodeClipboard;
- /* Save the Unicode support flag in a global */
- g_fUseUnicode = fUseUnicode;
+ /* Set error handler */
+ static Bool fErrorHandlerSet = FALSE;
- /* Allow multiple threads to access Xlib */
- if (XInitThreads() == 0) {
- ErrorF("winClipboardProc - XInitThreads failed.\n");
- goto winClipboardProc_Exit;
- }
+ g_winClipboardProcThread = pthread_self();
- /* See if X supports the current locale */
- if (XSupportsLocale() == False) {
- ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
+ if (! fErrorHandlerSet) {
+ XSetErrorHandler(winClipboardErrorHandler);
+ g_winClipboardOldIOErrorHandler =
+ XSetIOErrorHandler(winClipboardIOErrorHandler);
+ fErrorHandlerSet = TRUE;
}
- /* Set error handler */
- XSetErrorHandler(winClipboardErrorHandler);
- g_winClipboardProcThread = pthread_self();
- g_winClipboardOldIOErrorHandler =
- XSetIOErrorHandler(winClipboardIOErrorHandler);
-
/* Set jump point for Error exits */
- iReturn = setjmp(g_jmpEntry);
-
- /* Check if we should continue operations */
- if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
- /* setjmp returned an unknown value, exit */
- ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
- goto winClipboardProc_Exit;
- }
- else if (iReturn == WIN_JMP_ERROR_IO) {
- /* TODO: Cleanup the Win32 window and free any allocated memory */
+ if (setjmp(g_jmpEntry)) {
ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
- pthread_exit(NULL);
- }
-
- /* Use our generated cookie for authentication */
- winSetAuthorization();
-
- /* Initialize retry count */
- iRetries = 0;
-
- /* Setup the display connection string x */
- /*
- * NOTE: Always connect to screen 0 since we require that screen
- * numbers start at 0 and increase without gaps. We only need
- * to connect to one screen on the display to get events
- * for all screens on the display. That is why there is only
- * one clipboard client thread.
- */
- snprintf(szDisplay, 512, "127.0.0.1:%s.0", display);
-
- /* Print the display connection string */
- ErrorF("winClipboardProc - DISPLAY=%s\n", szDisplay);
-
- /* Open the X display */
- do {
- pDisplay = XOpenDisplay(szDisplay);
- if (pDisplay == NULL) {
- ErrorF("winClipboardProc - Could not open display, "
- "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
- ++iRetries;
- sleep(WIN_CONNECT_DELAY);
- continue;
- }
- else
- break;
+ goto winClipboardProc_Done;
}
- while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
/* Make sure that the display opened */
+ pDisplay = XOpenDisplay(szDisplay);
if (pDisplay == NULL) {
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
goto winClipboardProc_Done;
}
- /* Save the display in the screen privates */
- g_pClipboardDisplay = pDisplay;
-
ErrorF("winClipboardProc - XOpenDisplay () returned and "
"successfully opened the display.\n");
/* Get our connection number */
- iConnectionNumber = ConnectionNumber(pDisplay);
+ iConnectionNumber = XConnectionNumber(pDisplay);
#ifdef HAS_DEVWINDOWS
/* Open a file descriptor for the windows message queue */
@@ -201,22 +165,29 @@ winClipboardProc(void *pvNotUsed)
}
/* Find max of our file descriptors */
- iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
+ iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
#else
iMaxDescriptor = iConnectionNumber + 1;
#endif
- /* Create atom */
- atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+ if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
+ ErrorF ("winClipboardProc - XFixes extension not present\n");
+
+ /* Create atoms */
+ atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+ atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False);
+ atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
+ atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
+ atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False);
/* Create a messaging window */
iWindow = XCreateSimpleWindow(pDisplay,
- DefaultRootWindow(pDisplay),
+ XDefaultRootWindow(pDisplay),
1, 1,
500, 500,
0,
- BlackPixel(pDisplay, 0),
- BlackPixel(pDisplay, 0));
+ XBlackPixel(pDisplay, 0),
+ XBlackPixel(pDisplay, 0));
if (iWindow == 0) {
ErrorF("winClipboardProc - Could not create an X window.\n");
goto winClipboardProc_Done;
@@ -229,13 +200,27 @@ winClipboardProc(void *pvNotUsed)
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
"on messaging window\n");
- /* Save the window in the screen privates */
- g_iClipboardWindow = iWindow;
+ XFixesSelectSelectionInput (pDisplay,
+ iWindow,
+ XA_PRIMARY,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+
+ XFixesSelectSelectionInput (pDisplay,
+ iWindow,
+ atoms.atomClipboard,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+
+ /* Initialize monitored selection state */
+ winClipboardInitMonitoredSelections();
/* Create Windows messaging window */
- hwnd = winClipboardCreateMessagingWindow();
+ hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
- /* Save copy of HWND in screen privates */
+ /* Save copy of HWND */
g_hwndClipboard = hwnd;
/* Assert ownership of selections if Win32 clipboard is owned */
@@ -250,32 +235,35 @@ winClipboardProc(void *pvNotUsed)
}
/* CLIPBOARD */
- iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
+ iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+ XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
goto winClipboardProc_Done;
}
}
- /* Pre-flush X events */
- /*
- * NOTE: Apparently you'll freeze if you don't do this,
- * because there may be events in local data structures
- * already.
- */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+ ClipboardConversionData data;
+ data.fUseUnicode = fUseUnicode;
- /* Pre-flush Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd))
- return 0;
+ /* Loop for events */
+ while (1) {
- /* Signal that the clipboard client has started */
- g_fClipboardStarted = TRUE;
+ /* Process X events */
+ winClipboardFlushXEvents(hwnd,
+ iWindow, pDisplay, &data, &atoms);
+
+ /* Process Windows messages */
+ if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+ ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue trapped "
+ "WM_QUIT message, exiting main loop.\n");
+ break;
+ }
+
+ /* We need to ensure that all pending requests are sent */
+ XFlush(pDisplay);
- /* Loop for X events */
- while (1) {
/* Setup the file descriptor set */
/*
* NOTE: You have to do this before every call to select
@@ -291,6 +279,8 @@ winClipboardProc(void *pvNotUsed)
tvTimeout.tv_usec = 100;
#endif
+ winDebug("winClipboardProc - Waiting in select\n");
+
/* Wait for a Windows event or an X event */
iReturn = select(iMaxDescriptor, /* Highest fds number */
&fdsRead, /* Read mask */
@@ -322,10 +312,11 @@ winClipboardProc(void *pvNotUsed)
break;
}
- /* Branch on which descriptor became active */
+ winDebug("winClipboardProc - select returned %d\n", iReturn);
+
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
- /* Process X events */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+ winDebug
+ ("winClipboardProc - X connection ready, pumping X event queue\n");
}
#ifdef HAS_DEVWINDOWS
@@ -335,27 +326,25 @@ winClipboardProc(void *pvNotUsed)
if (1)
#endif
{
- /* Process Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
- ErrorF("winClipboardProc - "
- "winClipboardFlushWindowsMessageQueue trapped "
- "WM_QUIT message, exiting main loop.\n");
- break;
- }
+ winDebug
+ ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n");
+ }
+
+#ifdef HAS_DEVWINDOWS
+ if (!(FD_ISSET(iConnectionNumber, &fdsRead)) &&
+ !(FD_ISSET(fdMessageQueue, &fdsRead))) {
+ winDebug("winClipboardProc - Spurious wake, select() returned %d\n", iReturn);
}
+#endif
}
- winClipboardProc_Exit:
- /* disable the clipboard, which means the thread will die */
- g_fClipboard = FALSE;
+ /* broke out of while loop on a shutdown message */
+ fShutdown = TRUE;
winClipboardProc_Done:
/* Close our Windows window */
if (g_hwndClipboard) {
- /* Destroy the Window window (hwnd) */
- winDebug("winClipboardProc - Destroy Windows window\n");
- PostMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
- winClipboardFlushWindowsMessageQueue(g_hwndClipboard);
+ DestroyWindow(g_hwndClipboard);
}
/* Close our X window */
@@ -375,15 +364,18 @@ winClipboardProc(void *pvNotUsed)
#if 0
/*
- * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The
- * XSync and XSelectInput calls did not help.
+ * FIXME: XCloseDisplay hangs if we call it
+ *
+ * XCloseDisplay() calls XSync(), so any outstanding errors are reported.
+ * If we are built into the server, this can deadlock if the server is
+ * in the process of exiting and waiting for this thread to exit.
*/
/* Discard any remaining events */
XSync(pDisplay, TRUE);
/* Select event types to watch */
- XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
+ XSelectInput(pDisplay, XDefaultRootWindow(pDisplay), None);
/* Close our X display */
if (pDisplay) {
@@ -392,42 +384,64 @@ winClipboardProc(void *pvNotUsed)
#endif
/* global clipboard variable reset */
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
- g_iClipboardWindow = None;
- g_pClipboardDisplay = NULL;
g_hwndClipboard = NULL;
- /* checking if we need to restart */
- if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
- /* terminates clipboard thread but the main server still lives */
- ErrorF
- ("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n",
- clipboardRestarts);
- g_fClipboard = FALSE;
- return NULL;
- }
-
- if (g_fClipboard) {
- sleep(WIN_CLIPBOARD_DELAY);
- ErrorF("winClipboardProc - trying to restart clipboard thread \n");
- /* Create the clipboard client thread */
- if (!winInitClipboard()) {
- ErrorF("winClipboardProc - winClipboardInit failed.\n");
- return NULL;
- }
+ return fShutdown;
+}
- winDebug("winClipboardProc - winInitClipboard returned.\n");
- /* Flag that clipboard client has been launched */
- g_fClipboardLaunched = TRUE;
- }
- else {
- ErrorF("winClipboardProc - Clipboard disabled - Exit from server \n");
- /* clipboard thread has exited, stop server as well */
- raise(SIGTERM);
- }
+/*
+ * Create the Windows window that we use to receive Windows messages
+ */
- return NULL;
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
+{
+ WNDCLASSEX wc;
+ HWND hwnd;
+
+ /* Setup our window class */
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = winClipboardWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
+ wc.hIconSm = 0;
+ RegisterClassEx(&wc);
+
+ /* Information to be passed to WM_CREATE */
+ ClipboardWindowCreationParams cwcp;
+ cwcp.pClipboardDisplay = pDisplay;
+ cwcp.iClipboardWindow = iWindow;
+ cwcp.atoms = atoms;
+
+ /* Create the window */
+ hwnd = CreateWindowExA(0, /* Extended styles */
+ WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */
+ WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
+ WS_OVERLAPPED, /* Not visible anyway */
+ CW_USEDEFAULT, /* Horizontal position */
+ CW_USEDEFAULT, /* Vertical position */
+ CW_USEDEFAULT, /* Right edge */
+ CW_USEDEFAULT, /* Bottom edge */
+ (HWND) NULL, /* No parent or owner window */
+ (HMENU) NULL, /* No menu */
+ GetModuleHandle(NULL), /* Instance handle */
+ &cwcp); /* Creation data */
+ assert(hwnd != NULL);
+
+ /* I'm not sure, but we may need to call this to start message processing */
+ ShowWindow(hwnd, SW_HIDE);
+
+ /* Similarly, we may need a call to this even though we don't paint */
+ UpdateWindow(hwnd);
+
+ return hwnd;
}
/*
@@ -457,7 +471,7 @@ winClipboardIOErrorHandler(Display * pDisplay)
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
/* Restart at the main entry point */
- longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
+ longjmp(g_jmpEntry, 2);
}
if (g_winClipboardOldIOErrorHandler)
@@ -465,3 +479,19 @@ winClipboardIOErrorHandler(Display * pDisplay)
return 0;
}
+
+void
+winClipboardWindowDestroy(void)
+{
+ if (g_hwndClipboard) {
+ SendMessage(g_hwndClipboard, WM_WM_QUIT, 0, 0);
+ }
+}
+
+void
+winFixClipboardChain(void)
+{
+ if (g_hwndClipboard) {
+ PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
+ }
+}
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
new file mode 100644
index 000000000..e7ccc3637
--- /dev/null
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -0,0 +1,38 @@
+//
+// Copyright © Jon TURNEY 2013
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// File: winclipboard.h
+// Purpose: public interface to winclipboard library
+//
+
+#ifndef WINCLIPBOARD_H
+#define WINCLIPBOARD_H
+
+Bool winClipboardProc(Bool fUseUnicode, char *szDisplay);
+
+void winFixClipboardChain(void);
+
+void winClipboardWindowDestroy(void);
+
+extern int fPrimarySelection;
+
+#endif
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboard/wndproc.c
index 90dc9e0bb..f0867f91d 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -33,10 +33,24 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
#include <sys/types.h>
#include <sys/time.h>
+#include <limits.h>
+
+#include <X11/Xatom.h>
+
+#include "internal.h"
#include "winclipboard.h"
-#include "misc.h"
/*
* Constants
@@ -44,21 +58,14 @@
#define WIN_POLL_TIMEOUT 1
-/*
- * References to external symbols
- */
-
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
/*
* Process X events up to specified timeout
*/
static int
-winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
- Bool fUseUnicode, int iTimeoutSec)
+winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
+ ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec)
{
int iConnNumber;
struct timeval tv;
@@ -69,15 +76,25 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
iTimeoutSec);
/* Get our connection number */
- iConnNumber = ConnectionNumber(pDisplay);
+ iConnNumber = XConnectionNumber(pDisplay);
/* Loop for X events */
while (1) {
fd_set fdsRead;
long remainingTime;
- /* We need to ensure that all pending events are processed */
- XSync(pDisplay, FALSE);
+ /* Process X events */
+ iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, data, atoms);
+
+ winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn);
+
+ if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) {
+ /* Bail out */
+ return iReturn;
+ }
+
+ /* We need to ensure that all pending requests are sent */
+ XFlush(pDisplay);
/* Setup the file descriptor set */
FD_ZERO(&fdsRead);
@@ -106,24 +123,8 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
break;
}
- /* Branch on which descriptor became active */
- if (FD_ISSET(iConnNumber, &fdsRead)) {
- /* Process X events */
- /* Exit when we see that server is shutting down */
- iReturn = winClipboardFlushXEvents(hwnd,
- iWindow, pDisplay, fUseUnicode);
-
- winDebug
- ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
- iReturn);
-
- if (WIN_XEVENTS_NOTIFY == iReturn) {
- /* Bail out if notify processed */
- return iReturn;
- }
- }
- else {
- winDebug("winProcessXEventsTimeout - Spurious wake\n");
+ if (!FD_ISSET(iConnNumber, &fdsRead)) {
+ winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn);
}
}
@@ -139,6 +140,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndNextViewer;
static Bool s_fCBCInitialized;
+ static Display *pDisplay;
+ static Window iWindow;
+ static ClipboardAtoms *atoms;
+ static Bool fRunning;
/* Branch on message type */
switch (message) {
@@ -150,7 +155,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
ChangeClipboardChain(hwnd, s_hwndNextViewer);
s_hwndNextViewer = NULL;
+ }
+ return 0;
+ case WM_WM_QUIT:
+ {
+ winDebug("winClipboardWindowProc - WM_WM_QUIT\n");
+ fRunning = FALSE;
PostQuitMessage(0);
}
return 0;
@@ -162,6 +173,12 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winClipboardWindowProc - WM_CREATE\n");
+ ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
+ pDisplay = cwcp->pClipboardDisplay;
+ iWindow = cwcp->iClipboardWindow;
+ atoms = cwcp->atoms;
+ fRunning = TRUE;
+
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
if (first == hwnd)
return 0; /* Make sure it's not us! */
@@ -185,8 +202,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
s_hwndNextViewer = (HWND) lParam;
if (s_hwndNextViewer == hwnd) {
s_hwndNextViewer = NULL;
- winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
- "attempted to set next window to ourselves.");
+ ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
+ "attempted to set next window to ourselves.");
}
}
else if (s_hwndNextViewer)
@@ -241,20 +258,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_DRAWCLIPBOARD:
{
- static Atom atomClipboard;
- static int generation;
static Bool s_fProcessingDrawClipboard = FALSE;
- Display *pDisplay = g_pClipboardDisplay;
- Window iWindow = g_iClipboardWindow;
int iReturn;
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
- if (generation != serverGeneration) {
- generation = serverGeneration;
- atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
- }
-
/*
* We've occasionally seen a loop in the clipboard chain.
* Try and fix it on the first hint of recursion.
@@ -267,8 +275,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
s_fCBCInitialized = FALSE;
ChangeClipboardChain(hwnd, s_hwndNextViewer);
winFixClipboardChain();
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Nested calls detected. Re-initing.\n");
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Nested calls detected. Re-initing.\n");
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
return 0;
@@ -302,6 +310,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
+ /* Bail when shutting down */
+ if (!fRunning)
+ return 0;
+
/*
* Do not take ownership of the X11 selections when something
* other than CF_TEXT or CF_UNICODETEXT has been copied
@@ -314,6 +326,36 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
"Clipboard does not contain CF_TEXT nor "
"CF_UNICODETEXT.\n");
+ winDebug("winClipboardWindowProc: %d formats\n",
+ CountClipboardFormats());
+
+ if (OpenClipboard(hwnd)) {
+ unsigned int format = 0;
+
+ do {
+ format = EnumClipboardFormats(format);
+ if (GetLastError() != ERROR_SUCCESS) {
+ winDebug
+ ("winClipboardWindowProc: EnumClipboardFormats failed %x\n",
+ GetLastError());
+ }
+ if (format > 0xc000) {
+ char buff[256];
+
+ GetClipboardFormatName(format, buff, 256);
+ winDebug("winClipboardWindowProc: %d %s\n", format,
+ buff);
+ }
+ else if (format > 0)
+ winDebug("winClipboardWindowProc: %d\n", format);
+ } while (format != 0);
+ CloseClipboard();
+ }
+ else {
+ winDebug
+ ("WindowProc: could not open clipboard to enumerate formats\n");
+ }
+
/*
* We need to make sure that the X Server has processed
* previous XSetSelectionOwner messages.
@@ -324,27 +366,27 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Release PRIMARY selection if owned */
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
- if (iReturn == g_iClipboardWindow) {
+ if (iReturn == iWindow) {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "PRIMARY selection is owned by us.\n");
+ "PRIMARY selection is owned by us, releasing\n");
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "XGetSelection failed for PRIMARY: %d\n",
- iReturn);
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelectionOwner failed for PRIMARY: %d\n",
+ iReturn);
/* Release CLIPBOARD selection if owned */
- iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
- if (iReturn == g_iClipboardWindow) {
+ iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
+ if (iReturn == iWindow) {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "CLIPBOARD selection is owned by us.\n");
- XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
+ "CLIPBOARD selection is owned by us, releasing\n");
+ XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "XGetSelection failed for CLIPBOARD: %d\n",
- iReturn);
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelectionOwner failed for CLIPBOARD: %d\n",
+ iReturn);
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
@@ -358,8 +400,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
XA_PRIMARY, iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Could not reassert ownership of PRIMARY\n");
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of PRIMARY\n");
}
else {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -368,12 +410,12 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Reassert ownership of the CLIPBOARD */
iReturn = XSetSelectionOwner(pDisplay,
- atomClipboard, iWindow, CurrentTime);
+ atoms->atomClipboard, iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Could not reassert ownership of CLIPBOARD\n");
+ XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of CLIPBOARD\n");
}
else {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -405,96 +447,149 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
return 0;
- case WM_RENDERFORMAT:
case WM_RENDERALLFORMATS:
+ winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");
+
+ /*
+ WM_RENDERALLFORMATS is sent as we are shutting down, to render the
+ clipboard so it's contents remains available to other applications.
+
+ Unfortunately, this can't work without major changes. The server is
+ already waiting for us to stop, so we can't ask for the rendering of
+ clipboard text now.
+ */
+
+ return 0;
+
+ case WM_RENDERFORMAT:
{
int iReturn;
- Display *pDisplay = g_pClipboardDisplay;
- Window iWindow = g_iClipboardWindow;
Bool fConvertToUnicode;
+ Bool pasted = FALSE;
- winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
+ winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
+ wParam);
/* Flag whether to convert to Unicode or not */
- if (message == WM_RENDERALLFORMATS)
- fConvertToUnicode = FALSE;
- else
- fConvertToUnicode = (CF_UNICODETEXT == wParam);
+ fConvertToUnicode = (CF_UNICODETEXT == wParam);
- /* Request the selection contents */
- iReturn = XConvertSelection(pDisplay,
- g_atomLastOwnedSelection,
- XInternAtom(pDisplay,
- "COMPOUND_TEXT", False),
- XInternAtom(pDisplay,
- "CYGX_CUT_BUFFER", False),
- iWindow, CurrentTime);
- if (iReturn == BadAtom || iReturn == BadWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
- "XConvertSelection () failed\n");
- break;
+ Atom selection = winClipboardGetLastOwnedSelectionAtom(atoms);
+
+ if (selection == None) {
+ ErrorF("winClipboardWindowProc - no monitored selection is owned\n");
+ goto fake_paste;
}
- /* Special handling for WM_RENDERALLFORMATS */
- if (message == WM_RENDERALLFORMATS) {
- /* We must open and empty the clipboard */
+ winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");
- /* Close clipboard if we have it open already */
- if (GetOpenClipboardWindow() == hwnd) {
- CloseClipboard();
- }
+ /* Request the selection's supported conversion targets */
+ XConvertSelection(pDisplay,
+ selection,
+ atoms->atomTargets,
+ atoms->atomLocalProperty,
+ iWindow, CurrentTime);
- if (!OpenClipboard(hwnd)) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "OpenClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ /* Process X events */
+ ClipboardConversionData data;
+ data.fUseUnicode = fConvertToUnicode;
+ iReturn = winProcessXEventsTimeout(hwnd,
+ iWindow,
+ pDisplay,
+ &data,
+ atoms,
+ WIN_POLL_TIMEOUT);
- if (!EmptyClipboard()) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "EmptyClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
+ ErrorF
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
+ goto fake_paste;
}
- /* Process the SelectionNotify event */
+ /* Choose the most preferred target */
+ struct target_priority
+ {
+ Atom target;
+ unsigned int priority;
+ };
+
+ struct target_priority target_priority_table[] =
+ {
+ { atoms->atomCompoundText, 0 },
+#ifdef X_HAVE_UTF8_STRING
+ { atoms->atomUTF8String, 1 },
+#endif
+ { XA_STRING, 2 },
+ };
+
+ int best_priority = INT_MAX;
+ int best_target = 0;
+
+ int i,j;
+ for (i = 0 ; data.targetList[i] != 0; i++)
+ {
+ for (j = 0; j < sizeof(target_priority_table)/sizeof(struct target_priority); j ++)
+ {
+ if ((data.targetList[i] == target_priority_table[j].target) &&
+ (target_priority_table[j].priority < best_priority))
+ {
+ best_target = target_priority_table[j].target;
+ best_priority = target_priority_table[j].priority;
+ }
+ }
+ }
+
+ free(data.targetList);
+ data.targetList = 0;
+
+ winDebug("winClipboardWindowProc - best target is %d\n", best_target);
+
+ /* No useful targets found */
+ if (best_target == 0)
+ goto fake_paste;
+
+ winDebug("winClipboardWindowProc - requesting selection from owner\n");
+
+ /* Request the selection contents */
+ XConvertSelection(pDisplay,
+ selection,
+ best_target,
+ atoms->atomLocalProperty,
+ iWindow, CurrentTime);
+
+ /* Process X events */
iReturn = winProcessXEventsTimeout(hwnd,
iWindow,
pDisplay,
- fConvertToUnicode, WIN_POLL_TIMEOUT);
+ &data,
+ atoms,
+ WIN_POLL_TIMEOUT);
/*
- * The last call to winProcessXEventsTimeout
- * from above had better have seen a notify event, or else we
- * are dealing with a buggy or old X11 app. In these cases we
- * have to paste some fake data to the Win32 clipboard to
- * satisfy the requirement that we write something to it.
+ * winProcessXEventsTimeout had better have seen a notify event,
+ * or else we are dealing with a buggy or old X11 app.
*/
- if (WIN_XEVENTS_NOTIFY != iReturn) {
- /* Paste no data, to satisfy required call to SetClipboardData */
- SetClipboardData(CF_UNICODETEXT, NULL);
- SetClipboardData(CF_TEXT, NULL);
-
+ if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
ErrorF
- ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n");
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
}
-
- /* Special handling for WM_RENDERALLFORMATS */
- if (message == WM_RENDERALLFORMATS) {
- /* We must close the clipboard */
-
- if (!CloseClipboard()) {
- winErrorFVerb(1,
- "winClipboardWindowProc - WM_RENDERALLFORMATS - "
- "CloseClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ else {
+ pasted = TRUE;
}
- winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
+ /*
+ * If we couldn't get the data from the X clipboard, we
+ * have to paste some fake data to the Win32 clipboard to
+ * satisfy the requirement that we write something to it.
+ */
+ fake_paste:
+ if (!pasted)
+ {
+ /* Paste no data, to satisfy required call to SetClipboardData */
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+ }
+
+ winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n");
return 0;
}
}
@@ -507,7 +602,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
* Process any pending Windows messages
*/
-BOOL
+Bool
winClipboardFlushWindowsMessageQueue(HWND hwnd)
{
MSG msg;
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboard/xevents.c
index 7d3c30e85..59bf5bd8c 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -33,8 +33,156 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
+#include <limits.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+
#include "winclipboard.h"
-#include "misc.h"
+#include "internal.h"
+
+/*
+ * Constants
+ */
+
+#define CLIP_NUM_SELECTIONS 2
+#define CLIP_OWN_NONE -1
+#define CLIP_OWN_PRIMARY 0
+#define CLIP_OWN_CLIPBOARD 1
+
+/*
+ * Global variables
+ */
+
+extern int xfixes_event_base;
+int fPrimarySelection = 1;
+
+/*
+ * Local variables
+ */
+
+static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
+static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
+ { "PRIMARY", "CLIPBOARD" };
+
+static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
+
+static void
+MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
+{
+ /* Look for owned -> not owned transition */
+ if (None == e->owner && None != s_iOwners[i]) {
+ unsigned int other_index;
+
+ winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
+ szSelectionNames[i]);
+
+ /* If this selection is not owned, the other monitored selection must be the most
+ recently owned, if it is owned at all */
+ if (i == CLIP_OWN_PRIMARY)
+ other_index = CLIP_OWN_CLIPBOARD;
+ if (i == CLIP_OWN_CLIPBOARD)
+ other_index = CLIP_OWN_PRIMARY;
+ if (None != s_iOwners[other_index])
+ lastOwnedSelectionIndex = other_index;
+ else
+ lastOwnedSelectionIndex = CLIP_OWN_NONE;
+ }
+
+ /* Save last owned selection */
+ if (None != e->owner) {
+ lastOwnedSelectionIndex = i;
+ }
+
+ /* Save new selection owner or None */
+ s_iOwners[i] = e->owner;
+ winDebug("MonitorSelection - %s - Now owned by XID %x\n",
+ szSelectionNames[i], e->owner);
+}
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms)
+{
+ if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
+ return None;
+
+ winDebug("GetLastOwnedSelectionAtom: selection %s owned by XID %x\n", szSelectionNames[lastOwnedSelectionIndex], s_iOwners[lastOwnedSelectionIndex]);
+
+ if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
+ return XA_PRIMARY;
+
+ if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
+ return atoms->atomClipboard;
+
+ return None;
+}
+
+
+void
+winClipboardInitMonitoredSelections(void)
+{
+ /* Initialize static variables */
+ for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
+ s_iOwners[i] = None;
+
+ lastOwnedSelectionIndex = CLIP_OWN_NONE;
+}
+
+static int
+winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
+{
+ Atom type;
+ int format;
+ unsigned long nitems;
+ unsigned long after;
+ Atom *prop;
+
+ /* Retrieve the selection data and delete the property */
+ int iReturn = XGetWindowProperty(pDisplay,
+ iWindow,
+ atoms->atomLocalProperty,
+ 0,
+ INT_MAX,
+ True,
+ AnyPropertyType,
+ &type,
+ &format,
+ &nitems,
+ &after,
+ (unsigned char **)&prop);
+ if (iReturn != Success) {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "XGetWindowProperty () failed, aborting: %d\n", iReturn);
+ } else {
+ int i;
+ data->targetList = malloc((nitems+1)*sizeof(Atom));
+
+ for (i = 0; i < nitems; i++)
+ {
+ Atom atom = prop[i];
+ data->targetList[i] = atom;
+ char *pszAtomName = XGetAtomName(pDisplay, atom);
+ winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %d = %s\n", i, atom, pszAtomName);
+ XFree(pszAtomName);
+ }
+
+ data->targetList[nitems] = 0;
+
+ XFree(prop);
+ }
+
+ return WIN_XEVENTS_NOTIFY_TARGETS;
+}
/*
* Process any pending X events
@@ -42,21 +190,13 @@
int
winClipboardFlushXEvents(HWND hwnd,
- int iWindow, Display * pDisplay, Bool fUseUnicode)
+ Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
- static Atom atomLocalProperty;
- static Atom atomCompoundText;
- static Atom atomUTF8String;
- static Atom atomTargets;
- static int generation;
-
- if (generation != serverGeneration) {
- generation = serverGeneration;
- atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
- atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
- atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
- atomTargets = XInternAtom(pDisplay, "TARGETS", False);
- }
+ Atom atomClipboard = atoms->atomClipboard;
+ Atom atomLocalProperty = atoms->atomLocalProperty;
+ Atom atomUTF8String = atoms->atomUTF8String;
+ Atom atomCompoundText = atoms->atomCompoundText;
+ Atom atomTargets = atoms->atomTargets;
/* Process all pending events */
while (XPending(pDisplay)) {
@@ -77,7 +217,6 @@ winClipboardFlushXEvents(HWND hwnd,
wchar_t *pwszUnicodeStr = NULL;
int iUnicodeLen = 0;
int iReturnDataLen = 0;
- int i;
Bool fAbort = FALSE;
Bool fCloseClipboard = FALSE;
Bool fSetClipboardData = TRUE;
@@ -95,12 +234,14 @@ winClipboardFlushXEvents(HWND hwnd,
{
char *pszAtomName = NULL;
- winDebug("SelectionRequest - target %d\n",
- event.xselectionrequest.target);
+ pszAtomName = XGetAtomName(pDisplay,
+ event.xselectionrequest.selection);
+ winDebug("winClipboardFlushXEvents - SelectionRequest - Selection: %s\n", pszAtomName);
+ XFree(pszAtomName);
pszAtomName = XGetAtomName(pDisplay,
event.xselectionrequest.target);
- winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
+ winDebug("winClipboardFlushXEvents - SelectionRequest - Target %d = %s\n", event.xselectionrequest.target, pszAtomName);
XFree(pszAtomName);
pszAtomName = NULL;
}
@@ -122,6 +263,7 @@ winClipboardFlushXEvents(HWND hwnd,
atomUTF8String,
XA_STRING
};
+ winDebug("winClipboardFlushXEvents - SelectionRequest - populating targets\n");
/* Try to change the property */
iReturn = XChangeProperty(pDisplay,
@@ -184,7 +326,7 @@ winClipboardFlushXEvents(HWND hwnd,
fCloseClipboard = TRUE;
/* Check that clipboard format is available */
- if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+ if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
static int count; /* Hack to stop acroread spamming the log */
static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
@@ -201,7 +343,7 @@ winClipboardFlushXEvents(HWND hwnd,
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
- else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
+ else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
"available from Win32 clipboard. Aborting.\n");
@@ -223,7 +365,7 @@ winClipboardFlushXEvents(HWND hwnd,
xiccesStyle = XStringStyle;
/* Get a pointer to the clipboard text, in desired format */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
/* Retrieve clipboard data */
hGlobal = GetClipboardData(CF_UNICODETEXT);
}
@@ -242,7 +384,7 @@ winClipboardFlushXEvents(HWND hwnd,
pszGlobalData = (char *) GlobalLock(hGlobal);
/* Convert the Unicode string to UTF8 (MBCS) */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
iConvertDataLen = WideCharToMultiByte(CP_UTF8,
0,
(LPCWSTR) pszGlobalData,
@@ -273,7 +415,7 @@ winClipboardFlushXEvents(HWND hwnd,
xtpText.nitems = 0;
/* Create the text property from the text list */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextListToTextProperty(pDisplay,
pszTextList,
@@ -367,6 +509,7 @@ winClipboardFlushXEvents(HWND hwnd,
* client when we abort.
*/
if (fAbort) {
+ winDebug("winClipboardFlushXEvents - SelectionRequest - aborting\n");
/* Setup selection notify event */
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
@@ -418,75 +561,31 @@ winClipboardFlushXEvents(HWND hwnd,
}
/*
- * Request conversion of UTF8 and CompoundText targets.
- */
- if (event.xselection.property == None) {
- if (event.xselection.target == XA_STRING) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "XA_STRING\n");
+ SelectionNotify with property of None indicates either:
- return WIN_XEVENTS_CONVERT;
- }
- else if (event.xselection.target == atomUTF8String) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "Requesting conversion of UTF8 target.\n");
-
- XConvertSelection(pDisplay,
- event.xselection.selection,
- XA_STRING,
- atomLocalProperty, iWindow, CurrentTime);
-
- /* Process the ConvertSelection event */
- XFlush(pDisplay);
- return WIN_XEVENTS_CONVERT;
- }
-#ifdef X_HAVE_UTF8_STRING
- else if (event.xselection.target == atomCompoundText) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "Requesting conversion of CompoundText target.\n");
-
- XConvertSelection(pDisplay,
- event.xselection.selection,
- atomUTF8String,
- atomLocalProperty, iWindow, CurrentTime);
-
- /* Process the ConvertSelection event */
- XFlush(pDisplay);
- return WIN_XEVENTS_CONVERT;
- }
-#endif
- else {
+ (i) Generated by the X server if no owner for the specified selection exists
+ (perhaps it's disappeared on us mid-transaction), or
+ (ii) Sent by the selection owner when the requested selection conversion could
+ not be performed or server errors prevented the conversion data being returned
+ */
+ if (event.xselection.property == None) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
- "Unknown format. Cannot request conversion, "
- "aborting.\n");
- break;
+ "Conversion to format %d refused.\n",
+ event.xselection.target);
+ return WIN_XEVENTS_FAILED;
}
- }
- /* Retrieve the size of the stored data */
- iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */
- False,
- AnyPropertyType,
- &xtpText.encoding,
- &xtpText.format,
- &xtpText.nitems,
- &ulReturnBytesLeft, &xtpText.value);
- if (iReturn != Success) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
- "XGetWindowProperty () failed, aborting: %d\n", iReturn);
- break;
+ if (event.xselection.target == atomTargets) {
+ return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
}
- winDebug("SelectionNotify - returned data %d left %d\n",
- xtpText.nitems, ulReturnBytesLeft);
-
- /* Request the selection data */
+ /* Retrieve the selection data and delete the property */
iReturn = XGetWindowProperty(pDisplay,
iWindow,
atomLocalProperty,
0,
- ulReturnBytesLeft,
- False,
+ INT_MAX,
+ True,
AnyPropertyType,
&xtpText.encoding,
&xtpText.format,
@@ -495,7 +594,7 @@ winClipboardFlushXEvents(HWND hwnd,
if (iReturn != Success) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
- break;
+ goto winClipboardFlushXEvents_SelectionNotify_Done;
}
{
@@ -504,12 +603,13 @@ winClipboardFlushXEvents(HWND hwnd,
winDebug("SelectionNotify - returned data %d left %d\n",
xtpText.nitems, ulReturnBytesLeft);
pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
- winDebug("Notify atom name %s\n", pszAtomName);
+ winDebug("SelectionNotify - encoding atom name %s\n",
+ pszAtomName);
XFree(pszAtomName);
pszAtomName = NULL;
}
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
/* Convert the text property to a text list */
iReturn = Xutf8TextPropertyToTextList(pDisplay,
@@ -525,6 +625,8 @@ winClipboardFlushXEvents(HWND hwnd,
if (iReturn == Success || iReturn > 0) {
/* Conversion succeeded or some unconvertible characters */
if (ppszTextList != NULL) {
+ int i;
+
iReturnDataLen = 0;
for (i = 0; i < iCount; i++) {
iReturnDataLen += strlen(ppszTextList[i]);
@@ -574,7 +676,7 @@ winClipboardFlushXEvents(HWND hwnd,
/* Convert the X clipboard string to DOS format */
winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
/* Find out how much space needed to convert MBCS to Unicode */
iUnicodeLen = MultiByteToWideChar(CP_UTF8,
0,
@@ -633,7 +735,7 @@ winClipboardFlushXEvents(HWND hwnd,
}
/* Copy the returned string into the global memory */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
memcpy(pszGlobalData,
pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
free(pwszUnicodeStr);
@@ -650,7 +752,7 @@ winClipboardFlushXEvents(HWND hwnd,
pszGlobalData = NULL;
/* Push the selection data to the Windows clipboard */
- if (fUseUnicode)
+ if (data->fUseUnicode)
SetClipboardData(CF_UNICODETEXT, hGlobal);
else
SetClipboardData(CF_TEXT, hGlobal);
@@ -680,21 +782,100 @@ winClipboardFlushXEvents(HWND hwnd,
SetClipboardData(CF_UNICODETEXT, NULL);
SetClipboardData(CF_TEXT, NULL);
}
- return WIN_XEVENTS_NOTIFY;
+ return WIN_XEVENTS_NOTIFY_DATA;
case SelectionClear:
- winDebug("SelectionClear - doing nothing\n");
+ winDebug("winClipboardFlushXEvents - SelectionClear - doing nothing\n");
break;
case PropertyNotify:
+ {
+ char *pszAtomName;
+
+ pszAtomName = XGetAtomName(pDisplay, event.xproperty.atom);
+ winDebug("winClipboardFlushXEvents - PropertyNotify - ATOM: %s %s\n",
+ pszAtomName,
+ event.xproperty.state == PropertyNewValue ? "PropertyNewValue" : "PropertyDelete");
+ XFree(pszAtomName);
+ }
break;
case MappingNotify:
break;
default:
- ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
- event.type);
+ if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
+ XFixesSelectionNotifyEvent *e =
+ (XFixesSelectionNotifyEvent *) & event;
+
+ winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
+
+ /* Save selection owners for monitored selections, ignore other selections */
+ if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
+ MonitorSelection(e, CLIP_OWN_PRIMARY);
+ }
+ else if (e->selection == atomClipboard) {
+ MonitorSelection(e, CLIP_OWN_CLIPBOARD);
+ }
+ else
+ break;
+
+ /* Selection is being disowned */
+ if (e->owner == None) {
+ winDebug
+ ("winClipboardFlushXEvents - No window, returning.\n");
+ break;
+ }
+
+ /*
+ XXX: there are all kinds of wacky edge cases we might need here:
+ - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
+ - root window is taking ownership?
+ */
+
+ /* If we are the owner of the most recently owned selection, don't go all recursive :) */
+ if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
+ (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
+ winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
+ break;
+ }
+
+ /* Close clipboard if we have it open already (possible? correct??) */
+ if (GetOpenClipboardWindow() == hwnd) {
+ CloseClipboard();
+ }
+
+ /* Access the Windows clipboard */
+ if (!OpenClipboard(hwnd)) {
+ ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+
+ /* Take ownership of the Windows clipboard */
+ if (!EmptyClipboard()) {
+ ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+
+ /* Advertise regular text and unicode */
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+
+ /* Release the clipboard */
+ if (!CloseClipboard()) {
+ ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+ }
+ /* XFixesSelectionWindowDestroyNotifyMask */
+ /* XFixesSelectionClientCloseNotifyMask */
+ else {
+ ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
+ event.type);
+ }
break;
}
}
diff --git a/hw/xwin/winclipboard/xwinclip.c b/hw/xwin/winclipboard/xwinclip.c
new file mode 100644
index 000000000..8dfd24bd9
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.c
@@ -0,0 +1,134 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors: Harold L Hunt II
+ * Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* X headers */
+#include <X11/Xlib.h>
+#ifdef X_LOCALE
+#include <X11/Xlocale.h>
+#else /* X_LOCALE */
+#include <locale.h>
+#endif /* X_LOCALE */
+
+#include "winclipboard.h"
+
+/*
+ * Main function
+ */
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ char *pszDisplay = NULL;
+ int fUnicodeClipboard = 1;
+
+ /* Parse command-line parameters */
+ for (i = 1; i < argc; ++i)
+ {
+ /* Look for -display "display_name" or --display "display_name" */
+ if (i < argc - 1
+ && (!strcmp (argv[i], "-display")
+ || !strcmp (argv[i], "--display")))
+ {
+ /* Grab a pointer to the display parameter */
+ pszDisplay = argv[i + 1];
+
+ /* Skip the display argument */
+ i++;
+ continue;
+ }
+
+ /* Look for -nounicodeclipboard */
+ if (!strcmp (argv[i], "-nounicodeclipboard"))
+ {
+ fUnicodeClipboard = 0;
+ continue;
+ }
+
+ /* Look for -noprimary */
+ if (!strcmp (argv[i], "-noprimary"))
+ {
+ fPrimarySelection = 0;
+ continue;
+ }
+
+ /* Yack when we find a parameter that we don't know about */
+ printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
+ exit (1);
+ }
+
+ /* Do we have Unicode support? */
+ if (fUnicodeClipboard)
+ {
+ printf ("Unicode clipboard I/O\n");
+ }
+ else
+ {
+ printf ("Non Unicode clipboard I/O\n");
+ }
+
+ /* Apply locale specified in the LANG environment variable */
+ if (!setlocale (LC_ALL, ""))
+ {
+ printf ("setlocale() error\n");
+ exit (1);
+ }
+
+ /* See if X supports the current locale */
+ if (XSupportsLocale () == False)
+ {
+ printf ("Locale not supported by X, falling back to 'C' locale.\n");
+ setlocale(LC_ALL, "C");
+ }
+
+ winClipboardProc(fUnicodeClipboard, pszDisplay);
+
+ return 0;
+}
diff --git a/hw/xwin/winclipboard/xwinclip.man b/hw/xwin/winclipboard/xwinclip.man
new file mode 100644
index 000000000..a53dc3029
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.man
@@ -0,0 +1,64 @@
+.TH xwinclip 1 __xorgversion__
+.SH NAME
+xwinclip - An X11 and Windows clipboard integration tool
+
+.SH SYNOPSIS
+.B xwinclip [OPTION]...
+
+.SH DESCRIPTION
+\fIxwinclip\fP is a tool for copying and pasting text between the Windows and X11 clipboard systems.
+
+\fIxwinclip\fP watches for updates to either clipboard and copies data between them when either one is updated.
+
+\fIxwinclip\fP monitors the X PRIMARY and CLIBPOARD selections for changes in ownership, and makes
+the contents of the most recent one to change available to paste from the Windows clipboard.
+
+It also monitors the contents of the Windows clipboard for changes, taking ownership of the PRIMARY and
+CLIPBOARD selections, and making the contents of the Windows clipboard available in them.
+
+.B Note well:
+The \fIXWin(1)\fP X server has internal clipboard integration that is enabled by default.
+Do \fINOT\fP run \fIxwinclip\fP unless \fIXWin(1)\fP has been started with the -noclipboard option.
+
+.SH OPTIONS
+\fIxwinclip\fP accepts the following optional command line switches:
+
+.TP 8
+.B \-display [display]
+Specifies the X server display to connect to.
+.TP 8
+.B \-nounicodeclipboard
+Do not use unicode text on the clipboard.
+.TP 8
+.B \-noprimary
+Do not monitor the PRIMARY selection.
+
+.SH "SEE ALSO"
+XWin(1)
+
+.SH BUGS
+Only text clipboard contents are supported.
+
+The INCR (Incrememntal transfer) clipboard protocol for clipboard contents larger than the maximum size of an
+X request is not supported.
+
+Some X clients, notably ones written in Tcl/Tk, do not re-assert ownership of the PRIMARY selection or update
+it's timestamp when it's contents change, which currently prevents \fIxwinclip\fP from correctly noticing that
+the PRIMARY selection's contents have changed.
+
+Windows clipboard rendering is synchronous in the WM_RENDER*FORMAT message (that is, we must have placed the
+contents onto the clipboard by the time we return from processing this message), but we must wait for the X
+client which owns the selection to convert the selection to our requested format. This is currently achieved
+using a fixed timeout of one second.
+
+The XWin(1) server should indicate somehow (by placing an atom on the root window?) that it is running with it's
+internal clipboard integration enabled, and xwinclip should notice this and exit with an appropriate error.
+
+Probably many other bugs.
+
+.SH "CONFORMING TO"
+ICCCM (Inter-Client Communication Conventions Manual) 2.0
+
+.SH AUTHORS
+Contributors to xwinclip include Benjamin Riefenstahl, Roland Cassard, Brian Genisio, Colin Harrison,
+Harold L Hunt II, Matsuzaki Kensuke, Jon Turney, Chris Twiner and Jeremy Wilkins.
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 157006dab..8aef8fe02 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -31,25 +31,79 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
-#include "dixstruct.h"
-#include "winclipboard.h"
+
+#include <unistd.h>
+#include <pthread.h>
+
+#include "win.h"
+#include "winclipboard/winclipboard.h"
+#include "windisplay.h"
+
+#define WIN_CLIPBOARD_RETRIES 40
+#define WIN_CLIPBOARD_DELAY 1
/*
- * Local typedefs
+ * Local variables
*/
-typedef int (*winDispatchProcPtr) (ClientPtr);
-
-int winProcSetSelectionOwner(ClientPtr /* client */ );
+static pthread_t g_ptClipboardProc;
/*
- * References to external symbols
+ *
*/
+static void *
+winClipboardThreadProc(void *arg)
+{
+ char szDisplay[512];
+ int clipboardRestarts = 0;
+
+ while (1)
+ {
+ Bool fShutdown;
+
+ ++clipboardRestarts;
-extern pthread_t g_ptClipboardProc;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
-extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
+ /* Use our generated cookie for authentication */
+ winSetAuthorization();
+
+ /* Setup the display connection string */
+ /*
+ * NOTE: Always connect to screen 0 since we require that screen
+ * numbers start at 0 and increase without gaps. We only need
+ * to connect to one screen on the display to get events
+ * for all screens on the display. That is why there is only
+ * one clipboard client thread.
+ */
+ winGetDisplayName(szDisplay, 0);
+
+ /* Print the display connection string */
+ ErrorF("winClipboardThreadProc - DISPLAY=%s\n", szDisplay);
+
+ /* Flag that clipboard client has been launched */
+ g_fClipboardStarted = TRUE;
+
+ fShutdown = winClipboardProc(g_fUnicodeClipboard, szDisplay);
+
+ /* Flag that clipboard client has stopped */
+ g_fClipboardStarted = FALSE;
+
+ if (fShutdown)
+ break;
+
+ /* checking if we need to restart */
+ if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
+ /* terminates clipboard thread but the main server still lives */
+ ErrorF("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n", clipboardRestarts);
+ g_fClipboard = FALSE;
+ break;
+ }
+
+ sleep(WIN_CLIPBOARD_DELAY);
+ ErrorF("winClipboardProc - trying to restart clipboard thread \n");
+ }
+
+ return NULL;
+}
/*
* Intialize the Clipboard module
@@ -60,14 +114,8 @@ winInitClipboard(void)
{
winDebug("winInitClipboard ()\n");
- /* Wrap some internal server functions */
- if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) {
- winProcSetSelectionOwnerOrig = ProcVector[X_SetSelectionOwner];
- ProcVector[X_SetSelectionOwner] = winProcSetSelectionOwner;
- }
-
/* Spawn a thread for the Clipboard module */
- if (pthread_create(&g_ptClipboardProc, NULL, winClipboardProc, NULL)) {
+ if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) {
/* Bail if thread creation failed */
ErrorF("winInitClipboard - pthread_create failed.\n");
return FALSE;
@@ -76,59 +124,19 @@ winInitClipboard(void)
return TRUE;
}
-/*
- * Create the Windows window that we use to receive Windows messages
- */
-
-HWND
-winClipboardCreateMessagingWindow(void)
-{
- WNDCLASSEX wc;
- HWND hwnd;
-
- /* Setup our window class */
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = winClipboardWindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
- wc.hIconSm = 0;
- RegisterClassEx(&wc);
-
- /* Create the window */
- hwnd = CreateWindowExA(0, /* Extended styles */
- WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */
- WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
- WS_OVERLAPPED, /* Not visible anyway */
- CW_USEDEFAULT, /* Horizontal position */
- CW_USEDEFAULT, /* Vertical position */
- CW_USEDEFAULT, /* Right edge */
- CW_USEDEFAULT, /* Bottom edge */
- (HWND) NULL, /* No parent or owner window */
- (HMENU) NULL, /* No menu */
- GetModuleHandle(NULL), /* Instance handle */
- NULL); /* Creation data */
- assert(hwnd != NULL);
-
- /* I'm not sure, but we may need to call this to start message processing */
- ShowWindow(hwnd, SW_HIDE);
-
- /* Similarly, we may need a call to this even though we don't paint */
- UpdateWindow(hwnd);
-
- return hwnd;
-}
-
void
-winFixClipboardChain(void)
+winClipboardShutdown(void)
{
- if (g_fClipboard && g_hwndClipboard) {
- PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
- }
+ /* Close down clipboard resources */
+ if (g_fClipboard && g_fClipboardStarted) {
+ /* Synchronously destroy the clipboard window */
+ winClipboardWindowDestroy();
+
+ /* Wait for the clipboard thread to exit */
+ pthread_join(g_ptClipboardProc, NULL);
+
+ g_fClipboardStarted = FALSE;
+
+ winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
+ }
}
diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index bfd6bff8b..2679f4f98 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -33,36 +33,21 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "dixstruct.h"
-#include <X11/Xatom.h>
-
-/*
- * Constants
- */
-
-#define CLIP_NUM_SELECTIONS 2
-#define CLIP_OWN_PRIMARY 0
-#define CLIP_OWN_CLIPBOARD 1
/*
* Local function prototypes
*/
DISPATCH_PROC(winProcEstablishConnection);
-DISPATCH_PROC(winProcSetSelectionOwner);
/*
* References to external symbols
*/
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
extern Bool g_fClipboard;
-extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
-extern HWND g_hwndClipboard;
-
/*
* Wrapper for internal EstablishConnection function.
@@ -127,13 +112,6 @@ winProcEstablishConnection(ClientPtr client)
/* Clear original function pointer */
winProcEstablishConnectionOrig = NULL;
- /* If the clipboard client has already been started, abort */
- if (g_fClipboardLaunched) {
- ErrorF("winProcEstablishConnection - Clipboard client already "
- "launched, returning.\n");
- return iReturn;
- }
-
/* Startup the clipboard client if clipboard mode is being used */
if (g_fClipboard) {
/*
@@ -163,207 +141,5 @@ winProcEstablishConnection(ClientPtr client)
ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
}
- /* Flag that clipboard client has been launched */
- g_fClipboardLaunched = TRUE;
-
return iReturn;
}
-
-/*
- * Wrapper for internal SetSelectionOwner function.
- * Grabs ownership of Windows clipboard when X11 clipboard owner changes.
- */
-
-int
-winProcSetSelectionOwner(ClientPtr client)
-{
- int i;
- DrawablePtr pDrawable;
- WindowPtr pWindow = None;
- Bool fOwnedToNotOwned = FALSE;
- static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
- static unsigned long s_ulServerGeneration = 0;
-
- REQUEST(xSetSelectionOwnerReq);
-
- REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
-
- winDebug("winProcSetSelectionOwner - Hello.\n");
-
- /* Watch for server reset */
- if (s_ulServerGeneration != serverGeneration) {
- /* Save new generation number */
- s_ulServerGeneration = serverGeneration;
-
- /* Initialize static variables */
- for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
- s_iOwners[i] = None;
- }
-
- /* Abort if clipboard not completely initialized yet */
- if (!g_fClipboardStarted) {
- /* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
- "aborting.\n"); */
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Grab window if we have one */
- if (None != stuff->window) {
- /* Grab the Window from the request */
- int rc =
- dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
- if (rc != Success) {
- ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
- }
-
- /* Now we either have a valid window or None */
-
- /* Save selection owners for monitored selections, ignore other selections */
- if (XA_PRIMARY == stuff->selection) {
- /* Look for owned -> not owned transition */
- if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
- fOwnedToNotOwned = TRUE;
-
- winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
- "owned to not owned.\n");
-
- /* Adjust last owned selection */
- if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
- g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
- else
- g_atomLastOwnedSelection = None;
- }
-
- /* Save new selection owner or None */
- s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
-
- winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
- stuff->window);
- }
- else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
- /* Look for owned -> not owned transition */
- if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
- fOwnedToNotOwned = TRUE;
-
- winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
- "owned to not owned.\n");
-
- /* Adjust last owned selection */
- if (None != s_iOwners[CLIP_OWN_PRIMARY])
- g_atomLastOwnedSelection = XA_PRIMARY;
- else
- g_atomLastOwnedSelection = None;
- }
-
- /* Save new selection owner or None */
- s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
-
- winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
- stuff->window);
-
- }
- else
- goto winProcSetSelectionOwner_Done;
-
- /*
- * At this point, if one of the selections is still owned by the
- * clipboard manager then it should be marked as unowned since
- * we will be taking ownership of the Win32 clipboard.
- */
- if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
- s_iOwners[CLIP_OWN_PRIMARY] = None;
- if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
- s_iOwners[CLIP_OWN_CLIPBOARD] = None;
-
- /*
- * Handle case when selection is being disowned,
- * WM_DRAWCLIPBOARD did not do the disowning,
- * both monitored selections are no longer owned,
- * an owned to not owned transition was detected,
- * and we currently own the Win32 clipboard.
- */
- if (stuff->window == None
- && s_iOwners[CLIP_OWN_PRIMARY] == None
- && s_iOwners[CLIP_OWN_CLIPBOARD] == None
- && fOwnedToNotOwned
- && g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
- winDebug("winProcSetSelectionOwner - We currently own the "
- "clipboard and neither the PRIMARY nor the CLIPBOARD "
- "selections are owned, releasing ownership of Win32 "
- "clipboard.\n");
-
- /* Release ownership of the Windows clipboard */
- OpenClipboard(NULL);
- EmptyClipboard();
- CloseClipboard();
-
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if no window at this point */
- if (None == stuff->window) {
- winDebug("winProcSetSelectionOwner - No window, returning.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if invalid selection */
- if (!ValidAtom(stuff->selection)) {
- ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Cast Window to Drawable */
- pDrawable = (DrawablePtr) pWindow;
-
- /* Abort if clipboard manager is owning the selection */
- if (pDrawable->id == g_iClipboardWindow) {
- winDebug("winProcSetSelectionOwner - We changed ownership, "
- "aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if root window is taking ownership */
- if (pDrawable->id == 0) {
- ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
- "aborting\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Close clipboard if we have it open already */
- if (GetOpenClipboardWindow() == g_hwndClipboard) {
- CloseClipboard();
- }
-
- /* Access the Windows clipboard */
- if (!OpenClipboard(g_hwndClipboard)) {
- ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
- (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Take ownership of the Windows clipboard */
- if (!EmptyClipboard()) {
- ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
- (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Advertise regular text and unicode */
- SetClipboardData(CF_UNICODETEXT, NULL);
- SetClipboardData(CF_TEXT, NULL);
-
- /* Save handle to last owned selection */
- g_atomLastOwnedSelection = stuff->selection;
-
- /* Release the clipboard */
- if (!CloseClipboard()) {
- ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
- "%08x\n", (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- winProcSetSelectionOwner_Done:
- return (*winProcSetSelectionOwnerOrig) (client);
-}
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index a6d3c0a1f..ad3218dcc 100644
--- a/hw/xwin/winconfig.c
+++ b/hw/xwin/winconfig.c
@@ -70,6 +70,7 @@ WinCmdlineRec g_cmdline = {
#ifdef XWIN_XF86CONFIG
NULL, /* keyboard */
#endif
+ FALSE, /* customDPI */
NULL, /* xkbRules */
NULL, /* xkbModel */
NULL, /* xkbLayout */
@@ -263,8 +264,8 @@ winConfigKeyboard(DeviceIntPtr pDevice)
break;
}
g_winInfo.keyboard.rate = (kbd_speed > 0) ? kbd_speed : 1;
- winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%d, rate=%d\n",
- g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
+ winMsg(X_PROBED, "Setting autorepeat to delay=%d, rate=%d\n",
+ g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
}
}
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index 798c779a6..a2d40f09b 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -160,6 +160,7 @@ typedef struct {
#ifdef XWIN_XF86CONFIG
char *keyboard;
#endif
+ Bool customDPI;
char *xkbRules;
char *xkbModel;
char *xkbLayout;
@@ -200,7 +201,7 @@ typedef union {
unsigned long num;
char *str;
double realnum;
- Bool bool;
+ Bool bool_;
OptFrequency freq;
} ValueUnion;
diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c
index f3ac0f7ae..8e870414e 100644
--- a/hw/xwin/wincursor.c
+++ b/hw/xwin/wincursor.c
@@ -34,14 +34,14 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "winmsg.h"
#include <cursorstr.h>
#include <mipointrst.h>
#include <servermd.h>
#include "misc.h"
-
-#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114)
+#include "wmutil/cursor_convert.h"
#if 0
#define WIN_DEBUG_MSG winDebug
@@ -128,296 +128,30 @@ winCrossScreen(ScreenPtr pScreen, Bool fEntering)
{
}
-static unsigned char
-reverse(unsigned char c)
-{
- int i;
- unsigned char ret = 0;
-
- for (i = 0; i < 8; ++i) {
- ret |= ((c >> i) & 1) << (7 - i);
- }
- return ret;
-}
-
/*
* Convert X cursor to Windows cursor
- * FIXME: Perhaps there are more smart code
*/
static HCURSOR
winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen)
{
- winScreenPriv(pScreen);
- HCURSOR hCursor = NULL;
- unsigned char *pAnd;
- unsigned char *pXor;
- int nCX, nCY;
- int nBytes;
- double dForeY, dBackY;
- BOOL fReverse;
- HBITMAP hAnd, hXor;
- ICONINFO ii;
- unsigned char *pCur;
- unsigned char bit;
- HDC hDC;
- BITMAPV4HEADER bi;
- BITMAPINFO *pbmi;
- uint32_t *lpBits;
-
- WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height,
- pCursor->bits->xhot, pCursor->bits->yhot);
-
- /* We can use only White and Black, so calc brightness of color
- * Also check if the cursor is inverted */
- dForeY = BRIGHTNESS(pCursor->fore);
- dBackY = BRIGHTNESS(pCursor->back);
- fReverse = dForeY < dBackY;
-
- /* Check wether the X11 cursor is bigger than the win32 cursor */
- if (pScreenPriv->cursor.sm_cx < pCursor->bits->width ||
- pScreenPriv->cursor.sm_cy < pCursor->bits->height) {
- winErrorFVerb(3,
- "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height);
- }
-
- /* Get the number of bytes required to store the whole cursor image
- * This is roughly (sm_cx * sm_cy) / 8
- * round up to 8 pixel boundary so we can convert whole bytes */
- nBytes =
- bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy;
-
- /* Get the effective width and height */
- nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width);
- nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height);
-
- /* Allocate memory for the bitmaps */
- pAnd = malloc(nBytes);
- memset(pAnd, 0xFF, nBytes);
- pXor = calloc(1, nBytes);
-
- /* Convert the X11 bitmap to a win32 bitmap
- * The first is for an empty mask */
- if (pCursor->bits->emptyMask) {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- pAnd[nWinPix] = 0;
- if (fReverse)
- pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]);
- else
- pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]);
- }
- }
- else {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- unsigned char mask = pCursor->bits->mask[nXPix];
-
- pAnd[nWinPix] = reverse(~mask);
- if (fReverse)
- pXor[nWinPix] =
- reverse(~pCursor->bits->source[nXPix] & mask);
- else
- pXor[nWinPix] =
- reverse(pCursor->bits->source[nXPix] & mask);
- }
- }
-
- /* prepare the pointers */
- hCursor = NULL;
- lpBits = NULL;
-
- /* We have a truecolor alpha-blended cursor and can use it! */
- if (pCursor->bits->argb) {
- WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n");
- memset(&bi, 0, sizeof(BITMAPV4HEADER));
- bi.bV4Size = sizeof(BITMAPV4HEADER);
- bi.bV4Width = pScreenPriv->cursor.sm_cx;
- bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */
- bi.bV4Planes = 1;
- bi.bV4BitCount = 32;
- bi.bV4V4Compression = BI_BITFIELDS;
- bi.bV4RedMask = 0x00FF0000;
- bi.bV4GreenMask = 0x0000FF00;
- bi.bV4BlueMask = 0x000000FF;
- bi.bV4AlphaMask = 0xFF000000;
-
- lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy,
- sizeof(uint32_t));
-
- if (lpBits) {
- int y;
- for (y = 0; y < nCY; y++) {
- void *src, *dst;
- src = &(pCursor->bits->argb[y * pCursor->bits->width]);
- dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]);
- memcpy(dst, src, 4 * nCX);
- }
- }
- } /* End if-truecolor-icon */
-
- if (!lpBits) {
- RGBQUAD *pbmiColors;
- /* Bicolor, use a palettized DIB */
- WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n");
- pbmi = (BITMAPINFO *) &bi;
- pbmiColors = &(pbmi->bmiColors[0]);
-
- memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx;
- pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */
- pbmi->bmiHeader.biPlanes = 1;
- pbmi->bmiHeader.biBitCount = 8;
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biClrUsed = 3;
- pbmi->bmiHeader.biClrImportant = 3;
-
- pbmiColors[0].rgbRed = 0; /* Empty */
- pbmiColors[0].rgbGreen = 0;
- pbmiColors[0].rgbBlue = 0;
- pbmiColors[0].rgbReserved = 0;
- pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
- pbmiColors[1].rgbGreen = pCursor->backGreen >> 8;
- pbmiColors[1].rgbBlue = pCursor->backBlue >> 8;
- pbmiColors[1].rgbReserved = 0;
- pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
- pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
- pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
- pbmiColors[2].rgbReserved = 0;
-
- lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1);
-
- pCur = (unsigned char *) lpBits;
- if (lpBits) {
- int x, y;
- for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) {
- for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) {
- if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */
- (*pCur++) = 0;
- else { /* Within X11 icon bounds */
-
- int nWinPix =
- bits_to_bytes(pScreenPriv->cursor.sm_cx) * y +
- (x / 8);
-
- bit = pAnd[nWinPix];
- bit = bit & (1 << (7 - (x & 7)));
- if (!bit) { /* Within the cursor mask? */
- int nXPix =
- BitmapBytePad(pCursor->bits->width) * y +
- (x / 8);
- bit =
- ~reverse(~pCursor->bits->
- source[nXPix] & pCursor->bits->
- mask[nXPix]);
- bit = bit & (1 << (7 - (x & 7)));
- if (bit) /* Draw foreground */
- (*pCur++) = 2;
- else /* Draw background */
- (*pCur++) = 1;
- }
- else /* Outside the cursor mask */
- (*pCur++) = 0;
- }
- } /* end for (x) */
- } /* end for (y) */
- } /* end if (lpbits) */
- }
-
- /* If one of the previous two methods gave us the bitmap we need, make a cursor */
- if (lpBits) {
- WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n",
- pCursor->bits->xhot, pCursor->bits->yhot);
-
- hAnd = NULL;
- hXor = NULL;
-
- hAnd =
- CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- 1, 1, pAnd);
-
- hDC = GetDC(NULL);
- if (hDC) {
- hXor =
- CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx,
- pScreenPriv->cursor.sm_cy);
- SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits,
- (BITMAPINFO *) &bi, DIB_RGB_COLORS);
- ReleaseDC(NULL, hDC);
- }
- free(lpBits);
-
- if (hAnd && hXor) {
- ii.fIcon = FALSE;
- ii.xHotspot = pCursor->bits->xhot;
- ii.yHotspot = pCursor->bits->yhot;
- ii.hbmMask = hAnd;
- ii.hbmColor = hXor;
- hCursor = (HCURSOR) CreateIconIndirect(&ii);
-
- if (hCursor == NULL)
- winW32Error(2, "winLoadCursor - CreateIconIndirect failed:");
- else {
- if (GetIconInfo(hCursor, &ii)) {
- if (ii.fIcon) {
- WIN_DEBUG_MSG
- ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n");
-
- DestroyCursor(hCursor);
-
- ii.fIcon = FALSE;
- ii.xHotspot = pCursor->bits->xhot;
- ii.yHotspot = pCursor->bits->yhot;
- hCursor = (HCURSOR) CreateIconIndirect(&ii);
-
- if (hCursor == NULL)
- winW32Error(2,
- "winLoadCursor - CreateIconIndirect failed:");
- }
- /* GetIconInfo creates new bitmaps. Destroy them again */
- if (ii.hbmMask)
- DeleteObject(ii.hbmMask);
- if (ii.hbmColor)
- DeleteObject(ii.hbmColor);
- }
- }
- }
-
- if (hAnd)
- DeleteObject(hAnd);
- if (hXor)
- DeleteObject(hXor);
- }
-
- if (!hCursor) {
- /* We couldn't make a color cursor for this screen, use
- black and white instead */
- hCursor = CreateCursor(g_hInstance,
- pCursor->bits->xhot, pCursor->bits->yhot,
- pScreenPriv->cursor.sm_cx,
- pScreenPriv->cursor.sm_cy, pAnd, pXor);
- if (hCursor == NULL)
- winW32Error(2, "winLoadCursor - CreateCursor failed:");
- }
- free(pAnd);
- free(pXor);
-
- return hCursor;
+ WMUTIL_CURSOR cursor;
+
+ cursor.width = pCursor->bits->width;
+ cursor.height = pCursor->bits->height;
+ cursor.xhot = pCursor->bits->xhot;
+ cursor.yhot = pCursor->bits->yhot;
+ cursor.argb = (uint32_t *)pCursor->bits->argb;
+ cursor.source = pCursor->bits->source;
+ cursor.mask = pCursor->bits->mask;
+ cursor.emptyMask = pCursor->bits->emptyMask;
+ cursor.foreRed = pCursor->foreRed;
+ cursor.foreGreen = pCursor->foreGreen;
+ cursor.foreBlue = pCursor->foreBlue;
+ cursor.backRed = pCursor->backRed;
+ cursor.backGreen = pCursor->backGreen;
+ cursor.backBlue = pCursor->backBlue;
+
+ return winXCursorToHCURSOR(&cursor);
}
/*
diff --git a/hw/xwin/windialogs.c b/hw/xwin/windialogs.c
index c9af0e203..61f7fe0bd 100644
--- a/hw/xwin/windialogs.c
+++ b/hw/xwin/windialogs.c
@@ -37,13 +37,6 @@
#include "winprefs.h"
/*
- * References to external globals
- */
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fClipboardStarted;
-#endif
-/*
* Local function prototypes
*/
diff --git a/hw/xwin/windisplay.c b/hw/xwin/windisplay.c
new file mode 100644
index 000000000..17f0c7789
--- /dev/null
+++ b/hw/xwin/windisplay.c
@@ -0,0 +1,64 @@
+/*
+ * File: windisplay.c
+ * Purpose: Retrieve server display name
+ *
+ * Copyright (C) Jon TURNEY 2009
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <opaque.h> // for display
+#include "windisplay.h"
+#include "winmsg.h"
+
+#define XSERV_t
+#define TRANS_SERVER
+#include <X11/Xtrans/Xtrans.h>
+
+/*
+ Generate a display name string referring to the display of this server,
+ using a transport we know is enabled
+*/
+
+void
+winGetDisplayName(char *szDisplay, unsigned int screen)
+{
+ if (_XSERVTransIsListening("local")) {
+ snprintf(szDisplay, 512, ":%s.%d", display, screen);
+ }
+ else if (_XSERVTransIsListening("inet")) {
+ snprintf(szDisplay, 512, "127.0.0.1:%s.%d", display, screen);
+ }
+ else if (_XSERVTransIsListening("inet6")) {
+ snprintf(szDisplay, 512, "::1:%s.%d", display, screen);
+ }
+ else {
+ // this can't happen!
+ ErrorF("winGetDisplay: Don't know what to use for DISPLAY\n");
+ snprintf(szDisplay, 512, "localhost:%s.%d", display, screen);
+ }
+
+ winDebug("winGetDisplay: DISPLAY=%s\n", szDisplay);
+}
diff --git a/hw/xwin/windisplay.h b/hw/xwin/windisplay.h
new file mode 100644
index 000000000..d1d4549bf
--- /dev/null
+++ b/hw/xwin/windisplay.h
@@ -0,0 +1,34 @@
+/*
+ * File: windisplay.h
+ * Purpose: Interface to retrieve server display name
+ *
+ * Copyright (C) Jon TURNEY 2009
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WINDISPLAY_H
+#define WINDISPLAY_H
+
+void
+winGetDisplayName(char *szDisplay, unsigned int screen);
+
+#endif /* !WINDISPLAY_H */
diff --git a/hw/xwin/winengine.c b/hw/xwin/winengine.c
index 1f55ada58..94e5e36e9 100644
--- a/hw/xwin/winengine.c
+++ b/hw/xwin/winengine.c
@@ -89,21 +89,6 @@ winDetectSupportedEngines(void)
"winDetectSupportedEngines - DirectDraw not installed\n");
return;
}
- else {
- /* We have DirectDraw */
- winErrorFVerb(2,
- "winDetectSupportedEngines - DirectDraw installed, allowing ShadowDD\n");
- g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD;
-
-#ifdef XWIN_PRIMARYFB
- /* Allow PrimaryDD engine if NT */
- if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD;
- winErrorFVerb(2,
- "winDetectSupportedEngines - Windows NT, allowing PrimaryDD\n");
- }
-#endif
- }
/* Try to query for DirectDraw4 interface */
ddrval = IDirectDraw_QueryInterface(lpdd,
diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c
index 1318b0f36..ff2919c27 100644
--- a/hw/xwin/winerror.c
+++ b/hw/xwin/winerror.c
@@ -48,6 +48,16 @@ OsVendorVErrorF(const char *pszFormat, va_list va_args)
pthread_mutex_lock(&s_pmPrinting);
#endif
+ /* If we want to silence it,
+ * detect if we are going to abort due to duplication error */
+ if (g_fSilentDupError) {
+ if ((strcmp(pszFormat, "InitOutput - Duplicate invocation on display number: %s. Exiting.\n") == 0)
+ || (strcmp(pszFormat, "Server is already active for display %s\n%s %s\n%s\n") == 0)
+ || (strcmp(pszFormat, "MakeAllCOTSServerListeners: server already running\n") == 0)) {
+ g_fSilentFatalError = TRUE;
+ }
+ }
+
/* Print the error message to a log file, could be stderr */
LogVWrite(0, pszFormat, va_args);
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index b9ad294d5..1382c8972 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -78,7 +78,7 @@ Bool g_fNoHelpMessageBox = FALSE;
Bool g_fSoftwareCursor = FALSE;
Bool g_fSilentDupError = FALSE;
Bool g_fNativeGl = TRUE;
-Bool g_fHostInTitle = FALSE;
+Bool g_fHostInTitle = TRUE;
pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
#ifdef XWIN_CLIPBOARD
@@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
* Wrapped DIX functions
*/
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
-winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
/*
* Clipboard variables
@@ -94,13 +93,7 @@ winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
Bool g_fUnicodeClipboard = TRUE;
Bool g_fClipboard = TRUE;
-Bool g_fClipboardLaunched = FALSE;
Bool g_fClipboardStarted = FALSE;
-pthread_t g_ptClipboardProc;
-HWND g_hwndClipboard = NULL;
-void *g_pClipboardDisplay = NULL;
-Window g_iClipboardWindow = None;
-Atom g_atomLastOwnedSelection = None;
#endif
/*
@@ -112,10 +105,4 @@ void
winInitializeGlobals(void)
{
g_dwCurrentThreadID = GetCurrentThreadId();
-#ifdef XWIN_CLIPBOARD
- g_iClipboardWindow = None;
- g_pClipboardDisplay = NULL;
- g_atomLastOwnedSelection = None;
- g_hwndClipboard = NULL;
-#endif
}
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index 60c00da42..d7b813dbb 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -72,8 +72,10 @@ typedef int (*winDispatchProcPtr) (ClientPtr);
* Wrapped DIX functions
*/
extern winDispatchProcPtr winProcEstablishConnectionOrig;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
#endif
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboard;
+extern Bool g_fClipboardStarted;
/* The global X default icons */
#if defined(XWIN_MULTIWINDOW)
diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c
index 3a75ab268..403157090 100644
--- a/hw/xwin/winkeybd.c
+++ b/hw/xwin/winkeybd.c
@@ -34,17 +34,24 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
-#include "winkeybd.h"
+#include "wmutil/scancodes.h"
+#include "wmutil/keyboard.h"
#include "winconfig.h"
#include "winmsg.h"
#include "xkbsrv.h"
+#include "dixgrabs.h"
/* C does not have a logical XOR operator, so we use a macro instead */
#define LOGICAL_XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
-static Bool g_winKeyState[NUM_KEYCODES];
+#define AltMask Mod1Mask
+#define NumLockMask Mod2Mask
+#define AltLangMask Mod3Mask
+#define KanaMask Mod4Mask
+#define ScrollLockMask Mod5Mask
/*
* Local prototypes
@@ -56,68 +63,6 @@ static void
static void
winKeybdCtrl(DeviceIntPtr pDevice, KeybdCtrl * pCtrl);
-/*
- * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
- * into an ASCII scan code.
- *
- * We do this ourselves, rather than letting Windows handle it,
- * because Windows tends to munge the handling of special keys,
- * like AltGr on European keyboards.
- */
-
-int
-winTranslateKey(WPARAM wParam, LPARAM lParam)
-{
- int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
- int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
- int iParam = HIWORD(lParam);
- int iParamScanCode = LOBYTE(iParam);
- int iScanCode;
-
- winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
-
-/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
- * scan code.
- *
- * Vocola 3 (Rick Mohr's supplement to WSR) uses
- * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
- * scan code of 1
- */
- if (iParamScanCode <= 1) {
- if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
- /* Trigger special case table to translate to extended
- * keycode, otherwise if num_lock is on, we can get keypad
- * numbers instead of navigation keys. */
- iParam |= KF_EXTENDED;
- else
- iParamScanCode = MapVirtualKeyEx(wParam,
- /*MAPVK_VK_TO_VSC */ 0,
- GetKeyboardLayout(0));
- }
-
- /* Branch on special extended, special non-extended, or normal key */
- if ((iParam & KF_EXTENDED) && iKeyFixupEx)
- iScanCode = iKeyFixupEx;
- else if (iKeyFixup)
- iScanCode = iKeyFixup;
- else if (wParam == 0 && iParamScanCode == 0x70)
- iScanCode = KEY_HKTG;
- else
- switch (iParamScanCode) {
- case 0x70:
- iScanCode = KEY_HKTG;
- break;
- case 0x73:
- iScanCode = KEY_BSlash2;
- break;
- default:
- iScanCode = iParamScanCode;
- break;
- }
-
- return iScanCode;
-}
-
/* Ring the keyboard bell (system speaker on PCs) */
static void
winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, void *pCtrl, int iClass)
@@ -337,209 +282,46 @@ winRestoreModeKeyStates(void)
*/
}
-/*
- * Look for the lovely fake Control_L press/release generated by Windows
- * when AltGr is pressed/released on a non-U.S. keyboard.
- */
-
-Bool
-winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
-{
- MSG msgNext;
- LONG lTime;
- Bool fReturn;
-
- static Bool lastWasControlL = FALSE;
- static LONG lastTime;
-
- /*
- * Fake Ctrl_L presses will be followed by an Alt_R press
- * with the same timestamp as the Ctrl_L press.
- */
- if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
- /* Got a Ctrl_L press */
-
- /* Get time of current message */
- lTime = GetMessageTime();
-
- /* Look for next press message */
- fReturn = PeekMessage(&msgNext, NULL,
- WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
-
- if (fReturn && msgNext.message != WM_KEYDOWN &&
- msgNext.message != WM_SYSKEYDOWN)
- fReturn = 0;
-
- if (!fReturn) {
- lastWasControlL = TRUE;
- lastTime = lTime;
- }
- else {
- lastWasControlL = FALSE;
- }
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
- /*
- * Next key press is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L press is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
- /*
- * Sometimes, the Alt_R press message is not yet posted when the
- * fake Ctrl_L press message arrives (even though it has the
- * same timestamp), so check for an Alt_R press message that has
- * arrived since the last Ctrl_L message.
- */
- else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
- /* Got a Alt_R press */
-
- if (lastWasControlL) {
- lTime = GetMessageTime();
-
- if (lastTime == lTime) {
- /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */
- winSendKeyEvent(KEY_LCtrl, FALSE);
- }
- lastWasControlL = FALSE;
- }
- }
- /*
- * Fake Ctrl_L releases will be followed by an Alt_R release
- * with the same timestamp as the Ctrl_L release.
- */
- else if ((message == WM_KEYUP || message == WM_SYSKEYUP)
- && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
- /* Got a Ctrl_L release */
-
- /* Get time of current message */
- lTime = GetMessageTime();
-
- /* Look for next release message */
- fReturn = PeekMessage(&msgNext, NULL,
- WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE);
-
- if (fReturn && msgNext.message != WM_KEYUP &&
- msgNext.message != WM_SYSKEYUP)
- fReturn = 0;
-
- lastWasControlL = FALSE;
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn
- && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP)
- && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
- /*
- * Next key release is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L release is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
- else {
- /* On any other press or release message, we don't have a
- potentially fake Ctrl_L to worry about anymore... */
- lastWasControlL = FALSE;
- }
-
- /* Not a fake control left press/release */
- return FALSE;
-}
-
-/*
- * Lift any modifier keys that are pressed
- */
-
void
-winKeybdReleaseKeys(void)
+winSendKeyEventCallback(DWORD dwKey, bool fDown)
{
- int i;
-
#ifdef HAS_DEVWINDOWS
/* Verify that the mi input system has been initialized */
if (g_fdMessageQueue == WIN_FD_INVALID)
return;
#endif
- /* Loop through all keys */
- for (i = 0; i < NUM_KEYCODES; ++i) {
- /* Pop key if pressed */
- if (g_winKeyState[i])
- winSendKeyEvent(i, FALSE);
-
- /* Reset pressed flag for keys */
- g_winKeyState[i] = FALSE;
- }
+ QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease,
+ dwKey, NULL);
}
/*
- * Take a raw X key code and send an up or down event for it.
- *
- * Thanks to VNC for inspiration, though it is a simple function.
*/
-
-void
-winSendKeyEvent(DWORD dwKey, Bool fDown)
-{
- /*
- * When alt-tabing between screens we can get phantom key up messages
- * Here we only pass them through it we think we should!
- */
- if (g_winKeyState[dwKey] == FALSE && fDown == FALSE)
- return;
-
- /* Update the keyState map */
- g_winKeyState[dwKey] = fDown;
-
- QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease,
- dwKey + MIN_KEYCODE, NULL);
-
- winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown);
-}
-
-BOOL
-winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
+int
+XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act)
{
- switch (wParam) {
- case VK_CONTROL:
- if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
- return TRUE;
- if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
- return TRUE;
- break;
- case VK_SHIFT:
- if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
- return TRUE;
- if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
- return TRUE;
- break;
- default:
- return TRUE;
+ XkbAnyAction *xf86act = &(act->any);
+ char msgbuf[XkbAnyActionDataSize+1];
+
+ if (xf86act->type == XkbSA_XFree86Private)
+ {
+ memcpy(msgbuf, xf86act->data, XkbAnyActionDataSize);
+ msgbuf[XkbAnyActionDataSize]= '\0';
+ if (strcasecmp(msgbuf, "prgrbs")==0) {
+ DeviceIntPtr tmp;
+ winMsg(X_INFO, "Printing all currently active device grabs:\n");
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next)
+ if (tmp->deviceGrab.grab)
+ PrintDeviceGrabInfo(tmp);
+ winMsg(X_INFO, "End list of active device grabs\n");
+ }
+ else if (strcasecmp(msgbuf, "ungrab")==0)
+ UngrabAllDevices(FALSE);
+ else if (strcasecmp(msgbuf, "clsgrb")==0)
+ UngrabAllDevices(TRUE);
+ else if (strcasecmp(msgbuf, "prwins")==0)
+ PrintWindowTree();
}
- return FALSE;
-}
-
-/* Only one shift release message is sent even if both are pressed.
- * Fix this here
- */
-void
-winFixShiftKeys(int iScanCode)
-{
- if (GetKeyState(VK_SHIFT) & 0x8000)
- return;
- if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
- winSendKeyEvent(KEY_ShiftR, FALSE);
- if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
- winSendKeyEvent(KEY_ShiftL, FALSE);
+ return 0;
}
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index bbe21cba6..59705e655 100644
--- a/hw/xwin/winmouse.c
+++ b/hw/xwin/winmouse.c
@@ -41,6 +41,8 @@
#include "xserver-properties.h"
#include "inpututils.h"
+#include "wmutil/mouse.h"
+
/* Peek the internal button mapping */
static CARD8 const *g_winMouseButtonMap = NULL;
@@ -143,86 +145,20 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
return Success;
}
-/* Handle the mouse wheel */
-int
-winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown)
-{
- int button;
-
- /* Do we have any previous delta stored? */
- if ((*iTotalDeltaZ > 0 && iDeltaZ > 0)
- || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) {
- /* Previous delta and of same sign as current delta */
- iDeltaZ += *iTotalDeltaZ;
- *iTotalDeltaZ = 0;
- }
- else {
- /*
- * Previous delta of different sign, or zero.
- * We will set it to zero for either case,
- * as blindly setting takes just as much time
- * as checking, then setting if necessary :)
- */
- *iTotalDeltaZ = 0;
- }
-
- /*
- * Only process this message if the wheel has moved further than
- * WHEEL_DELTA
- */
- if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
- *iTotalDeltaZ = 0;
-
- /* Figure out how many whole deltas of the wheel we have */
- iDeltaZ /= WHEEL_DELTA;
- }
- else {
- /*
- * Wheel has not moved past WHEEL_DELTA threshold;
- * we will store the wheel delta until the threshold
- * has been reached.
- */
- *iTotalDeltaZ = iDeltaZ;
- return 0;
- }
-
- /* Set the button to indicate up or down wheel delta */
- if (iDeltaZ > 0) {
- button = iButtonUp;
- }
- else {
- button = iButtonDown;
- }
-
- /*
- * Flip iDeltaZ to positive, if negative,
- * because always need to generate a *positive* number of
- * button clicks for the Z axis.
- */
- if (iDeltaZ < 0) {
- iDeltaZ *= -1;
- }
-
- /* Generate X input messages for each wheel delta we have seen */
- while (iDeltaZ--) {
- /* Push the wheel button */
- winMouseButtonsSendEvent(ButtonPress, button);
-
- /* Release the wheel button */
- winMouseButtonsSendEvent(ButtonRelease, button);
- }
-
- return 0;
-}
-
/*
* Enqueue a mouse button event
*/
void
-winMouseButtonsSendEvent(int iEventType, int iButton)
+winMouseButtonsSendEvent(bool bPress, int iButton)
{
ValuatorMask mask;
+ int iEventType;
+
+ if (bPress)
+ iEventType = ButtonPress;
+ else
+ iEventType = ButtonRelease;
if (g_winMouseButtonMap)
iButton = g_winMouseButtonMap[iButton];
@@ -251,7 +187,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
/* Send button events right away if emulate 3 buttons is off */
if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF) {
/* Emulate 3 buttons is off, send the button event */
- winMouseButtonsSendEvent(iEventType, iButton);
+ winMouseButtonsSendEvent((iEventType == ButtonPress), iButton);
return 0;
}
@@ -288,7 +224,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send fake middle button */
- winMouseButtonsSendEvent(ButtonPress, Button2);
+ winMouseButtonsSendEvent(TRUE, Button2);
/* Indicate that a fake middle button event was sent */
pScreenPriv->fE3BFakeButton2Sent = TRUE;
@@ -303,8 +239,8 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send cached press, then send release */
- winMouseButtonsSendEvent(ButtonPress, iButton);
- winMouseButtonsSendEvent(ButtonRelease, iButton);
+ winMouseButtonsSendEvent(TRUE, iButton);
+ winMouseButtonsSendEvent(FALSE, iButton);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->fE3BFakeButton2Sent && !(wParam & MK_LBUTTON)
@@ -315,7 +251,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->fE3BFakeButton2Sent = FALSE;
/* Send middle mouse button release */
- winMouseButtonsSendEvent(ButtonRelease, Button2);
+ winMouseButtonsSendEvent(FALSE, Button2);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->iE3BCachedPress == 0
@@ -324,7 +260,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
* Button was release, no button is cached,
* and there is no fake button 2 release is pending.
*/
- winMouseButtonsSendEvent(ButtonRelease, iButton);
+ winMouseButtonsSendEvent(FALSE, iButton);
}
return 0;
diff --git a/hw/xwin/winmsg.c b/hw/xwin/winmsg.c
index 56e7a097c..8aa8d9ed2 100644
--- a/hw/xwin/winmsg.c
+++ b/hw/xwin/winmsg.c
@@ -39,17 +39,6 @@
#include <stdarg.h>
void
-winVMsg(int, MessageType, int verb, const char *, va_list)
-_X_ATTRIBUTE_PRINTF(4, 0);
-
-void
-winVMsg(int scrnIndex, MessageType type, int verb, const char *format,
- va_list ap)
-{
- LogVMessageVerb(type, verb, format, ap);
-}
-
-void
winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
{
va_list ap;
@@ -60,16 +49,6 @@ winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
}
void
-winMsg(MessageType type, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- LogVMessageVerb(type, 1, format, ap);
- va_end(ap);
-}
-
-void
winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
...)
{
@@ -81,22 +60,22 @@ winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
}
void
-winMsgVerb(MessageType type, int verb, const char *format, ...)
+winErrorFVerb(int verb, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- LogVMessageVerb(type, verb, format, ap);
+ LogVMessageVerb(X_NONE, verb, format, ap);
va_end(ap);
}
void
-winErrorFVerb(int verb, const char *format, ...)
+winError(const char *format, ...)
{
va_list ap;
va_start(ap, format);
- LogVMessageVerb(X_NONE, verb, format, ap);
+ LogVMessageVerb(X_NONE, -1, format, ap);
va_end(ap);
}
diff --git a/hw/xwin/winmsg.h b/hw/xwin/winmsg.h
index b638f2cb3..25d887510 100644
--- a/hw/xwin/winmsg.h
+++ b/hw/xwin/winmsg.h
@@ -1,5 +1,3 @@
-#ifndef __WIN_MSG_H__
-#define __WIN_MSG_H__
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*
@@ -30,10 +28,17 @@
* Authors: Alexander Gottwald
*/
+#ifndef __WIN_MSG_H__
+#define __WIN_MSG_H__
+
+#include <X11/Xwindows.h>
+#include <X11/Xfuncproto.h>
+
/*
* Function prototypes
*/
+#ifdef XWIN_XF86CONFIG
void
winDrvMsgVerb(int scrnIndex,
MessageType type, int verb, const char *format, ...)
@@ -41,12 +46,10 @@ _X_ATTRIBUTE_PRINTF(4, 5);
void
winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
_X_ATTRIBUTE_PRINTF(3, 4);
-void
-winMsgVerb(MessageType type, int verb, const char *format, ...)
-_X_ATTRIBUTE_PRINTF(3, 4);
-void
-winMsg(MessageType type, const char *format, ...)
-_X_ATTRIBUTE_PRINTF(2, 3);
+#endif
+
+#define winMsg LogMessage
+
void
winDebug(const char *format, ...)
_X_ATTRIBUTE_PRINTF(1, 2);
@@ -57,6 +60,10 @@ _X_ATTRIBUTE_PRINTF(1, 2);
void
winErrorFVerb(int verb, const char *format, ...)
_X_ATTRIBUTE_PRINTF(2, 3);
+void
+winError(const char *format, ...)
+_X_ATTRIBUTE_PRINTF(1, 2);
+
void winW32Error(int verb, const char *message);
void winW32ErrorEx(int verb, const char *message, DWORD errorcode);
void winDebugWin32Message(const char *function, HWND hwnd, UINT message,
diff --git a/hw/xwin/winmultiwindowclass.h b/hw/xwin/winmultiwindowclass.h
index 3244f78e3..37ee9fb13 100644
--- a/hw/xwin/winmultiwindowclass.h
+++ b/hw/xwin/winmultiwindowclass.h
@@ -31,11 +31,24 @@
*/
/*
+ * The next block of definitions are for window manager properties that
+ * clients and applications use for communication.
+ */
+
+/*
* Structures
*/
+/*
+ * WM_HINTS structure
+ *
+ * NOTE: this structure represents the internal format stored in the property
+ * after it is marshalled by libX11, converting the flags field from an
+ * arch-dependent long to a 32-bit int.
+ */
+
typedef struct {
- long flags; /* marks which fields in this structure are defined */
+ int flags; /* marks which fields in this structure are defined */
Bool input; /* does this application rely on the window manager to
get keyboard input? */
int initial_state; /* see below */
@@ -59,11 +72,15 @@ typedef struct {
#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint|IconPositionHint|IconMaskHint|WindowGroupHint)
/*
- * new version containing base_width, base_height, and win_gravity fields;
+ * ICCCM 1.0 version containing base_width, base_height, and win_gravity fields;
* used with WM_NORMAL_HINTS.
+ *
+ * NOTE: this structure represents the internal format stored in the property
+ * after it is marshalled by libX11, converting the flags field from an
+ * arch-dependent long to a 32-bit int.
*/
typedef struct {
- long flags; /* marks which fields in this structure are defined */
+ int flags; /* marks which fields in this structure are defined */
int x, y; /* obsolete for new window mgrs, but clients */
int width, height; /* should set so old wm's don't mess up */
int min_width, min_height;
@@ -77,11 +94,6 @@ typedef struct {
int win_gravity; /* added by ICCCM version 1 */
} WinXSizeHints;
-/*
- * The next block of definitions are for window manager properties that
- * clients and applications use for communication.
- */
-
/* flags argument in size hints */
#define USPosition (1L << 0) /* user specified x, y */
#define USSize (1L << 1) /* user specified width, height */
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index 93d389d46..09b9b0412 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -32,528 +32,22 @@
#include <xwin-config.h>
#endif
-#ifndef WINVER
-#define WINVER 0x0500
-#endif
-
#include <X11/Xwindows.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#include <X11/Xlib-xcb.h>
#include "winresource.h"
#include "winprefs.h"
-#include "winmsg.h"
#include "winmultiwindowicons.h"
#include "winglobals.h"
+#include "wmutil/icon_convert.h"
+
/*
* global variables
*/
extern HINSTANCE g_hInstance;
/*
- * Scale an X icon ZPixmap into a Windoze icon bitmap
- */
-
-static void
-winScaleXImageToWindowsIcon(int iconSize,
- int effBPP,
- int stride, XImage * pixmap, unsigned char *image)
-{
- int row, column, effXBPP, effXDepth;
- unsigned char *outPtr;
- unsigned char *iconData = 0;
- int xStride;
- float factX, factY;
- int posX, posY;
- unsigned char *ptr;
- unsigned int zero;
- unsigned int color;
-
- effXBPP = pixmap->bits_per_pixel;
- if (pixmap->bits_per_pixel == 15)
- effXBPP = 16;
-
- effXDepth = pixmap->depth;
- if (pixmap->depth == 15)
- effXDepth = 16;
-
- xStride = pixmap->bytes_per_line;
- if (stride == 0 || xStride == 0) {
- ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. "
- "Bailing.\n");
- return;
- }
-
- /* Get icon data */
- iconData = (unsigned char *) pixmap->data;
-
- /* Keep aspect ratio */
- factX = ((float) pixmap->width) / ((float) iconSize);
- factY = ((float) pixmap->height) / ((float) iconSize);
- if (factX > factY)
- factY = factX;
- else
- factX = factY;
-
- /* Out-of-bounds, fill icon with zero */
- zero = 0;
-
- for (row = 0; row < iconSize; row++) {
- outPtr = image + stride * row;
- for (column = 0; column < iconSize; column++) {
- posX = factX * column;
- posY = factY * row;
-
- ptr = (unsigned char *) iconData + posY * xStride;
- if (effXBPP == 1) {
- ptr += posX / 8;
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
-
- if ((*ptr) & (1 << (posX & 7)))
- switch (effBPP) {
- case 32:
- *(outPtr++) = 0;
- case 24:
- *(outPtr++) = 0;
- case 16:
- *(outPtr++) = 0;
- case 8:
- *(outPtr++) = 0;
- break;
- case 1:
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- }
- else
- switch (effBPP) {
- case 32:
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 0;
- break;
- case 24:
- *(outPtr++) = 255;
- case 16:
- *(outPtr++) = 255;
- case 8:
- *(outPtr++) = 255;
- break;
- case 1:
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- break;
- }
- }
- else if (effXDepth == 24 || effXDepth == 32) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = (((*ptr) << 16)
- + ((*(ptr + 1)) << 8)
- + ((*(ptr + 2)) << 0));
- switch (effBPP) {
- case 32:
- *(outPtr++) = *(ptr++); /* b */
- *(outPtr++) = *(ptr++); /* g */
- *(outPtr++) = *(ptr++); /* r */
- *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
- break;
- case 24:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 16:
- color = ((((*ptr) >> 2) << 10)
- + (((*(ptr + 1)) >> 2) << 5)
- + (((*(ptr + 2)) >> 2)));
- *(outPtr++) = (color >> 8);
- *(outPtr++) = (color & 255);
- break;
- case 8:
- color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
- color /= 3;
- *(outPtr++) = color;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- }
- }
- else if (effXDepth == 16) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = ((*ptr) << 8) + (*(ptr + 1));
- switch (effBPP) {
- case 32:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- *(outPtr++) = 0; /* resvd */
- break;
- case 24:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- break;
- case 16:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 8:
- *(outPtr++) = (((color & 31)
- + ((color >> 5) & 31)
- + ((color >> 10) & 31)) / 3) << 2;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- } /* end switch(effbpp) */
- } /* end if effxbpp==16) */
- } /* end for column */
- } /* end for row */
-}
-
-static HICON
-NetWMToWinIconAlpha(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- HICON result;
- HDC hdc = GetDC(NULL);
- uint32_t *DIB_pixels;
- ICONINFO ii;
- BITMAPV4HEADER bmh = { sizeof(bmh) };
-
- /* Define an ARGB pixel format used for Color+Alpha icons */
- bmh.bV4Width = width;
- bmh.bV4Height = -height; /* Invert the image */
- bmh.bV4Planes = 1;
- bmh.bV4BitCount = 32;
- bmh.bV4V4Compression = BI_BITFIELDS;
- bmh.bV4AlphaMask = 0xFF000000;
- bmh.bV4RedMask = 0x00FF0000;
- bmh.bV4GreenMask = 0x0000FF00;
- bmh.bV4BlueMask = 0x000000FF;
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh,
- DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
- 0);
- ReleaseDC(NULL, hdc);
-
- if (!ii.hbmColor)
- return NULL;
-
- ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
- memcpy(DIB_pixels, pixels, height * width * 4);
-
- /* CreateIconIndirect() traditionally required DDBitmaps */
- /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
- /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
- return result;
-}
-
-static HICON
-NetWMToWinIconThreshold(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- int row, col;
- HICON result;
- ICONINFO ii;
-
- HDC hdc = GetDC(NULL);
- HDC xorDC = CreateCompatibleDC(hdc);
- HDC andDC = CreateCompatibleDC(hdc);
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
- ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
- ReleaseDC(NULL, hdc);
- SelectObject(xorDC, ii.hbmColor);
- SelectObject(andDC, ii.hbmMask);
-
- for (row = 0; row < height; row++) {
- for (col = 0; col < width; col++) {
- if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
- SetPixelV(xorDC, col, row,
- RGB(((char *) pixels)[2], ((char *) pixels)[1],
- ((char *) pixels)[0]));
- SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
- }
- else {
- SetPixelV(xorDC, col, row, RGB(0, 0, 0));
- SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
- }
- pixels++;
- }
- }
- DeleteDC(xorDC);
- DeleteDC(andDC);
-
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
- result);
- return result;
-}
-
-static HICON
-NetWMToWinIcon(int bpp, uint32_t * icon)
-{
- static Bool hasIconAlphaChannel = FALSE;
- static BOOL versionChecked = FALSE;
-
- if (!versionChecked) {
- OSVERSIONINFOEX osvi = { 0 };
- ULONGLONG dwlConditionMask = 0;
-
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- osvi.dwMajorVersion = 5;
- osvi.dwMinorVersion = 1;
-
- /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
- VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
- VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
- VER_GREATER_EQUAL);
- hasIconAlphaChannel =
- VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
- dwlConditionMask);
- versionChecked = TRUE;
-
- ErrorF("OS has icon alpha channel support: %s\n",
- hasIconAlphaChannel ? "yes" : "no");
- }
-
- if (hasIconAlphaChannel && (bpp == 32))
- return NetWMToWinIconAlpha(icon);
- else
- return NetWMToWinIconThreshold(icon);
-}
-
-/*
- * Attempt to create a custom icon from the WM_HINTS bitmaps
- */
-
-static
- HICON
-winXIconToHICON(Display * pDisplay, Window id, int iconSize)
-{
- unsigned char *mask, *image = NULL, *imageMask;
- unsigned char *dst, *src;
- int planes, bpp, i;
- unsigned int biggest_size = 0;
- HDC hDC;
- ICONINFO ii;
- XWMHints *hints;
- HICON hIcon = NULL;
- uint32_t *biggest_icon = NULL;
- static Atom _XA_NET_WM_ICON;
- static int generation;
- uint32_t *icon, *icon_data = NULL;
- unsigned long int size;
- unsigned long int type;
- int format;
- unsigned long int left;
-
- hDC = GetDC(GetDesktopWindow());
- planes = GetDeviceCaps(hDC, PLANES);
- bpp = GetDeviceCaps(hDC, BITSPIXEL);
- ReleaseDC(GetDesktopWindow(), hDC);
-
- /* Always prefer _NET_WM_ICON icons */
- if (generation != serverGeneration) {
- generation = serverGeneration;
- _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE);
- }
-
- if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON,
- 0, MAXINT, FALSE,
- AnyPropertyType, &type, &format, &size, &left,
- (unsigned char **) &icon_data) == Success) &&
- (icon_data != NULL)) {
- for (icon = icon_data; icon < &icon_data[size] && *icon;
- icon = &icon[icon[0] * icon[1] + 2]) {
- winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
-
- /* Icon data size will overflow an int and thus is bigger than the
- property can possibly be */
- if ((INT_MAX/icon[0]) < icon[1]) {
- winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
- break;
- }
-
- /* Icon data size is bigger than amount of data remaining */
- if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
- winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
- break;
- }
-
- /* Found an exact match to the size we require... */
- if (icon[0] == iconSize && icon[1] == iconSize) {
- winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
- iconSize, iconSize);
- hIcon = NetWMToWinIcon(bpp, icon);
- break;
- }
- /* Otherwise, find the biggest icon and let Windows scale the size */
- else if (biggest_size < icon[0]) {
- biggest_icon = icon;
- biggest_size = icon[0];
- }
- }
-
- if (!hIcon && biggest_icon) {
- winDebug
- ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
- biggest_icon[0], biggest_icon[1], iconSize, iconSize);
-
- hIcon = NetWMToWinIcon(bpp, biggest_icon);
- }
-
- XFree(icon_data);
- }
-
- if (!hIcon) {
- winDebug("winXIconToHICON: no suitable NetIcon\n");
-
- hints = XGetWMHints(pDisplay, id);
- if (hints) {
- winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
- hints->icon_pixmap);
-
- if (hints->icon_pixmap) {
- Window root;
- int x, y;
- unsigned int width, height, border_width, depth;
- XImage *xImageIcon;
- XImage *xImageMask = NULL;
-
- XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y,
- &width, &height, &border_width, &depth);
-
- xImageIcon =
- XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height,
- 0xFFFFFFFF, ZPixmap);
- winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
- xImageIcon);
-
- if (hints->icon_mask)
- xImageMask =
- XGetImage(pDisplay, hints->icon_mask, 0, 0, width,
- height, 0xFFFFFFFF, ZPixmap);
-
- if (xImageIcon) {
- int effBPP, stride, maskStride;
-
- /* 15 BPP is really 16BPP as far as we care */
- if (bpp == 15)
- effBPP = 16;
- else
- effBPP = bpp;
-
- /* Need 16-bit aligned rows for DDBitmaps */
- stride = ((iconSize * effBPP + 15) & (~15)) / 8;
-
- /* Mask is 1-bit deep */
- maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
-
- image = malloc(stride * iconSize);
- imageMask = malloc(stride * iconSize);
- mask = malloc(maskStride * iconSize);
-
- /* Default to a completely black mask */
- memset(imageMask, 0, stride * iconSize);
- memset(mask, 0, maskStride * iconSize);
-
- winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
- xImageIcon, image);
-
- if (xImageMask) {
- winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
- xImageMask, mask);
- winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
- xImageMask, imageMask);
- }
-
- /* Now we need to set all bits of the icon which are not masked */
- /* on to 0 because Color is really an XOR, not an OR function */
- dst = image;
- src = imageMask;
-
- for (i = 0; i < (stride * iconSize); i++)
- if ((*(src++)))
- *(dst++) = 0;
- else
- dst++;
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
-
- /* Create Win32 mask from pixmap shape */
- ii.hbmMask =
- CreateBitmap(iconSize, iconSize, planes, 1, mask);
-
- /* Create Win32 bitmap from pixmap */
- ii.hbmColor =
- CreateBitmap(iconSize, iconSize, planes, bpp, image);
-
- /* Merge Win32 mask and bitmap into icon */
- hIcon = CreateIconIndirect(&ii);
-
- /* Release Win32 mask and bitmap */
- DeleteObject(ii.hbmMask);
- DeleteObject(ii.hbmColor);
-
- /* Free X mask and bitmap */
- free(mask);
- free(image);
- free(imageMask);
-
- if (xImageMask)
- XDestroyImage(xImageMask);
-
- XDestroyImage(xImageIcon);
- }
- }
- XFree(hints);
- }
- }
- return hIcon;
-}
-
-/*
* Change the Windows window icon
*/
@@ -563,32 +57,46 @@ winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew)
{
HICON hIcon, hIconSmall = NULL, hIconOld;
- /* Start with the icon from preferences, if any */
- hIcon = hIconNew;
- hIconSmall = hIconNew;
+ if (hIconNew)
+ {
+ /* Start with the icon from preferences, if any */
+ hIcon = hIconNew;
+ hIconSmall = hIconNew;
+ }
+ else
+ {
+ /* If we still need an icon, try and get the icon from WM_HINTS */
+ xcb_connection_t *conn = XGetXCBConnection(pDisplay);
+
+ hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON));
+ hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON));
- /* If we still need an icon, try and get the icon from WM_HINTS */
- if (!hIcon)
- hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON));
- if (!hIconSmall)
- hIconSmall =
- winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON));
+ /* If we got the small, but not the large one swap them */
+ if (!hIcon && hIconSmall) {
+ hIcon = hIconSmall;
+ hIconSmall = NULL;
+ }
+ }
- /* If we got the small, but not the large one swap them */
- if (!hIcon && hIconSmall) {
- hIcon = hIconSmall;
- hIconSmall = NULL;
+ /* If we still need an icon, use the default one */
+ if (!hIcon) {
+ hIcon = g_hIconX;
+ hIconSmall = g_hSmallIconX;
}
- /* Set the large icon */
- hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
- /* Delete the old icon if its not the default */
- winDestroyIcon(hIconOld);
+ if (hIcon) {
+ /* Set the large icon */
+ hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+ /* Delete the old icon if its not the default */
+ winDestroyIcon(hIconOld);
+ }
- /* Same for the small icon */
- hIconOld =
- (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
- winDestroyIcon(hIconOld);
+ if (hIconSmall) {
+ /* Same for the small icon */
+ hIconOld =
+ (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
+ winDestroyIcon(hIconOld);
+ }
}
void
diff --git a/hw/xwin/winmultiwindowicons.h b/hw/xwin/winmultiwindowicons.h
index bf7f6eda7..5e0873ab9 100644
--- a/hw/xwin/winmultiwindowicons.h
+++ b/hw/xwin/winmultiwindowicons.h
@@ -27,8 +27,8 @@
#ifndef WINMULTIWINDOWICONS_H
#define WINMULTIWINDOWICONS_H
-void
- winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
+//void
+// winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
void
winInitGlobalIcons(void);
diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c
index f2e7907b8..d71dfb88d 100644
--- a/hw/xwin/winmultiwindowwindow.c
+++ b/hw/xwin/winmultiwindowwindow.c
@@ -35,9 +35,11 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "dixevents.h"
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
/*
* Prototypes for local functions
@@ -55,11 +57,27 @@ static void
static void
winFindWindow(void *value, XID id, void *cdata);
+static Bool
+isToplevelWindow(WindowPtr pWin)
+{
+ assert(pWin->parent); /* root window isn't expected here */
+
+ /* If the immediate parent is the root window, this is a top-level window */
+ if ((pWin->parent) && (pWin->parent->parent == NULL)) {
+ assert(pWin->parent == pWin->drawable.pScreen->root);
+ return TRUE;
+ }
+
+ /* otherwise, a child window */
+ return FALSE;
+}
+
static
void
winInitMultiWindowClass(void)
{
static wATOM atomXWinClass = 0;
+ static wATOM atomXWinChildClass = 0;
WNDCLASSEX wcx;
if (atomXWinClass == 0) {
@@ -83,11 +101,40 @@ winInitMultiWindowClass(void)
wcx.hIconSm = hIconSmall;
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
+ ErrorF("winInitMultiWindowClass - Creating class: %s\n",
+ WINDOW_CLASS_X);
#endif
atomXWinClass = RegisterClassEx(&wcx);
}
+
+ if (atomXWinChildClass == 0) {
+ HICON hIcon, hIconSmall;
+
+ /* Load the default icons */
+ winSelectIcons(&hIcon, &hIconSmall);
+
+ /* Setup our window class */
+ wcx.cbSize = sizeof(WNDCLASSEX);
+ wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
+ wcx.lpfnWndProc = winChildWindowProc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = g_hInstance;
+ wcx.hIcon = hIcon;
+ wcx.hCursor = 0;
+ wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = WINDOW_CLASS_X_CHILD;
+ wcx.hIconSm = hIconSmall;
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF("winInitMultiWindowClass - Creating class: %s\n",
+ WINDOW_CLASS_X_CHILD);
+#endif
+
+ atomXWinChildClass = RegisterClassEx(&wcx);
+ }
}
/*
@@ -202,6 +249,29 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y)
return fResult;
}
+ if (!isToplevelWindow(pWin)) {
+ POINT parentOrigin;
+
+ /* Get the X and Y location of the X window */
+ iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ /* Get the height and width of the X window */
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Convert screen coordinates into client area co-ordinates of the parent */
+ parentOrigin.x = 0;
+ parentOrigin.y = 0;
+ ClientToScreen(GetParent(hWnd), &parentOrigin);
+
+ MoveWindow(hWnd,
+ iX - parentOrigin.x, iY - parentOrigin.y, iWidth, iHeight,
+ TRUE);
+
+ return fResult;
+ }
+
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
@@ -470,12 +540,8 @@ winRestackWindowMultiWindow(WindowPtr pWin, WindowPtr pOldNextSib)
#endif
}
-/*
- * winCreateWindowsWindow - Create a Windows window associated with an X window
- */
-
-void
-winCreateWindowsWindow(WindowPtr pWin)
+static void
+winCreateWindowsTopLevelWindow(WindowPtr pWin)
{
int iX, iY;
int iWidth;
@@ -502,19 +568,23 @@ winCreateWindowsWindow(WindowPtr pWin)
iHeight = pWin->drawable.height;
/* If it's an InputOutput window, and so is going to end up being made visible,
- make sure the window actually ends up somewhere where it will be visible */
- if (pWin->drawable.class != InputOnly) {
- if ((iX < GetSystemMetrics(SM_XVIRTUALSCREEN)) ||
- (iX > GetSystemMetrics(SM_CXVIRTUALSCREEN)))
- iX = CW_USEDEFAULT;
+ make sure the window actually ends up somewhere where it will be visible
- if ((iY < GetSystemMetrics(SM_YVIRTUALSCREEN)) ||
- (iY > GetSystemMetrics(SM_CYVIRTUALSCREEN)))
- iY = CW_USEDEFAULT;
+ To handle arrangements of monitors which form a non-rectangular virtual
+ desktop, check if the window will end up with it's top-left corner on any
+ monitor
+ */
+ if (pWin->drawable.class != InputOnly) {
+ POINT pt = { iX, iY };
+ if (MonitorFromPoint(pt, MONITOR_DEFAULTTONULL) == NULL)
+ {
+ iX = CW_USEDEFAULT;
+ iY = CW_USEDEFAULT;
+ }
}
- winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX,
- iY);
+ winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth,
+ iHeight, iX, iY);
if (winMultiWindowGetTransientFor(pWin, &daddyId)) {
if (daddyId) {
@@ -524,17 +594,33 @@ winCreateWindowsWindow(WindowPtr pWin)
}
}
else {
- /* Default positions if none specified */
- if (!winMultiWindowGetWMNormalHints(pWin, &hints))
- hints.flags = 0;
- if (!(hints.flags & (USPosition | PPosition)) &&
- !pWin->overrideRedirect) {
- iX = CW_USEDEFAULT;
- iY = CW_USEDEFAULT;
+ if (!pWin->overrideRedirect) {
+ /* Default positions if none specified */
+ if (!winMultiWindowGetWMNormalHints(pWin, &hints))
+ hints.flags = 0;
+
+ if ((hints.flags & USPosition) ||
+ ((hints.flags & PPosition) &&
+ ((pWin->drawable.x - pWin->borderWidth != 0) ||
+ (pWin->drawable.y - pWin->borderWidth != 0)))) {
+ /*
+ Always respect user specified position, respect program
+ specified position if it's not the origin
+ */
+ }
+ else {
+ /* Use default position */
+ iX = CW_USEDEFAULT;
+ iY = CW_USEDEFAULT;
+ }
}
}
- /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */
+ winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth,
+ iHeight, iX, iY);
+
+ /* Create the window */
+ /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */
/* CW_USEDEFAULT, change back to popup after creation */
dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
dwExStyle = WS_EX_TOOLWINDOW;
@@ -572,11 +658,14 @@ winCreateWindowsWindow(WindowPtr pWin)
GetModuleHandle(NULL), /* Instance handle */
pWin); /* ScreenPrivates */
if (hWnd == NULL) {
- ErrorF("winCreateWindowsWindow - CreateWindowExA () failed: %d\n",
- (int) GetLastError());
+ ErrorF
+ ("winCreateWindowsTopLevelWindow - CreateWindowExA () failed: %d\n",
+ (int) GetLastError());
}
pWinPriv->hWnd = hWnd;
+ winDebug("winCreateWindowsTopLevelWindow - hwnd 0x%08x\n", hWnd);
+
/* Change style back to popup, already placed... */
SetWindowLongPtr(hWnd, GWL_STYLE,
WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
@@ -602,6 +691,107 @@ winCreateWindowsWindow(WindowPtr pWin)
(*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin);
}
+static void
+winCreateWindowsChildWindow(WindowPtr pWin)
+{
+ int iX, iY, iWidth, iHeight;
+ HWND hWnd;
+ WindowPtr pParent = pWin->parent;
+ DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED;
+ DWORD dwExStyle = WS_EX_TRANSPARENT;
+
+ /*
+ WS_DISABLED means child window never gains the input focus, so only the
+ top-level window needs deal with passing input to the X server
+
+ WS_EX_TRANSPARENT ensures that the contents of the top-level
+ Windows window (which will contain all non-OpenGL drawing for the hierarchy)
+ can be seen through any intermediate child windows which have nothing
+ drawn to them
+ */
+ winPrivWinPtr pParentPriv, pWinPriv;
+
+ winDebug("winCreateWindowsChildWindow - pWin:%08x XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ winInitMultiWindowClass();
+
+ assert(pParent);
+
+ pParentPriv = winGetWindowPriv(pParent);
+ pWinPriv = winGetWindowPriv(pWin);
+
+ iX = pWin->drawable.x - pParent->drawable.x;
+ iY = pWin->drawable.y - pParent->drawable.y;
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ winDebug
+ ("winCreateWindowsChildWindow - parent pWin:%08x XID:0x%08x hWnd:0x%08x\n",
+ pParent, pParent->drawable.id, pParentPriv->hWnd);
+ winDebug("winCreateWindowsChildWindow - %dx%d @ %dx%d\n", iWidth, iHeight,
+ iX, iY);
+
+ /* Create the window */
+ hWnd = CreateWindowExA(dwExStyle, /* Extended styles */
+ WINDOW_CLASS_X_CHILD, /* Class name */
+ WINDOW_TITLE_X, /* Window name */
+ dwStyle, /* Styles */
+ iX, /* Horizontal position */
+ iY, /* Vertical position */
+ iWidth, /* Right edge */
+ iHeight, /* Bottom edge */
+ pParentPriv->hWnd, /* parent window */
+ (HMENU) NULL, /* No menu */
+ GetModuleHandle(NULL), /* Instance handle */
+ pWin); /* ScreenPrivates */
+ if (hWnd == NULL) {
+ ErrorF("winCreateWindowsChildWindow - CreateWindowExA () failed: %d\n",
+ (int) GetLastError());
+ }
+ winDebug("winCreateWindowsChildWindow - hwnd 0x%08x\n", hWnd);
+ pWinPriv->hWnd = hWnd;
+
+ SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin));
+}
+
+/*
+ * winCreateWindowsWindow - Create a Windows window associated with an X window
+ */
+
+void
+winCreateWindowsWindow(WindowPtr pWin)
+{
+ winDebug("winCreateWindowsWindow - pWin:%08x XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ if (isToplevelWindow(pWin)) {
+ winCreateWindowsTopLevelWindow(pWin);
+ }
+ else {
+ winCreateWindowsChildWindow(pWin);
+ }
+}
+
+static int
+winDestroyChildWindowsWindow(WindowPtr pWin, void *data)
+{
+ winWindowPriv(pWin);
+
+ winDebug("winDestroyChildWindowsWindow - pWin:%08x XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ /* Null our handle to the Window so referencing it will cause an error */
+ pWinPriv->hWnd = NULL;
+
+#ifdef XWIN_GLX_WINDOWS
+ /* No longer note WGL used on this window */
+ pWinPriv->fWglUsed = FALSE;
+#endif
+
+ return WT_WALKCHILDREN; /* continue enumeration */
+}
+
Bool winInDestroyWindowsWindow = FALSE;
/*
@@ -617,6 +807,7 @@ winDestroyWindowsWindow(WindowPtr pWin)
BOOL oldstate = winInDestroyWindowsWindow;
HICON hIcon;
HICON hIconSm;
+ HWND hWnd;
winDebug("winDestroyWindowsWindow - pWin:%08x XID:0x%x \n", pWin,
pWin->drawable.id);
@@ -631,21 +822,20 @@ winDestroyWindowsWindow(WindowPtr pWin)
hIcon = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0);
hIconSm = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0);
- /* Destroy the Windows window */
- DestroyWindow(pWinPriv->hWnd);
+ hWnd = pWinPriv->hWnd;
- /* Null our handle to the Window so referencing it will cause an error */
- pWinPriv->hWnd = NULL;
+ /* DestroyWindow() implicitly destroys all child windows,
+ so first walk over the child tree of this window, clearing
+ any hWnds */
+ TraverseTree(pWin, winDestroyChildWindowsWindow, 0);
+
+ /* Destroy the Windows window */
+ DestroyWindow(hWnd);
/* Destroy any icons we created for this window */
winDestroyIcon(hIcon);
winDestroyIcon(hIconSm);
-#ifdef XWIN_GLX_WINDOWS
- /* No longer note WGL used on this window */
- pWinPriv->fWglUsed = FALSE;
-#endif
-
/* Process all messages on our queue */
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (g_hDlgDepthChange == 0 || !IsDialogMessage(g_hDlgDepthChange, &msg)) {
@@ -667,29 +857,58 @@ static void
winUpdateWindowsWindow(WindowPtr pWin)
{
winWindowPriv(pWin);
- HWND hWnd = pWinPriv->hWnd;
#if CYGMULTIWINDOW_DEBUG
ErrorF("winUpdateWindowsWindow\n");
#endif
- /* Check if the Windows window's parents have been destroyed */
- if (pWin->parent != NULL && pWin->parent->parent == NULL && pWin->mapped) {
- /* Create the Windows window if it has been destroyed */
- if (hWnd == NULL) {
- winCreateWindowsWindow(pWin);
- assert(pWinPriv->hWnd != NULL);
+ /* Ignore the root window */
+ if (pWin->parent == NULL)
+ return;
+
+ /* If it's mapped */
+ if (pWin->mapped) {
+ /* If it's a top-level window */
+ if (isToplevelWindow(pWin)) {
+ /* Create the Windows window if needed */
+ if (pWinPriv->hWnd == NULL) {
+ winCreateWindowsWindow(pWin);
+ assert(pWinPriv->hWnd != NULL);
+ }
+
+ /* Display the window without activating it */
+ if (pWin->drawable.class != InputOnly)
+ ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE);
+
+ }
+ /* It's not a top-level window, but we created a window for GLX */
+ else if (pWinPriv->hWnd) {
+ winPrivWinPtr pParentPriv = winGetWindowPriv(pWin->parent);
+
+ /* XXX: This really belongs in winReparentWindow ??? */
+ /* XXX: this assumes parent window has been made to exist */
+ assert(pParentPriv->hWnd);
+
+ /* Ensure we have the correct parent and position if reparented */
+ SetParent(pWinPriv->hWnd, pParentPriv->hWnd);
+ SetWindowPos(pWinPriv->hWnd, NULL,
+ pWin->drawable.x - pWin->parent->drawable.x,
+ pWin->drawable.y - pWin->parent->drawable.y, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
- /* Display the window without activating it */
- if (pWin->drawable.class != InputOnly)
- ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE);
+ /* If it's top level, or a GLX window which has already been created getting mapped, show it */
+ if (pWinPriv->hWnd != NULL) {
+ /* Display the window without activating it */
+ if (pWin->drawable.class != InputOnly)
+ ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE);
- /* Send first paint message */
- UpdateWindow(pWinPriv->hWnd);
+ /* Send first paint message */
+ UpdateWindow(pWinPriv->hWnd);
+ }
}
- else if (hWnd != NULL) {
- /* Destroy the Windows window if its parents are destroyed */
+ else if (pWinPriv->hWnd != NULL) {
+ /* If it's been reparented to an unmapped window when previously mapped, destroy the Windows window */
winDestroyWindowsWindow(pWin);
assert(pWinPriv->hWnd == NULL);
}
@@ -926,6 +1145,14 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd)
ErrorF("winAdjustXWindow\n");
#endif
+ if (!isToplevelWindow(pWin)) {
+#if 1
+ ErrorF
+ ("winAdjustXWindow - immediately return because not a top-level window\n");
+#endif
+ return 0;
+ }
+
if (IsIconic(hwnd)) {
#if CYGWINDOWING_DEBUG
ErrorF("\timmediately return because the window is iconized\n");
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 618e38121..615786af9 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -30,10 +30,24 @@
* Colin Harrison
*/
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
/* X headers */
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -48,7 +62,6 @@
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
-#include <X11/Xlocale.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
@@ -58,9 +71,9 @@
#include "winwindow.h"
#include "winprefs.h"
#include "window.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
#include "winglobals.h"
+#include "winmultiwindowicons.h"
+#include "windisplay.h"
#ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h>
@@ -77,6 +90,9 @@
extern void winDebug(const char *format, ...);
extern void winReshapeMultiWindow(WindowPtr pWin);
extern void winUpdateRgnMultiWindow(WindowPtr pWin);
+extern void winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
+extern void winSetAuthorization(void);
+extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
#ifndef CYGDEBUG
#define CYGDEBUG NO
@@ -172,6 +188,9 @@ static int
static int
winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay);
+static void
+winMultiWindowThreadExit(void *arg);
+
static int
winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -189,10 +208,10 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
Bool fAllowOtherWM);
static void
- winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle);
+ winApplyUrgency(Display * pDisplay, Window iWindow, HWND hWnd);
-void
- winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
+static void
+ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle);
/*
* Local globals
@@ -527,6 +546,7 @@ SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData)
XEvent e;
/* Prepare the X event structure */
+ memset(&e, 0, sizeof(e));
e.type = ClientMessage;
e.xclient.window = iWin;
e.xclient.message_type = atmType;
@@ -692,6 +712,9 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow)
winShowWindowOnTaskbar(hWnd,
(GetWindowLongPtr(hWnd, GWL_EXSTYLE) &
WS_EX_APPWINDOW) ? TRUE : FALSE);
+
+ /* Check urgency hint */
+ winApplyUrgency(pWMInfo->pDisplay, iWindow, hWnd);
}
#if 0
@@ -745,6 +768,8 @@ winMultiWindowWMProc(void *pArg)
WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
/* Initialize the Window Manager */
winInitMultiWindowWM(pWMInfo, pProcArg);
@@ -840,8 +865,8 @@ winMultiWindowWMProc(void *pArg)
PropModeReplace,
(unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4);
UpdateName(pWMInfo, pNode->msg.iWindow);
- UpdateIcon(pWMInfo, pNode->msg.iWindow);
UpdateStyle(pWMInfo, pNode->msg.iWindow);
+ UpdateIcon(pWMInfo, pNode->msg.iWindow);
/* Reshape */
@@ -972,6 +997,9 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+
+ pthread_cleanup_pop(0);
+
return NULL;
}
@@ -995,6 +1023,8 @@ winMultiWindowXMsgProc(void *pArg)
int iReturn;
XIconSize *xis;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
winDebug("winMultiWindowXMsgProc - Hello\n");
/* Check that argument pointer is not invalid */
@@ -1015,17 +1045,6 @@ winMultiWindowXMsgProc(void *pArg)
ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
- /* Allow multiple threads to access Xlib */
- if (XInitThreads() == 0) {
- ErrorF("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n");
- pthread_exit(NULL);
- }
-
- /* See if X supports the current locale */
- if (XSupportsLocale() == False) {
- ErrorF("winMultiWindowXMsgProc - Warning: locale not supported by X\n");
- }
-
/* Release the server started mutex */
pthread_mutex_unlock(pProcArg->ppmServerStarted);
@@ -1053,8 +1072,7 @@ winMultiWindowXMsgProc(void *pArg)
}
/* Setup the display connection string x */
- snprintf(pszDisplay,
- 512, "127.0.0.1:%s.%d", display, (int) pProcArg->dwScreen);
+ winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
/* Print the display connection string */
ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
@@ -1109,7 +1127,7 @@ winMultiWindowXMsgProc(void *pArg)
xis->max_width = xis->max_height = 48;
xis->width_inc = xis->height_inc = 16;
XSetIconSizes(pProcArg->pDisplay,
- RootWindow(pProcArg->pDisplay, pProcArg->dwScreen),
+ XRootWindow(pProcArg->pDisplay, pProcArg->dwScreen),
xis, 1);
XFree(xis);
}
@@ -1248,6 +1266,10 @@ winMultiWindowXMsgProc(void *pArg)
}
}
else if (event.type == PropertyNotify) {
+ char *atomName =
+ XGetAtomName(pProcArg->pDisplay, event.xproperty.atom);
+ winDebug("winMultiWindowXMsgProc: PropertyNotify %s\n", atomName);
+ XFree(atomName);
if (event.xproperty.atom == atmWmName) {
memset(&msg, 0, sizeof(msg));
@@ -1302,7 +1324,7 @@ winMultiWindowXMsgProc(void *pArg)
}
XCloseDisplay(pProcArg->pDisplay);
- pthread_exit(NULL);
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -1408,17 +1430,6 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
ErrorF("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
- /* Allow multiple threads to access Xlib */
- if (XInitThreads() == 0) {
- ErrorF("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n");
- pthread_exit(NULL);
- }
-
- /* See if X supports the current locale */
- if (XSupportsLocale() == False) {
- ErrorF("winInitMultiWindowWM - Warning: Locale not supported by X.\n");
- }
-
/* Release the server started mutex */
pthread_mutex_unlock(pProcArg->ppmServerStarted);
@@ -1446,8 +1457,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
}
/* Setup the display connection string x */
- snprintf(pszDisplay,
- 512, "127.0.0.1:%s.%d", display, (int) pProcArg->dwScreen);
+ winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
/* Print the display connection string */
ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
@@ -1497,7 +1507,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
if (cursor) {
XDefineCursor(pWMInfo->pDisplay,
- DefaultRootWindow(pWMInfo->pDisplay), cursor);
+ XDefaultRootWindow(pWMInfo->pDisplay), cursor);
XFreeCursor(pWMInfo->pDisplay, cursor);
}
}
@@ -1606,6 +1616,17 @@ winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay)
}
/*
+ * winMultiWindowThreadExit - Thread exit handler
+ */
+
+static void
+winMultiWindowThreadExit(void *arg)
+{
+ /* multiwindow client thread has exited, stop server as well */
+ raise(SIGTERM);
+}
+
+/*
* Catch RedirectError to detect other window manager running
*/
@@ -1630,7 +1651,7 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
*/
redirectError = FALSE;
XSetErrorHandler(winRedirectErrorHandler);
- XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
+ XSelectInput(pDisplay, XRootWindow(pDisplay, dwScreen),
ResizeRedirectMask | SubstructureRedirectMask |
ButtonPressMask);
XSync(pDisplay, 0);
@@ -1642,7 +1663,7 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
If other WMs are not allowed, also select one of the events which only one client
at a time is allowed to select, so other window managers won't start...
*/
- XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
+ XSelectInput(pDisplay, XRootWindow(pDisplay, dwScreen),
SubstructureNotifyMask | (!fAllowOtherWM ? ButtonPressMask :
0));
XSync(pDisplay, 0);
@@ -1660,6 +1681,40 @@ winDeinitMultiWindowWM(void)
g_shutdown = TRUE;
}
+static void
+winApplyUrgency(Display * pDisplay, Window iWindow, HWND hWnd)
+{
+ XWMHints *hints = XGetWMHints(pDisplay, iWindow);
+
+ if (hints) {
+ FLASHWINFO fwi;
+
+ fwi.cbSize = sizeof(FLASHWINFO);
+ fwi.hwnd = hWnd;
+
+ winDebug("winApplyUrgency: window 0x%08x has urgency hint %s\n",
+ iWindow, (hints->flags & XUrgencyHint) ? "on" : "off");
+
+ if (hints->flags & XUrgencyHint) {
+ DWORD count = 3;
+
+ SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &count, 0);
+ fwi.dwFlags = FLASHW_TRAY;
+ fwi.uCount = count;
+ fwi.dwTimeout = 0;
+ }
+ else {
+ fwi.dwFlags = FLASHW_STOP;
+ fwi.uCount = 0;
+ fwi.dwTimeout = 0;
+ }
+
+ FlashWindowEx(&fwi);
+
+ XFree(hints);
+ }
+}
+
/* Windows window styles */
#define HINT_NOFRAME (1L<<0)
#define HINT_BORDER (1L<<1)
@@ -1678,8 +1733,8 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
{
static Atom windowState, motif_wm_hints, windowType;
static Atom hiddenState, fullscreenState, belowState, aboveState,
- skiptaskbarState;
- static Atom dockWindow;
+ skiptaskbarState, vertMaxState, horzMaxState;
+ static Atom dockWindow, splashWindow;
static int generation;
Atom type, *pAtom = NULL;
int format;
@@ -1703,14 +1758,20 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False);
aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False);
dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ splashWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_SPLASH", False);
skiptaskbarState =
XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False);
+ vertMaxState = XInternAtom(pDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ horzMaxState = XInternAtom(pDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
}
if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
MAXINT, False, XA_ATOM, &type, &format,
&nitems, &left,
(unsigned char **) &pAtom) == Success) {
+ Bool verMax = FALSE;
+ Bool horMax = FALSE;
+
if (pAtom ) {
unsigned long i;
@@ -1725,8 +1786,15 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
*zstyle = HWND_BOTTOM;
else if (pAtom[i] == aboveState)
*zstyle = HWND_TOPMOST;
+ if (pAtom[i] == vertMaxState)
+ verMax = TRUE;
+ if (pAtom[i] == horzMaxState)
+ horMax = TRUE;
}
+ if (verMax && horMax)
+ maxmin |= HINT_MAX;
+
XFree(pAtom);
}
}
@@ -1739,7 +1807,7 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
if (mwm_hint && nitems == PropMwmHintsElements &&
(mwm_hint->flags & MwmHintsDecorations)) {
if (!mwm_hint->decorations)
- hint |= HINT_NOFRAME;
+ hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
else if (!(mwm_hint->decorations & MwmDecorAll)) {
if (mwm_hint->decorations & MwmDecorBorder)
hint |= HINT_BORDER;
@@ -1776,6 +1844,10 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */
*zstyle = HWND_TOPMOST;
}
+ else if (*pAtom == splashWindow) {
+ hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
+ *zstyle = HWND_TOPMOST;
+ }
}
if (pAtom)
XFree(pAtom);
@@ -1786,9 +1858,12 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
long supplied;
if (normal_hint &&
- (XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied) ==
- Success)) {
+ XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied)) {
if (normal_hint->flags & PMaxSize) {
+ /* Ensure default style is used if no other styling */
+ if (!(hint & ~HINT_SKIPTASKBAR))
+ hint |= HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION;
+
/* Not maximizable if a maximum size is specified */
hint |= HINT_NOMAXIMIZE;
@@ -1916,57 +1991,3 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n",
iWindow, hint, style, exStyle);
}
-
-void
-winUpdateWindowPosition(HWND hWnd, HWND * zstyle)
-{
- int iX, iY, iWidth, iHeight;
- int iDx, iDy;
- RECT rcNew;
- WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
- DrawablePtr pDraw = NULL;
-
- if (!pWin)
- return;
- pDraw = &pWin->drawable;
- if (!pDraw)
- return;
-
- /* Get the X and Y location of the X window */
- iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
-
- /* Get the height and width of the X window */
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* Setup a rectangle with the X window position and size */
- SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
-
- winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
- GetWindowLongPtr(hWnd, GWL_EXSTYLE));
-
- /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
- if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
- iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
- rcNew.left += iDx;
- rcNew.right += iDx;
- }
-
- if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
- iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
- rcNew.top += iDy;
- rcNew.bottom += iDy;
- }
-
- winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- /* Position the Windows window */
- SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
-
-}
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 17823baf2..56a770de4 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -41,6 +41,7 @@
#include "winprefs.h"
#include "winmsg.h"
#include "inputstr.h"
+#include "wmutil/keyboard.h"
extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
@@ -1045,6 +1046,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!hasEnteredSizeMove) {
/* Adjust the X Window to the moved Windows window */
winAdjustXWindow(pWin, hwnd);
+ if (wParam == SIZE_MINIMIZED)
+ winReorderWindowsMultiWindow();
}
/* else: wait for WM_EXITSIZEMOVE */
return 0; /* end of WM_SIZE handler */
@@ -1156,3 +1159,95 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winReorderWindowsMultiWindow();
return ret;
}
+
+/*
+ * winChildWindowProc - Window procedure for all top-level Windows windows.
+ */
+
+LRESULT CALLBACK
+winChildWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+#if CYGDEBUG
+ winDebugWin32Message("winChildWindowProc", hwnd, message, wParam, lParam);
+#endif
+
+ switch (message) {
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_PAINT:
+ /*
+ We don't have the bits to draw into the window, they went straight into the OpenGL
+ surface
+
+ XXX: For now, just leave it alone, but ideally we want to send an expose event to
+ the window so it really redraws the affected region...
+ */
+ {
+ PAINTSTRUCT ps;
+ HDC hdcUpdate;
+
+ hdcUpdate = BeginPaint(hwnd, &ps);
+ ValidateRect(hwnd, &(ps.rcPaint));
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+ /* XXX: this is exactly what DefWindowProc does? */
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+void
+winUpdateWindowPosition(HWND hWnd, HWND * zstyle)
+{
+ int iX, iY, iWidth, iHeight;
+ int iDx, iDy;
+ RECT rcNew;
+ WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
+ DrawablePtr pDraw = NULL;
+
+ if (!pWin)
+ return;
+ pDraw = &pWin->drawable;
+ if (!pDraw)
+ return;
+
+ /* Get the X and Y location of the X window */
+ iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ /* Get the height and width of the X window */
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Setup a rectangle with the X window position and size */
+ SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
+
+ winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
+ rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
+
+ AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
+ GetWindowLongPtr(hWnd, GWL_EXSTYLE));
+
+ /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
+ if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
+ iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
+ rcNew.left += iDx;
+ rcNew.right += iDx;
+ }
+
+ if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
+ iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
+ rcNew.top += iDy;
+ rcNew.bottom += iDy;
+ }
+
+ winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
+ rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
+
+ /* Position the Windows window */
+ SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
+ rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
+
+}
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c
index f386facdd..3f25362d0 100644
--- a/hw/xwin/winprefs.c
+++ b/hw/xwin/winprefs.c
@@ -37,6 +37,8 @@
#include <stdlib.h>
#ifdef __CYGWIN__
#include <sys/resource.h>
+#include <sys/wait.h>
+#include <pthread.h>
#endif
#include "win.h"
@@ -44,7 +46,9 @@
#include <shellapi.h>
#include "winprefs.h"
+#include "windisplay.h"
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
/* Where will the custom menu commands start counting from? */
#define STARTMENUID WM_USER
@@ -296,6 +300,110 @@ HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu)
}
+#ifdef __CYGWIN__
+static void
+LogLineFromFd(int fd, const char *fdname, int pid)
+{
+#define BUFSIZE 512 /* must be less than internal buffer size used in LogVWrite */
+ char buf[BUFSIZE];
+ char *bufptr = buf;
+
+ /* read from fd until eof, newline or our buffer is full */
+ while ((read(fd, bufptr, 1) > 0) && (bufptr < &(buf[BUFSIZE - 1]))) {
+ if (*bufptr == '\n')
+ break;
+ bufptr++;
+ }
+
+ /* null terminate and log */
+ *bufptr = 0;
+ if (strlen(buf))
+ ErrorF("(pid %d %s) %s\n", pid, fdname, buf);
+}
+
+static void *
+ExecAndLogThread(void *cmd)
+{
+ int pid;
+ int stdout_filedes[2];
+ int stderr_filedes[2];
+ int status;
+
+ /* Create a pair of pipes */
+ pipe(stdout_filedes);
+ pipe(stderr_filedes);
+
+ switch (pid = fork()) {
+ case 0: /* child */
+ {
+ struct rlimit rl;
+ unsigned int fd;
+
+ /* dup write end of pipes onto stderr and stdout */
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ dup2(stdout_filedes[1], STDOUT_FILENO);
+ dup2(stderr_filedes[1], STDERR_FILENO);
+
+ /* Close any open descriptors except for STD* */
+ getrlimit(RLIMIT_NOFILE, &rl);
+ for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
+ close(fd);
+
+ /* Disassociate any TTYs */
+ setsid();
+
+ execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
+ perror("execl failed");
+ exit(127);
+ }
+ break;
+
+ default: /* parent */
+ {
+ close(stdout_filedes[1]);
+ close(stderr_filedes[1]);
+
+ ErrorF("executing '%s', pid %d\n", (char *) cmd, pid);
+
+ /* read from pipes, write to log, until both are closed */
+ while (TRUE) {
+ fd_set readfds, errorfds;
+ int nfds = max(stdout_filedes[0], stderr_filedes[0]) + 1;
+
+ FD_ZERO(&readfds);
+ FD_SET(stdout_filedes[0], &readfds);
+ FD_SET(stderr_filedes[0], &readfds);
+ errorfds = readfds;
+
+ if (select(nfds, &readfds, NULL, &errorfds, NULL) > 0) {
+ if (FD_ISSET(stdout_filedes[0], &readfds))
+ LogLineFromFd(stdout_filedes[0], "stdout", pid);
+ if (FD_ISSET(stderr_filedes[0], &readfds))
+ LogLineFromFd(stderr_filedes[0], "stderr", pid);
+
+ if (FD_ISSET(stdout_filedes[0], &errorfds) &&
+ FD_ISSET(stderr_filedes[0], &errorfds))
+ break;
+ }
+ else {
+ break;
+ }
+ }
+
+ waitpid(pid, &status, 0);
+ }
+ break;
+
+ case -1: /* error */
+ ErrorF("fork() to run command failed\n");
+ }
+
+ return (void *) (intptr_t) status;
+}
+#endif
+
/*
* Searches for the custom WM_COMMAND command ID and performs action.
* Return TRUE if command is proccessed, FALSE otherwise.
@@ -318,24 +426,17 @@ HandleCustomWM_COMMAND(HWND hwnd, int command)
switch (m->menuItem[j].cmd) {
#ifdef __CYGWIN__
case CMD_EXEC:
- if (fork() == 0) {
- struct rlimit rl;
- int fd;
-
- /* Close any open descriptors except for STD* */
- getrlimit(RLIMIT_NOFILE, &rl);
- for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
- close(fd);
-
- /* Disassociate any TTYs */
- setsid();
+ {
+ pthread_t t;
- execl("/bin/sh",
- "/bin/sh", "-c", m->menuItem[j].param, NULL);
- exit(0);
- }
+ if (!pthread_create
+ (&t, NULL, ExecAndLogThread, m->menuItem[j].param))
+ pthread_detach(t);
else
- return TRUE;
+ ErrorF
+ ("Creating command output logging thread failed\n");
+ }
+ return TRUE;
break;
#else
case CMD_EXEC:
@@ -636,11 +737,17 @@ winPrefsLoadPreferences(char *path)
"MENU rmenu {\n"
" \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n"
" \"Launch xterm\" EXEC xterm\n"
- " \"Load .XWinrc\" RELOAD\n"
+ " SEPARATOR\n"
+ " FAQ EXEC \"cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html\"\n"
+ " \"User's Guide\" EXEC \"cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html\"\n"
+ " SEPARATOR\n"
+ " \"Reload .XWinrc\" RELOAD\n"
" SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n";
path = "built-in default";
prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r");
+
+
}
#endif
@@ -671,7 +778,7 @@ LoadPreferences(void)
char *home;
char fname[PATH_MAX + NAME_MAX + 2];
char szDisplay[512];
- char *szEnvDisplay;
+ char *szEnvDisplay, *szEnvLogFile;
int i, j;
char param[PARAM_MAX + 1];
char *srcParam, *dstParam;
@@ -712,15 +819,19 @@ LoadPreferences(void)
/* Setup a DISPLAY environment variable, need to allocate on heap */
/* because putenv doesn't copy the argument... */
- snprintf(szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display);
- szEnvDisplay = (char *) (malloc(strlen(szDisplay) + 1));
+ winGetDisplayName(szDisplay, 0);
+ szEnvDisplay = (char *) (malloc(strlen(szDisplay) + strlen("DISPLAY=") + 1));
if (szEnvDisplay) {
- strcpy(szEnvDisplay, szDisplay);
+ snprintf(szEnvDisplay, 512, "DISPLAY=%s", szDisplay);
putenv(szEnvDisplay);
}
+ /* Setup XWINLOGFILE environment variable */
+ szEnvLogFile = (char *) (malloc(strlen(g_pszLogFile) + strlen("XWINLOGFILE=") + 1));
+ snprintf(szEnvLogFile, 512, "XWINLOGFILE=%s", g_pszLogFile);
+ putenv(szEnvLogFile);
+
/* Replace any "%display%" in menu commands with display string */
- snprintf(szDisplay, 512, "127.0.0.1:%s.0", display);
for (i = 0; i < pref.menuItems; i++) {
for (j = 0; j < pref.menu[i].menuItems; j++) {
if (pref.menu[i].menuItem[j].cmd == CMD_EXEC) {
diff --git a/hw/xwin/winprefs.h b/hw/xwin/winprefs.h
index 8f4eb0807..702e5897d 100644
--- a/hw/xwin/winprefs.h
+++ b/hw/xwin/winprefs.h
@@ -34,9 +34,6 @@
/* Need Bool */
#include <X11/Xdefs.h>
-/* Need TRUE */
-#include "misc.h"
-
/* Need to know how long paths can be... */
#include <limits.h>
/* Xwindows redefines PATH_MAX to at least 1024 */
diff --git a/hw/xwin/winprefslex.l b/hw/xwin/winprefslex.l
index fd13edc05..7533bd35b 100644
--- a/hw/xwin/winprefslex.l
+++ b/hw/xwin/winprefslex.l
@@ -92,6 +92,12 @@ RELOAD { return RELOAD; }
TRAYICON { return TRAYICON; }
FORCEEXIT { return FORCEEXIT; }
SILENTEXIT { return SILENTEXIT; }
+DPI { return DPI; }
+XKBLAYOUT { return XKBLAYOUT; }
+XKBMODEL { return XKBMODEL; }
+XKBOPTIONS { return XKBOPTIONS; }
+XKBRULES { return XKBRULES; }
+XKBVARIANT { return XKBVARIANT; }
"{" { return LB; }
"}" { return RB; }
"\""[^\"\r\n]+"\"" { yylval.sVal = makestr(yytext+1); \
diff --git a/hw/xwin/winprefsyacc.y b/hw/xwin/winprefsyacc.y
index 683fc44ca..68d68b9f4 100644
--- a/hw/xwin/winprefsyacc.y
+++ b/hw/xwin/winprefsyacc.y
@@ -39,6 +39,8 @@
#include <stdlib.h>
#define _STDLIB_H 1 /* bison checks this to know if stdlib has been included */
#include <string.h>
+#include "globals.h"
+#include "winconfig.h"
#include "winprefs.h"
/* The following give better error messages in bison at the cost of a few KB */
@@ -57,6 +59,13 @@ static MENUPARSED menu;
/* Functions for parsing the tokens into out structure */
/* Defined at the end section of this file */
+static void SetDPI (char *dpi);
+static void SetXKBLayout (char *layout);
+static void SetXKBModel (char *model);
+static void SetXKBOptions (char *options);
+static void SetXKBRules (char *rules);
+static void SetXKBVariant (char *variant);
+
static void SetIconDirectory (char *path);
static void SetDefaultIcon (char *fname);
static void SetRootMenu (char *menu);
@@ -120,6 +129,12 @@ extern int yylex(void);
%token TRAYICON
%token FORCEEXIT
%token SILENTEXIT
+%token DPI
+%token XKBLAYOUT
+%token XKBMODEL
+%token XKBOPTIONS
+%token XKBRULES
+%token XKBVARIANT
%token <sVal> STRING
%type <uVal> group1
@@ -154,6 +169,30 @@ command: defaulticon
| trayicon
| forceexit
| silentexit
+ | dpi
+ | xkblayout
+ | xkbmodel
+ | xkboptions
+ | xkbrules
+ | xkbvariant
+ ;
+
+dpi: DPI STRING NEWLINE { SetDPI($2); free($2); }
+ ;
+
+xkblayout: XKBLAYOUT STRING NEWLINE { SetXKBLayout($2); }
+ ;
+
+xkbmodel: XKBMODEL STRING NEWLINE { SetXKBModel($2); }
+ ;
+
+xkboptions: XKBOPTIONS STRING NEWLINE { SetXKBOptions($2); }
+ ;
+
+xkbrules: XKBRULES STRING NEWLINE { SetXKBRules($2); }
+ ;
+
+xkbvariant: XKBVARIANT STRING NEWLINE { SetXKBVariant($2); }
;
trayicon: TRAYICON STRING NEWLINE { SetTrayIcon($2); free($2); }
@@ -260,6 +299,58 @@ yyerror (char *s)
return 1;
}
+static void
+SetDPI (char *dpi)
+{
+ if (!g_cmdline.customDPI)
+ monitorResolution = atoi (dpi);
+}
+
+static void
+SetXKBLayout (char *layout)
+{
+ if (!g_cmdline.xkbLayout)
+ g_cmdline.xkbLayout = layout;
+ else
+ free (layout);
+}
+
+static void
+SetXKBModel (char *model)
+{
+ if (!g_cmdline.xkbModel)
+ g_cmdline.xkbModel = model;
+ else
+ free (model);
+}
+
+static void
+SetXKBOptions (char *options)
+{
+ if (!g_cmdline.xkbOptions)
+ g_cmdline.xkbOptions = options;
+ else
+ free (options);
+}
+
+static void
+SetXKBRules (char *rules)
+{
+ if (!g_cmdline.xkbRules)
+ g_cmdline.xkbRules = rules;
+ else
+ free (rules);
+}
+
+static void
+SetXKBVariant (char *variant)
+{
+ if (!g_cmdline.xkbVariant)
+ g_cmdline.xkbVariant = variant;
+ else
+ free (variant);
+}
+
/* Miscellaneous functions to store TOKENs into the structure */
static void
SetIconDirectory (char *path)
diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c
index f2bf05bad..04b2f49fd 100644
--- a/hw/xwin/winprocarg.c
+++ b/hw/xwin/winprocarg.c
@@ -31,6 +31,10 @@ from The Open Group.
#include <xwin-config.h>
#endif
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
#include <../xfree86/common/xorgVersion.h>
#include "win.h"
#include "winconfig.h"
@@ -44,6 +48,7 @@ from The Open Group.
#ifdef XWIN_CLIPBOARD
extern Bool g_fUnicodeClipboard;
extern Bool g_fClipboard;
+#include "winclipboard/winclipboard.h"
#endif
/*
@@ -716,6 +721,26 @@ ddxProcessArgument(int argc, char *argv[], int i)
/* Indicate that we have processed this argument */
return 1;
}
+
+ /*
+ * Look for the '-primary' argument
+ */
+ if (IS_OPTION("-primary")) {
+ fPrimarySelection = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-noprimary' argument
+ */
+ if (IS_OPTION("-noprimary")) {
+ fPrimarySelection = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
#endif
/*
@@ -938,6 +963,14 @@ ddxProcessArgument(int argc, char *argv[], int i)
}
/*
+ * Look for the '-dpi' argument
+ */
+ if (IS_OPTION("-dpi")) {
+ g_cmdline.customDPI = TRUE;
+ return 0; /* Let DIX parse this again */
+ }
+
+ /*
* Look for the '-config' argument
*/
if (IS_OPTION("-config")
@@ -1079,6 +1112,11 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
+ if (IS_OPTION("-nohostintitle")) {
+ g_fHostInTitle = FALSE;
+ return 1;
+ }
+
return 0;
}
@@ -1150,6 +1188,115 @@ winLogCommandLine(int argc, char *argv[])
}
/*
+ * Detect the OS
+ */
+
+typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+static void
+winOS(void)
+{
+ OSVERSIONINFOEX osvi = { 0 };
+ const char *windowstype = "Unknown";
+ const char *prodName = "Unknown";
+ const char *isWow = "Unknown";
+
+ /* Get operating system version information */
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ GetVersionEx((LPOSVERSIONINFO) & osvi);
+
+ /* Branch on platform ID */
+ switch (osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_NT:
+ windowstype = "Windows NT";
+
+ if (osvi.dwMajorVersion <= 4)
+ prodName = "Windows NT";
+ else if (osvi.dwMajorVersion == 6) {
+ if (osvi.dwMinorVersion == 3) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 8.1";
+ else
+ prodName = "Windows Server 2012 R2";
+ }
+ if (osvi.dwMinorVersion == 2) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 8";
+ else
+ prodName = "Windows Server 2012";
+ }
+ else if (osvi.dwMinorVersion == 1) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 7";
+ else
+ prodName = "Windows Server 2008 R2";
+ }
+ else if (osvi.dwMinorVersion == 0) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows Vista";
+ else
+ prodName = "Windows Server 2008";
+ }
+ }
+ else if (osvi.dwMajorVersion == 5) {
+ if (osvi.dwMinorVersion == 2) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows XP x64 Edition";
+ else if (GetSystemMetrics(SM_SERVERR2))
+ prodName = "Windows Server 2003 R2";
+ else
+ prodName = "Windows Server 2003";
+ }
+ else if (osvi.dwMinorVersion == 1)
+ prodName = "Windows XP";
+ else if (osvi.dwMinorVersion == 0) {
+ prodName = "Windows 2000";
+ break;
+ }
+ }
+
+ break;
+
+ case VER_PLATFORM_WIN32_WINDOWS:
+ windowstype = "Windows";
+ break;
+ }
+
+#ifdef __x86_64__
+ isWow = " (Win64)";
+#else
+ {
+ /* Check if we are running under WoW64 */
+ LPFN_ISWOW64PROCESS fnIsWow64Process;
+
+ fnIsWow64Process =
+ (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle("kernel32"),
+ "IsWow64Process");
+ if (NULL != fnIsWow64Process) {
+ wBOOL bIsWow64 = FALSE;
+
+ if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) {
+ isWow = bIsWow64 ? " (WoW64)" : " (Win32)";
+ }
+ else {
+ /* IsWow64Process() failed */
+ isWow = " (WoWUnknown)";
+ }
+ }
+ else {
+ /* OS doesn't support IsWow64Process() */
+ isWow = "";
+ }
+ }
+#endif
+
+ ErrorF("OS: %s %s [%s %d.%d build %d]%s\n",
+ prodName, osvi.szCSDVersion,
+ windowstype, (int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion,
+ (int)osvi.dwBuildNumber, isWow);
+}
+
+/*
* winLogVersionInfo - Log version information
*/
@@ -1166,8 +1313,18 @@ winLogVersionInfo(void)
ErrorF("Vendor: %s\n", XVENDORNAME);
ErrorF("Release: %d.%d.%d.%d\n", XORG_VERSION_MAJOR,
XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP);
+#ifdef HAVE_SYS_UTSNAME_H
+ {
+ struct utsname name;
+
+ if (uname(&name) >= 0) {
+ ErrorF("OS: %s %s %s %s %s\n", name.sysname, name.nodename,
+ name.release, name.version, name.machine);
+ }
+ }
+#endif
+ winOS();
if (strlen(BUILDERSTRING))
ErrorF("%s\n", BUILDERSTRING);
- ErrorF("Contact: %s\n", BUILDERADDR);
ErrorF("\n");
}
diff --git a/hw/xwin/winrandr.c b/hw/xwin/winrandr.c
index 1b340850c..5624e7563 100644
--- a/hw/xwin/winrandr.c
+++ b/hw/xwin/winrandr.c
@@ -104,7 +104,7 @@ winDoRandRScreenSetSize(ScreenPtr pScreen,
SetRootClip(pScreen, TRUE);
// and arrange for it to be repainted
- miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
+ pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
/* Indicate that a screen size change took place */
RRScreenSizeNotify(pScreen);
diff --git a/hw/xwin/winresource.h b/hw/xwin/winresource.h
index afbf9f28d..37e92ce61 100644
--- a/hw/xwin/winresource.h
+++ b/hw/xwin/winresource.h
@@ -43,6 +43,7 @@
#define ID_APP_HIDE_ROOT 201
#define ID_APP_ALWAYS_ON_TOP 202
#define ID_APP_ABOUT 203
+#define ID_APP_MONITOR_PRIMARY 204
#define ID_ABOUT_WEBSITE 303
diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c
index 23152cbd2..2c6fdff68 100644
--- a/hw/xwin/winscrinit.c
+++ b/hw/xwin/winscrinit.c
@@ -216,15 +216,19 @@ winScreenInit(ScreenPtr pScreen, int argc, char **argv)
else
winErrorFVerb(2, "winScreenInit - Using software cursor\n");
- /*
- Note the screen origin in a normalized coordinate space where (0,0) is at the top left
- of the native virtual desktop area
- */
- pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
- pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
+ if (!noPanoramiXExtension) {
+ /*
+ Note the screen origin in a normalized coordinate space where (0,0) is at the top left
+ of the native virtual desktop area
+ */
+ pScreen->x =
+ pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
+ pScreen->y =
+ pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
- ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
- pScreen->myNum, pScreen->x, pScreen->y);
+ ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
+ pScreen->myNum, pScreen->x, pScreen->y);
+ }
#if CYGDEBUG || YES
winDebug("winScreenInit - returning\n");
diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c
index 55af5c383..cb326dc81 100644
--- a/hw/xwin/winshadddnl.c
+++ b/hw/xwin/winshadddnl.c
@@ -986,6 +986,10 @@ winRedrawScreenShadowDDNL(ScreenPtr pScreen)
RECT rcSrc, rcDest;
POINT ptOrigin;
+ /* Return immediately if we didn't get needed surfaces */
+ if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
+ return;
+
/* Get the origin of the window in the screen coords */
ptOrigin.x = pScreenInfo->dwXOffset;
ptOrigin.y = pScreenInfo->dwYOffset;
diff --git a/hw/xwin/wintrayicon.c b/hw/xwin/wintrayicon.c
index e0aa7e5ab..6acc0d712 100644
--- a/hw/xwin/wintrayicon.c
+++ b/hw/xwin/wintrayicon.c
@@ -32,9 +32,13 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include <shellapi.h>
#include "winprefs.h"
+#ifdef XWIN_CLIPBOARD
+#include "winclipboard/winclipboard.h"
+#endif
/*
* Initialize the tray icon
@@ -170,6 +174,21 @@ winHandleIconMessage(HWND hwnd, UINT message,
RemoveMenu(hmenuTray, ID_APP_HIDE_ROOT, MF_BYCOMMAND);
}
+#ifdef XWIN_CLIPBOARD
+ if (g_fClipboard) {
+ /* Set menu state to indicate if 'Monitor Primary' is enabled or not */
+ MENUITEMINFO mii = { 0 };
+ mii.cbSize = sizeof(MENUITEMINFO);
+ mii.fMask = MIIM_STATE;
+ mii.fState = fPrimarySelection ? MFS_CHECKED : MFS_UNCHECKED;
+ SetMenuItemInfo(hmenuTray, ID_APP_MONITOR_PRIMARY, FALSE, &mii);
+ }
+ else {
+ /* Remove 'Monitor Primary' menu item */
+ RemoveMenu(hmenuTray, ID_APP_MONITOR_PRIMARY, MF_BYCOMMAND);
+ }
+#endif
+
SetupRootMenu(hmenuTray);
/*
diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index 660a78f2d..9d0bab531 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -40,6 +40,7 @@
#define _WINDOWSWM_SERVER_
#include <X11/extensions/windowswmstr.h>
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
#include <X11/Xatom.h>
/*
diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c
index 001d0d2fc..8261e61c1 100644
--- a/hw/xwin/winwin32rootlesswndproc.c
+++ b/hw/xwin/winwin32rootlesswndproc.c
@@ -42,6 +42,7 @@
#include "winmultiwindowclass.h"
#include "winmsg.h"
#include "inputstr.h"
+#include "wmutil/keyboard.h"
/*
* Constant defines
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index 7e6bd565c..a5b9a386c 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -50,6 +50,7 @@
#define WIN_SCR_PROP "cyg_screen_prop rl"
#define WINDOW_CLASS_X "cygwin/x X rl"
#define WINDOW_CLASS_X_MSG "cygwin/x X msg"
+#define WINDOW_CLASS_X_CHILD "cygwin/x X child"
#define WINDOW_TITLE_X PROJECT_NAME " X"
#define WIN_WINDOW_PROP "cyg_window_prop_rl"
#ifdef HAS_DEVWINDOWS
diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index bee223de7..ccea2aa77 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -42,6 +42,11 @@
#include "winmsg.h"
#include "winmonitors.h"
#include "inputstr.h"
+#include "wmutil/mouse.h"
+#include "wmutil/keyboard.h"
+#ifdef XWIN_CLIPBOARD
+#include "winclipboard/winclipboard.h"
+#endif
/*
* Global variables
@@ -916,7 +921,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (wParam) {
case WIN_E3B_TIMER_ID:
/* Send delayed button press */
- winMouseButtonsSendEvent(ButtonPress,
+ winMouseButtonsSendEvent(TRUE,
s_pScreenPriv->iE3BCachedPress);
/* Kill this timer */
@@ -1223,6 +1228,12 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
#endif
+#ifdef XWIN_CLIPBOARD
+ case ID_APP_MONITOR_PRIMARY:
+ fPrimarySelection = !fPrimarySelection;
+ return 0;
+#endif
+
case ID_APP_ABOUT:
/* Display the About box */
winDisplayAboutDialog(s_pScreenPriv);
diff --git a/hw/xwin/wmutil/Makefile.am b/hw/xwin/wmutil/Makefile.am
new file mode 100644
index 000000000..5ccee32a6
--- /dev/null
+++ b/hw/xwin/wmutil/Makefile.am
@@ -0,0 +1,24 @@
+lib_LTLIBRARIES = libXWinWMUtil.la
+
+library_includedir=$(includedir)/XWinWMUtil
+
+library_include_HEADERS = \
+ icon_convert.h \
+ cursor_convert.h \
+ mouse.h \
+ keyboard.h
+
+libXWinWMUtil_la_SOURCES = \
+ icon_convert.c \
+ cursor_convert.c \
+ mouse.c \
+ keyboard.c \
+ winvkmap.h \
+ scancodes.h
+
+AM_CFLAGS = -DHAVE_XWIN_CONFIG_H \
+ $(DIX_CFLAGS) \
+ $(XWINMODULES_CFLAGS) \
+ -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/..
+
+libXWinWMUtil_la_LDFLAGS = -static
diff --git a/hw/xwin/wmutil/cursor_convert.c b/hw/xwin/wmutil/cursor_convert.c
new file mode 100644
index 000000000..b91200478
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.c
@@ -0,0 +1,351 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+
+#include "win.h"
+#include "winmsg.h"
+#include <cursorstr.h>
+
+#include "cursor_convert.h"
+
+#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114)
+
+#if 1
+#define WIN_DEBUG_MSG winDebug
+#else
+#define WIN_DEBUG_MSG(...)
+#endif
+
+static unsigned char
+reverse(unsigned char c)
+{
+ int i;
+ unsigned char ret = 0;
+
+ for (i = 0; i < 8; ++i) {
+ ret |= ((c >> i) & 1) << (7 - i);
+ }
+ return ret;
+}
+
+/*
+ * Convert X cursor to Windows cursor
+ * FIXME: Perhaps there are more smart code
+ */
+HCURSOR
+winXCursorToHCURSOR(WMUTIL_CURSOR *pCursor)
+{
+ HCURSOR hCursor = NULL;
+ unsigned char *pAnd;
+ unsigned char *pXor;
+ int nCX, nCY;
+ int nBytes;
+ double dForeY, dBackY;
+ BOOL fReverse;
+ HBITMAP hAnd, hXor;
+ ICONINFO ii;
+ unsigned char *pCur;
+ unsigned char bit;
+ HDC hDC;
+ BITMAPV4HEADER bi;
+ BITMAPINFO *pbmi;
+ uint32_t *lpBits;
+
+ int sm_cx = GetSystemMetrics(SM_CXCURSOR);
+ int sm_cy = GetSystemMetrics(SM_CYCURSOR);
+
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Win32 size: %dx%d X11 size: %dx%d hotspot: %d,%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height,
+ pCursor->xhot, pCursor->yhot);
+
+ /* We can use only White and Black, so calc brightness of color
+ * Also check if the cursor is inverted */
+ dForeY = BRIGHTNESS(pCursor->fore);
+ dBackY = BRIGHTNESS(pCursor->back);
+ fReverse = dForeY < dBackY;
+
+ /* Check whether the X11 cursor is bigger than the win32 cursor */
+ if (sm_cx < pCursor->width ||
+ sm_cy < pCursor->height) {
+ winError("winXCursorToHCURSOR - Windows requires %dx%d cursor but X requires %dx%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height);
+ }
+
+ /* Get the number of bytes required to store the whole cursor image
+ * This is roughly (sm_cx * sm_cy) / 8
+ * round up to 8 pixel boundary so we can convert whole bytes */
+ nBytes =
+ bits_to_bytes(sm_cx) * sm_cy;
+
+ /* Get the effective width and height */
+ nCX = min(sm_cx, pCursor->width);
+ nCY = min(sm_cy, pCursor->height);
+
+ /* Allocate memory for the bitmaps */
+ pAnd = malloc(nBytes);
+ memset(pAnd, 0xFF, nBytes);
+ pXor = calloc(1, nBytes);
+ memset(pXor, 0x00, nBytes);
+
+ /* prepare the pointers */
+ hCursor = NULL;
+ lpBits = NULL;
+
+ /* We have a truecolor alpha-blended cursor and can use it! */
+ if (pCursor->argb) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying truecolor alphablended cursor\n");
+ memset(&bi, 0, sizeof(BITMAPV4HEADER));
+ bi.bV4Size = sizeof(BITMAPV4HEADER);
+ bi.bV4Width = sm_cx;
+ bi.bV4Height = -(sm_cy); /* right-side up */
+ bi.bV4Planes = 1;
+ bi.bV4BitCount = 32;
+ bi.bV4V4Compression = BI_BITFIELDS;
+ bi.bV4RedMask = 0x00FF0000;
+ bi.bV4GreenMask = 0x0000FF00;
+ bi.bV4BlueMask = 0x000000FF;
+ bi.bV4AlphaMask = 0xFF000000;
+
+ lpBits = calloc(sm_cx * sm_cy, sizeof(uint32_t));
+
+ if (lpBits) {
+ int y;
+ for (y = 0; y < nCY; y++) {
+ void *src, *dst;
+ src = &(pCursor->argb[y * pCursor->width]);
+ dst = &(lpBits[y * sm_cx]);
+ memcpy(dst, src, 4 * nCX);
+ }
+ }
+ } /* End if-truecolor-icon */
+ else
+ {
+ /* Convert the X11 bitmap to a win32 bitmap
+ * The first is for an empty mask */
+ if (pCursor->emptyMask) {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ pAnd[nWinPix] = 0;
+ if (fReverse)
+ pXor[nWinPix] = reverse(~pCursor->source[nXPix]);
+ else
+ pXor[nWinPix] = reverse(pCursor->source[nXPix]);
+ }
+ }
+ else {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ unsigned char mask = pCursor->mask[nXPix];
+
+ pAnd[nWinPix] = reverse(~mask);
+ if (fReverse)
+ pXor[nWinPix] =
+ reverse(~pCursor->source[nXPix] & mask);
+ else
+ pXor[nWinPix] =
+ reverse(pCursor->source[nXPix] & mask);
+ }
+ }
+ }
+
+ if (!lpBits) {
+ RGBQUAD *pbmiColors;
+ /* Bicolor, use a palettized DIB */
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying two color cursor\n");
+ pbmi = (BITMAPINFO *) &bi;
+ pbmiColors = &(pbmi->bmiColors[0]);
+
+ memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = sm_cx;
+ pbmi->bmiHeader.biHeight = -abs(sm_cy); /* right-side up */
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biClrUsed = 3;
+ pbmi->bmiHeader.biClrImportant = 3;
+
+ pbmiColors[0].rgbRed = 0; /* Empty */
+ pbmiColors[0].rgbGreen = 0;
+ pbmiColors[0].rgbBlue = 0;
+ pbmiColors[0].rgbReserved = 0;
+ pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
+ pbmiColors[1].rgbGreen = pCursor->backGreen >> 8;
+ pbmiColors[1].rgbBlue = pCursor->backBlue >> 8;
+ pbmiColors[1].rgbReserved = 0;
+ pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
+ pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
+ pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
+ pbmiColors[2].rgbReserved = 0;
+
+ lpBits = calloc(sm_cx * sm_cy, 1);
+
+ pCur = (unsigned char *) lpBits;
+ if (lpBits) {
+ int x, y;
+ for (y = 0; y < sm_cy; y++) {
+ for (x = 0; x < sm_cx; x++) {
+ if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */
+ (*pCur++) = 0;
+ else { /* Within X11 icon bounds */
+
+ int nWinPix =
+ bits_to_bytes(sm_cx) * y +
+ (x / 8);
+
+ bit = pAnd[nWinPix];
+ bit = bit & (1 << (7 - (x & 7)));
+ if (!bit) { /* Within the cursor mask? */
+ int nXPix =
+ BitmapBytePad(pCursor->width) * y +
+ (x / 8);
+ bit =
+ ~reverse(~pCursor->
+ source[nXPix] & pCursor->
+ mask[nXPix]);
+ bit = bit & (1 << (7 - (x & 7)));
+ if (bit) /* Draw foreground */
+ (*pCur++) = 2;
+ else /* Draw background */
+ (*pCur++) = 1;
+ }
+ else /* Outside the cursor mask */
+ (*pCur++) = 0;
+ }
+ } /* end for (x) */
+ } /* end for (y) */
+ } /* end if (lpbits) */
+ }
+
+ /* If one of the previous two methods gave us the bitmap we need, make a cursor */
+ if (lpBits) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating bitmap cursor\n");
+
+ hAnd = NULL;
+ hXor = NULL;
+
+ hAnd =
+ CreateBitmap(sm_cx, sm_cy,
+ 1, 1, pAnd);
+
+ hDC = GetDC(NULL);
+ if (hDC) {
+ hXor =
+ CreateCompatibleBitmap(hDC, sm_cx,
+ sm_cy);
+ SetDIBits(hDC, hXor, 0, sm_cy, lpBits,
+ (BITMAPINFO *) &bi, DIB_RGB_COLORS);
+ ReleaseDC(NULL, hDC);
+ }
+ free(lpBits);
+
+ if (hAnd && hXor) {
+ ii.fIcon = FALSE;
+ ii.xHotspot = pCursor->xhot;
+ ii.yHotspot = pCursor->yhot;
+ ii.hbmMask = hAnd;
+ ii.hbmColor = hXor;
+ hCursor = (HCURSOR) CreateIconIndirect(&ii);
+
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError());
+ else {
+ /*
+ Apparently, CreateIconIndirect() sometimes creates an Icon instead of a Cursor.
+ This breaks the hotspot and makes the cursor unusable. Discard the broken cursor
+ and revert to simple b&w cursor. (Seen on W2K in 2004...)
+ */
+ if (GetIconInfo(hCursor, &ii)) {
+ if (ii.fIcon) {
+ winError
+ ("winXCursorToHCURSOR: CreateIconIndirect made an icon, not a cursor. Trying again.\n");
+
+ DestroyCursor(hCursor);
+
+ ii.fIcon = FALSE;
+ ii.xHotspot = pCursor->xhot;
+ ii.yHotspot = pCursor->yhot;
+ hCursor = (HCURSOR) CreateIconIndirect(&ii);
+
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError());
+ }
+ /* GetIconInfo creates new bitmaps. Destroy them again */
+ if (ii.hbmMask)
+ DeleteObject(ii.hbmMask);
+ if (ii.hbmColor)
+ DeleteObject(ii.hbmColor);
+ }
+ }
+ }
+
+ if (hAnd)
+ DeleteObject(hAnd);
+ if (hXor)
+ DeleteObject(hXor);
+ }
+
+ if (!hCursor) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating b&w cursor\n");
+ /* We couldn't make a color cursor for this screen, use
+ black and white instead */
+ hCursor = CreateCursor(GetModuleHandle(NULL),
+ pCursor->xhot, pCursor->yhot,
+ sm_cx,
+ sm_cy, pAnd, pXor);
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateCursor failed: %x", GetLastError());
+ }
+ free(pAnd);
+ free(pXor);
+
+ return hCursor;
+}
diff --git a/hw/xwin/wmutil/cursor_convert.h b/hw/xwin/wmutil/cursor_convert.h
new file mode 100644
index 000000000..a5ddba3c2
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.h
@@ -0,0 +1,54 @@
+/*
+ * File: cursor_convert.h
+ * Purpose: interface for X->Windows cursor conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_CURSOR_H
+#define WMUTILS_CURSOR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct _WMUTIL_CURSOR
+{
+ // this is the data for cursor created with RENDER CreateCusor or read
+ // with XFIXES GetCursorImage
+ int width;
+ int height;
+ int xhot;
+ int yhot;
+ uint32_t *argb;
+
+ // for a core CreateCursor, we might need the following...
+ unsigned char *source;
+ unsigned char *mask;
+ bool emptyMask;
+ unsigned short foreRed, foreGreen, foreBlue;
+ unsigned short backRed, backGreen, backBlue;
+
+} WMUTIL_CURSOR;
+
+HCURSOR
+winXCursorToHCURSOR(WMUTIL_CURSOR *cursordata);
+
+#endif /* WMUTILS_CURSOR_H */
diff --git a/hw/xwin/wmutil/icon_convert.c b/hw/xwin/wmutil/icon_convert.c
new file mode 100644
index 000000000..14fcd80d1
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.c
@@ -0,0 +1,567 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Earle F. Philhower, III
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_image.h>
+
+#include <windows.h>
+
+#include <limits.h>
+#include <stdbool.h>
+
+#include "winmsg.h"
+
+#include "icon_convert.h"
+
+extern unsigned long serverGeneration;
+
+/*
+ * Scale an X icon ZPixmap into a Windoze icon bitmap
+ */
+
+static void
+winScaleXImageToWindowsIcon(int iconSize,
+ int effBPP,
+ int stride, xcb_image_t* pixmap, unsigned char *image)
+{
+ int row, column, effXBPP, effXDepth;
+ unsigned char *outPtr;
+ unsigned char *iconData = 0;
+ int xStride;
+ float factX, factY;
+ int posX, posY;
+ unsigned char *ptr;
+ unsigned int zero;
+ unsigned int color;
+
+ effXBPP = pixmap->bpp;
+ if (pixmap->bpp == 15)
+ effXBPP = 16;
+
+ effXDepth = pixmap->depth;
+ if (pixmap->depth == 15)
+ effXDepth = 16;
+
+ xStride = pixmap->stride;
+ if (stride == 0 || xStride == 0) {
+ winError("winScaleXBitmapToWindows - stride or xStride is zero. "
+ "Bailing.\n");
+ return;
+ }
+
+ /* Get icon data */
+ iconData = (unsigned char *) pixmap->data;
+
+ /* Keep aspect ratio */
+ factX = ((float) pixmap->width) / ((float) iconSize);
+ factY = ((float) pixmap->height) / ((float) iconSize);
+ if (factX > factY)
+ factY = factX;
+ else
+ factX = factY;
+
+ /* Out-of-bounds, fill icon with zero */
+ zero = 0;
+
+ for (row = 0; row < iconSize; row++) {
+ outPtr = image + stride * row;
+ for (column = 0; column < iconSize; column++) {
+ posX = factX * column;
+ posY = factY * row;
+
+ ptr = (unsigned char *) iconData + posY * xStride;
+ if (effXBPP == 1) {
+ ptr += posX / 8;
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+
+ if ((*ptr) & (1 << (posX & 7)))
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 0;
+ case 24:
+ *(outPtr++) = 0;
+ case 16:
+ *(outPtr++) = 0;
+ case 8:
+ *(outPtr++) = 0;
+ break;
+ case 1:
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ }
+ else
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 0;
+ break;
+ case 24:
+ *(outPtr++) = 255;
+ case 16:
+ *(outPtr++) = 255;
+ case 8:
+ *(outPtr++) = 255;
+ break;
+ case 1:
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ break;
+ }
+ }
+ else if (effXDepth == 24 || effXDepth == 32) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = (((*ptr) << 16)
+ + ((*(ptr + 1)) << 8)
+ + ((*(ptr + 2)) << 0));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = *(ptr++); /* b */
+ *(outPtr++) = *(ptr++); /* g */
+ *(outPtr++) = *(ptr++); /* r */
+ *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
+ break;
+ case 24:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 16:
+ color = ((((*ptr) >> 2) << 10)
+ + (((*(ptr + 1)) >> 2) << 5)
+ + (((*(ptr + 2)) >> 2)));
+ *(outPtr++) = (color >> 8);
+ *(outPtr++) = (color & 255);
+ break;
+ case 8:
+ color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
+ color /= 3;
+ *(outPtr++) = color;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ }
+ }
+ else if (effXDepth == 16) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = ((*ptr) << 8) + (*(ptr + 1));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ *(outPtr++) = 0; /* resvd */
+ break;
+ case 24:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ break;
+ case 16:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 8:
+ *(outPtr++) = (((color & 31)
+ + ((color >> 5) & 31)
+ + ((color >> 10) & 31)) / 3) << 2;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ } /* end switch(effbpp) */
+ } /* end if effxbpp==16) */
+ } /* end for column */
+ } /* end for row */
+}
+
+static HICON
+NetWMToWinIconAlpha(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ HICON result;
+ HDC hdc = GetDC(NULL);
+ uint32_t *DIB_pixels;
+ ICONINFO ii;
+ BITMAPV4HEADER bmh = { sizeof(bmh) };
+
+ /* Define an ARGB pixel format used for Color+Alpha icons */
+ bmh.bV4Width = width;
+ bmh.bV4Height = -height; /* Invert the image */
+ bmh.bV4Planes = 1;
+ bmh.bV4BitCount = 32;
+ bmh.bV4V4Compression = BI_BITFIELDS;
+ bmh.bV4AlphaMask = 0xFF000000;
+ bmh.bV4RedMask = 0x00FF0000;
+ bmh.bV4GreenMask = 0x0000FF00;
+ bmh.bV4BlueMask = 0x000000FF;
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh,
+ DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
+ 0);
+ ReleaseDC(NULL, hdc);
+
+ if (!ii.hbmColor)
+ return NULL;
+
+ ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
+ memcpy(DIB_pixels, pixels, height * width * 4);
+
+ /* CreateIconIndirect() traditionally required DDBitmaps */
+ /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
+ /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
+ return result;
+}
+
+static HICON
+NetWMToWinIconThreshold(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ int row, col;
+ HICON result;
+ ICONINFO ii;
+
+ HDC hdc = GetDC(NULL);
+ HDC xorDC = CreateCompatibleDC(hdc);
+ HDC andDC = CreateCompatibleDC(hdc);
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
+ ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
+ ReleaseDC(NULL, hdc);
+ SelectObject(xorDC, ii.hbmColor);
+ SelectObject(andDC, ii.hbmMask);
+
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
+ SetPixelV(xorDC, col, row,
+ RGB(((char *) pixels)[2], ((char *) pixels)[1],
+ ((char *) pixels)[0]));
+ SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
+ }
+ else {
+ SetPixelV(xorDC, col, row, RGB(0, 0, 0));
+ SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
+ }
+ pixels++;
+ }
+ }
+ DeleteDC(xorDC);
+ DeleteDC(andDC);
+
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
+ result);
+ return result;
+}
+
+static HICON
+NetWMToWinIcon(int bpp, uint32_t * icon)
+{
+ static bool hasIconAlphaChannel = FALSE;
+ static bool versionChecked = FALSE;
+
+ if (!versionChecked) {
+ OSVERSIONINFOEX osvi = { 0 };
+ ULONGLONG dwlConditionMask = 0;
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ osvi.dwMajorVersion = 5;
+ osvi.dwMinorVersion = 1;
+
+ /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
+ VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
+ VER_GREATER_EQUAL);
+ hasIconAlphaChannel =
+ VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
+ dwlConditionMask);
+ versionChecked = TRUE;
+
+ winError("OS has icon alpha channel support: %s\n",
+ hasIconAlphaChannel ? "yes" : "no");
+ }
+
+ if (hasIconAlphaChannel && (bpp == 32))
+ return NetWMToWinIconAlpha(icon);
+ else
+ return NetWMToWinIconThreshold(icon);
+}
+
+/*
+ * Attempt to create a custom icon from the WM_HINTS bitmaps
+ */
+
+HICON
+winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize)
+{
+ unsigned char *mask, *image = NULL, *imageMask;
+ unsigned char *dst, *src;
+ int planes, bpp, i;
+ unsigned int biggest_size = 0;
+ HDC hDC;
+ ICONINFO ii;
+ xcb_icccm_wm_hints_t hints;
+ HICON hIcon = NULL;
+ uint32_t *biggest_icon = NULL;
+ static xcb_atom_t _XA_NET_WM_ICON;
+ static int generation;
+ uint32_t *icon, *icon_data = NULL;
+ unsigned long int size;
+
+ hDC = GetDC(GetDesktopWindow());
+ planes = GetDeviceCaps(hDC, PLANES);
+ bpp = GetDeviceCaps(hDC, BITSPIXEL);
+ ReleaseDC(GetDesktopWindow(), hDC);
+
+ /* Always prefer _NET_WM_ICON icons */
+ if (generation != serverGeneration) {
+ generation = serverGeneration;
+
+ xcb_intern_atom_reply_t *atom_reply;
+ xcb_intern_atom_cookie_t atom_cookie;
+ const char *atomName = "_NET_WM_ICON";
+
+ _XA_NET_WM_ICON = XCB_NONE;
+
+ atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
+ atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
+ if (atom_reply) {
+ _XA_NET_WM_ICON = atom_reply->atom;
+ free(atom_reply);
+ }
+ }
+
+ xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
+
+ if (reply &&
+ ((icon_data = xcb_get_property_value(reply)) != NULL)) {
+ size = xcb_get_property_value_length(reply)/sizeof(uint32_t);
+ for (icon = icon_data; icon < &icon_data[size] && *icon;
+ icon = &icon[icon[0] * icon[1] + 2]) {
+ winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
+
+ /* Icon data size will overflow an int and thus is bigger than the
+ property can possibly be */
+ if ((INT_MAX/icon[0]) < icon[1]) {
+ winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
+ break;
+ }
+
+ /* Icon data size is bigger than amount of data remaining */
+ if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
+ winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
+ break;
+ }
+
+ /* Found an exact match to the size we require... */
+ if (icon[0] == iconSize && icon[1] == iconSize) {
+ winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
+ iconSize, iconSize);
+ hIcon = NetWMToWinIcon(bpp, icon);
+ break;
+ }
+ /* Otherwise, find the biggest icon and let Windows scale the size */
+ else if (biggest_size < icon[0]) {
+ biggest_icon = icon;
+ biggest_size = icon[0];
+ }
+ }
+
+ if (!hIcon && biggest_icon) {
+ winDebug
+ ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
+ biggest_icon[0], biggest_icon[1], iconSize, iconSize);
+
+ hIcon = NetWMToWinIcon(bpp, biggest_icon);
+ }
+
+ free(reply);
+ }
+
+ if (!hIcon) {
+ winDebug("winXIconToHICON: no suitable NetIcon\n");
+
+ xcb_get_property_cookie_t wm_hints_cookie = xcb_icccm_get_wm_hints(conn, id);
+ if (xcb_icccm_get_wm_hints_reply(conn, wm_hints_cookie, &hints, NULL)) {
+ winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
+ hints.icon_pixmap);
+
+ if (hints.icon_pixmap) {
+ unsigned int width, height;
+ xcb_image_t *xImageIcon;
+ xcb_image_t *xImageMask = NULL;
+
+ xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, hints.icon_pixmap);
+ xcb_get_geometry_reply_t *geom_reply = xcb_get_geometry_reply(conn, geom_cookie, NULL);
+
+ if (geom_reply) {
+ width = geom_reply->width;
+ height = geom_reply->height;
+
+ xImageIcon = xcb_image_get(conn, hints.icon_pixmap,
+ 0, 0, width, height,
+ 0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
+
+ winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
+ xImageIcon);
+
+ if (hints.icon_mask)
+ xImageMask = xcb_image_get(conn, hints.icon_mask,
+ 0, 0, width, height,
+ 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
+
+ if (xImageIcon) {
+ int effBPP, stride, maskStride;
+
+ /* 15 BPP is really 16BPP as far as we care */
+ if (bpp == 15)
+ effBPP = 16;
+ else
+ effBPP = bpp;
+
+ /* Need 16-bit aligned rows for DDBitmaps */
+ stride = ((iconSize * effBPP + 15) & (~15)) / 8;
+
+ /* Mask is 1-bit deep */
+ maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
+
+ image = malloc(stride * iconSize);
+ imageMask = malloc(stride * iconSize);
+ mask = malloc(maskStride * iconSize);
+
+ /* Default to a completely black mask */
+ memset(imageMask, 0, stride * iconSize);
+ memset(mask, 0, maskStride * iconSize);
+
+ winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+ xImageIcon, image);
+
+ if (xImageMask) {
+ winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
+ xImageMask, mask);
+ winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+ xImageMask, imageMask);
+ }
+
+ /* Now we need to set all bits of the icon which are not masked */
+ /* on to 0 because Color is really an XOR, not an OR function */
+ dst = image;
+ src = imageMask;
+
+ for (i = 0; i < (stride * iconSize); i++)
+ if ((*(src++)))
+ *(dst++) = 0;
+ else
+ dst++;
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+
+ /* Create Win32 mask from pixmap shape */
+ ii.hbmMask =
+ CreateBitmap(iconSize, iconSize, planes, 1, mask);
+
+ /* Create Win32 bitmap from pixmap */
+ ii.hbmColor =
+ CreateBitmap(iconSize, iconSize, planes, bpp, image);
+
+ /* Merge Win32 mask and bitmap into icon */
+ hIcon = CreateIconIndirect(&ii);
+
+ /* Release Win32 mask and bitmap */
+ DeleteObject(ii.hbmMask);
+ DeleteObject(ii.hbmColor);
+
+ /* Free X mask and bitmap */
+ free(mask);
+ free(image);
+ free(imageMask);
+
+ if (xImageMask)
+ xcb_image_destroy(xImageMask);
+
+ xcb_image_destroy(xImageIcon);
+ }
+ }
+ }
+ }
+ }
+ return hIcon;
+}
diff --git a/hw/xwin/wmutil/icon_convert.h b/hw/xwin/wmutil/icon_convert.h
new file mode 100644
index 000000000..0065326be
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.h
@@ -0,0 +1,34 @@
+/*
+ * File: icons.h
+ * Purpose: interface for X->Windows icon conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_ICONS_H
+#define WMUTILS_ICONS_H
+
+#include <xcb/xcb.h>
+
+HICON
+winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize);
+
+#endif /* WMUTILS_ICONS_H */
diff --git a/hw/xwin/wmutil/keyboard.c b/hw/xwin/wmutil/keyboard.c
new file mode 100644
index 000000000..780668d42
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.c
@@ -0,0 +1,308 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/Xmd.h> // to provide a BYTE type, since the Windows one is eclipsed
+
+#include "winvkmap.h"
+#include "keyboard.h"
+
+#include "winmsg.h"
+
+static bool g_winKeyState[NUM_KEYCODES];
+
+/*
+ * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
+ * into an ASCII scan code.
+ *
+ * We do this ourselves, rather than letting Windows handle it,
+ * because Windows tends to munge the handling of special keys,
+ * like AltGr on European keyboards.
+ */
+
+int
+winTranslateKey(WPARAM wParam, LPARAM lParam)
+{
+ int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
+ int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
+ int iParam = HIWORD(lParam);
+ int iParamScanCode = LOBYTE(iParam);
+ int iScanCode;
+
+ winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
+
+/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
+ * scan code.
+ *
+ * Vocola 3 (Rick Mohr's supplement to WSR) uses
+ * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
+ * scan code of 1
+ */
+ if (iParamScanCode <= 1) {
+ if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
+ /* Trigger special case table to translate to extended
+ * keycode, otherwise if num_lock is on, we can get keypad
+ * numbers instead of navigation keys. */
+ iParam |= KF_EXTENDED;
+ else
+ iParamScanCode = MapVirtualKeyEx(wParam,
+ /*MAPVK_VK_TO_VSC */ 0,
+ GetKeyboardLayout(0));
+ }
+
+ /* Branch on special extended, special non-extended, or normal key */
+ if ((iParam & KF_EXTENDED) && iKeyFixupEx)
+ iScanCode = iKeyFixupEx;
+ else if (iKeyFixup)
+ iScanCode = iKeyFixup;
+ else if (wParam == 0 && iParamScanCode == 0x70)
+ iScanCode = KEY_HKTG;
+ else
+ switch (iParamScanCode) {
+ case 0x70:
+ iScanCode = KEY_HKTG;
+ break;
+ case 0x73:
+ iScanCode = KEY_BSlash2;
+ break;
+ default:
+ iScanCode = iParamScanCode;
+ break;
+ }
+
+ return iScanCode;
+}
+
+/*
+ * Look for the lovely fake Control_L press/release generated by Windows
+ * when AltGr is pressed/released on a non-U.S. keyboard.
+ */
+
+bool
+winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ MSG msgNext;
+ LONG lTime;
+ bool fReturn;
+
+ static bool lastWasControlL = FALSE;
+ static LONG lastTime;
+
+ /*
+ * Fake Ctrl_L presses will be followed by an Alt_R press
+ * with the same timestamp as the Ctrl_L press.
+ */
+ if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L press */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next press message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYDOWN &&
+ msgNext.message != WM_SYSKEYDOWN)
+ fReturn = 0;
+
+ if (!fReturn) {
+ lastWasControlL = TRUE;
+ lastTime = lTime;
+ }
+ else {
+ lastWasControlL = FALSE;
+ }
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key press is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L press is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ /*
+ * Sometimes, the Alt_R press message is not yet posted when the
+ * fake Ctrl_L press message arrives (even though it has the
+ * same timestamp), so check for an Alt_R press message that has
+ * arrived since the last Ctrl_L message.
+ */
+ else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
+ /* Got a Alt_R press */
+
+ if (lastWasControlL) {
+ lTime = GetMessageTime();
+
+ if (lastTime == lTime) {
+ /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */
+ winSendKeyEvent(KEY_LCtrl, FALSE);
+ }
+ lastWasControlL = FALSE;
+ }
+ }
+ /*
+ * Fake Ctrl_L releases will be followed by an Alt_R release
+ * with the same timestamp as the Ctrl_L release.
+ */
+ else if ((message == WM_KEYUP || message == WM_SYSKEYUP)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L release */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next release message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYUP &&
+ msgNext.message != WM_SYSKEYUP)
+ fReturn = 0;
+
+ lastWasControlL = FALSE;
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn
+ && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP)
+ && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key release is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L release is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ else {
+ /* On any other press or release message, we don't have a
+ potentially fake Ctrl_L to worry about anymore... */
+ lastWasControlL = FALSE;
+ }
+
+ /* Not a fake control left press/release */
+ return FALSE;
+}
+
+/*
+ * Lift any modifier keys that are pressed
+ */
+
+void
+winKeybdReleaseKeys(void)
+{
+ int i;
+
+ /* Loop through all keys */
+ for (i = 0; i < NUM_KEYCODES; ++i) {
+ /* Pop key if pressed */
+ if (g_winKeyState[i])
+ winSendKeyEvent(i, FALSE);
+
+ /* Reset pressed flag for keys */
+ g_winKeyState[i] = FALSE;
+ }
+}
+
+/*
+ * Take a raw X key code and send an up or down event for it.
+ *
+ * Thanks to VNC for inspiration, though it is a simple function.
+ */
+
+void
+winSendKeyEvent(DWORD dwKey, bool fDown)
+{
+ /*
+ * When alt-tabing between screens we can get phantom key up messages
+ * Here we only pass them through it we think we should!
+ */
+ if (g_winKeyState[dwKey] == FALSE && fDown == FALSE)
+ return;
+
+ /* Update the keyState map */
+ g_winKeyState[dwKey] = fDown;
+
+ winSendKeyEventCallback(dwKey + MIN_KEYCODE, fDown);
+
+ winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown);
+}
+
+bool
+winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case VK_CONTROL:
+ if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
+ return TRUE;
+ break;
+ case VK_SHIFT:
+ if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
+ return TRUE;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Only one shift release message is sent even if both are pressed.
+ * Fix this here
+ */
+void
+winFixShiftKeys(int iScanCode)
+{
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ return;
+
+ if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
+ winSendKeyEvent(KEY_ShiftR, FALSE);
+ if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
+ winSendKeyEvent(KEY_ShiftL, FALSE);
+}
diff --git a/hw/xwin/wmutil/keyboard.h b/hw/xwin/wmutil/keyboard.h
new file mode 100644
index 000000000..5b229c25c
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.h
@@ -0,0 +1,39 @@
+/*
+ * File: keyboard.h
+ * Purpose: interface for X->Windows keyboard event conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_KEYBOARD_H
+#define WMUTILS_KEYBOARD_H
+
+#include <stdbool.h>
+
+void winSendKeyEvent(DWORD dwKey, bool fDown);
+void winSendKeyEventCallback(DWORD dwKey, bool fDown);
+void winKeybdReleaseKeys(void);
+bool winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam);
+bool winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
+int winTranslateKey(WPARAM wParam, LPARAM lParam);
+void winFixShiftKeys(int iScanCode);
+
+#endif /* WMUTILS_KEYBOARD_H */
diff --git a/hw/xwin/wmutil/mouse.c b/hw/xwin/wmutil/mouse.c
new file mode 100644
index 000000000..ba58f067a
--- /dev/null
+++ b/hw/xwin/wmutil/mouse.c
@@ -0,0 +1,111 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/X.h>
+
+#include "mouse.h"
+
+/* Handle the mouse wheel */
+void
+winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown)
+{
+ int button;
+
+ /* Do we have any previous delta stored? */
+ if ((*iTotalDeltaZ > 0 && iDeltaZ > 0)
+ || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) {
+ /* Previous delta and of same sign as current delta */
+ iDeltaZ += *iTotalDeltaZ;
+ *iTotalDeltaZ = 0;
+ }
+ else {
+ /*
+ * Previous delta of different sign, or zero.
+ * We will set it to zero for either case,
+ * as blindly setting takes just as much time
+ * as checking, then setting if necessary :)
+ */
+ *iTotalDeltaZ = 0;
+ }
+
+ /*
+ * Only process this message if the wheel has moved further than
+ * WHEEL_DELTA
+ */
+ if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
+ *iTotalDeltaZ = 0;
+
+ /* Figure out how many whole deltas of the wheel we have */
+ iDeltaZ /= WHEEL_DELTA;
+ }
+ else {
+ /*
+ * Wheel has not moved past WHEEL_DELTA threshold;
+ * we will store the wheel delta until the threshold
+ * has been reached.
+ */
+ *iTotalDeltaZ = iDeltaZ;
+ return;
+ }
+
+ /* Set the button to indicate up or down wheel delta */
+ if (iDeltaZ > 0) {
+ button = iButtonUp;
+ }
+ else {
+ button = iButtonDown;
+ }
+
+ /*
+ * Flip iDeltaZ to positive, if negative,
+ * because always need to generate a *positive* number of
+ * button clicks for the Z axis.
+ */
+ if (iDeltaZ < 0) {
+ iDeltaZ *= -1;
+ }
+
+ /* Generate X input messages for each wheel delta we have seen */
+ while (iDeltaZ--) {
+ /* Push the wheel button */
+ winMouseButtonsSendEvent(TRUE, button);
+
+ /* Release the wheel button */
+ winMouseButtonsSendEvent(FALSE, button);
+ }
+}
diff --git a/hw/xwin/wmutil/mouse.h b/hw/xwin/wmutil/mouse.h
new file mode 100644
index 000000000..8bd6fe9eb
--- /dev/null
+++ b/hw/xwin/wmutil/mouse.h
@@ -0,0 +1,36 @@
+/*
+ * File: mouse.h
+ * Purpose: interface for X->Windows mouse event conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_MOUSE_H
+#define WMUTILS_MOUSE_H
+
+#include <stdbool.h>
+
+void winMouseWheel(int *iTotalDeltaz, int iDeltaZ, int iButtonUp, int iButtonDown);
+
+/* Callback for sending mouse button events */
+void winMouseButtonsSendEvent(bool bPress, int iButton);
+
+#endif /* WMUTILS_MOUSE_H */
diff --git a/hw/xwin/winkeynames.h b/hw/xwin/wmutil/scancodes.h
index bfed9d427..3215a4bcb 100644
--- a/hw/xwin/winkeynames.h
+++ b/hw/xwin/wmutil/scancodes.h
@@ -1,5 +1,3 @@
-#ifndef _WINKEYNAMES_H
-#define _WINKEYNAMES_H
/*
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
*
@@ -23,18 +21,8 @@
*
*/
-#define GLYPHS_PER_KEY 4
-#define NUM_KEYCODES 248
-#define MIN_KEYCODE 8
-#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
-
-#define AltMask Mod1Mask
-#define NumLockMask Mod2Mask
-#define AltLangMask Mod3Mask
-#define KanaMask Mod4Mask
-#define ScrollLockMask Mod5Mask
-
-#define ModifierDown(k) ((keyc->state & (k)) == (k))
+#ifndef SCANCODES_H
+#define SCANCODES_H
/*
* NOTE: The AT/MF keyboards can generate (via the 8042) two (MF: three)
@@ -203,4 +191,4 @@
#define KEY_NOTUSED 0
#define KEY_UNKNOWN 255
-#endif /* _WINKEYNAMES_H */
+#endif /* SCANCODES_H */
diff --git a/hw/xwin/winkeybd.h b/hw/xwin/wmutil/winvkmap.h
index 6701f0959..eff61c7f9 100644
--- a/hw/xwin/winkeybd.h
+++ b/hw/xwin/wmutil/winvkmap.h
@@ -1,5 +1,3 @@
-#if !defined(WINKEYBD_H)
-#define WINKEYBD_H
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*
@@ -30,10 +28,17 @@
* Authors: Harold L Hunt II
*/
+#ifndef WINVKMAP_H
+#define WINVKMAP_H
+
/*
* We need symbols for the scan codes of keys.
*/
-#include "winkeynames.h"
+#include "scancodes.h"
+
+#define NUM_KEYCODES 248
+#define MIN_KEYCODE 8
+#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
#define VK_FN 0xFF
@@ -268,8 +273,7 @@ const int
/* 220 */ 0, 0, 0,
/* 221 */ 0, 0, 0,
/* 222 */ 0, 0, 0,
- /* 223 */ VK_OEM_8, 0, KEY_RCtrl,
- /* at least on Canadian Multilingual Standard layout */
+ /* 223 */ VK_OEM_8, 0, KEY_RCtrl, /* at least on Canadian Multilingual Standard layout */
/* 224 */ 0, 0, 0,
/* 225 */ 0, 0, 0,
/* 226 */ 0, 0, 0,
@@ -301,8 +305,7 @@ const int
/* 252 */ 0, 0, 0,
/* 253 */ 0, 0, 0,
/* 254 */ 0, 0, 0,
- /* 255 */ VK_FN, 0, KEY_Fn
- /* Most keyboards don't generate a scancode for Fn, but a few do... */
+ /* 255 */ VK_FN, 0, KEY_Fn /* Most keyboards don't generate a scancode for Fn, but a few do... */
};
-#endif /* WINKEYBD_H */
+#endif /* WINVKMAP_H */
diff --git a/include/dixmain.h b/include/dixmain.h
new file mode 100644
index 000000000..56fa0cd4b
--- /dev/null
+++ b/include/dixmain.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+ * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the XFree86 Project shall not
+ * be used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from the XFree86 Project.
+ */
+
+#ifndef DIXMAIN_H
+#define DIXMAIN_H
+
+/* this is separate to avoid being pulled in by sdksyms */
+int dix_main(int argc, char *argv[], char *envp[]);
+
+#endif
diff --git a/include/extinit.h b/include/extinit.h
index fa5f29378..10f7b4620 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -163,7 +163,7 @@ extern void SELinuxExtensionInit(void);
extern void XTestExtensionInit(void);
#endif
-#ifdef INXQUARTZ
+#ifndef SDKSYMS
extern _X_EXPORT Bool noPseudoramiXExtension;
extern void PseudoramiXExtensionInit(void);
#endif
diff --git a/include/os.h b/include/os.h
index d26e399b6..435f556aa 100644
--- a/include/os.h
+++ b/include/os.h
@@ -367,6 +367,10 @@ extern _X_EXPORT void *
Fopen(const char *, const char *);
extern _X_EXPORT int
Fclose(void *);
+#if defined(__CYGWIN__)
+extern const char *
+Win32TempDir(void);
+#endif
#else
extern const char *
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 6acdadd7a..7725a9827 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -158,6 +158,10 @@ typedef void (*WindowExposuresProcPtr) (WindowPtr /*pWindow */ ,
RegionPtr /*prgn */ ,
RegionPtr /*other_exposed */ );
+typedef void (* PaintWindowProcPtr) (WindowPtr /*pWindow*/ ,
+ RegionPtr /*pRegion*/ ,
+ int /*what*/ );
+
typedef void (*CopyWindowProcPtr) (WindowPtr /*pWindow */ ,
DDXPointRec /*ptOldOrg */ ,
RegionPtr /*prgnSrc */ );
@@ -408,6 +412,7 @@ typedef struct _Screen {
ValidateTreeProcPtr ValidateTree;
PostValidateTreeProcPtr PostValidateTree;
WindowExposuresProcPtr WindowExposures;
+ PaintWindowProcPtr PaintWindow;
CopyWindowProcPtr CopyWindow;
ClearToBackgroundProcPtr ClearToBackground;
ClipNotifyProcPtr ClipNotify;
diff --git a/man/Xserver.man b/man/Xserver.man
index 7a74e8541..0432d70b1 100644
--- a/man/Xserver.man
+++ b/man/Xserver.man
@@ -562,9 +562,6 @@ Outline font directories
.I /tmp/.X11-unix/X\fBn\fP
Unix domain socket for display number \fBn\fP
.TP 30
-.I /usr/adm/X\fBn\fPmsgs
-Error log file for display number \fBn\fP if run from \fIinit\fP(__adminmansuffix__)
-.TP 30
.I __projectroot__/lib/X11/xdm/xdm-errors
Default error log file if the server is run from \fIxdm\fP(1)
.SH "SEE ALSO"
diff --git a/mi/miexpose.c b/mi/miexpose.c
index 198c4332f..b43538627 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -277,7 +277,7 @@ miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
/* miPaintWindow doesn't clip, so we have to */
RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
}
- miPaintWindow((WindowPtr) pDstDrawable, &rgnExposed, PW_BACKGROUND);
+ (*pWin->drawable.pScreen->PaintWindow)(pWin, &rgnExposed, PW_BACKGROUND);
if (extents) {
RegionReset(&rgnExposed, &expBox);
@@ -467,7 +467,7 @@ miWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
RegionIntersect(prgn, prgn, &pWin->clipList);
}
if (prgn && !RegionNil(prgn))
- miPaintWindow(pWin, prgn, PW_BACKGROUND);
+ (*pWin->drawable.pScreen->PaintWindow)(pWin, prgn, PW_BACKGROUND);
if (clientInterested && exposures && !RegionNil(exposures))
miSendExposures(pWin, exposures,
pWin->drawable.x, pWin->drawable.y);
@@ -483,14 +483,6 @@ miWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
RegionDestroy(exposures);
}
-#ifdef ROOTLESS
-/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */
-void RootlessSetPixmapOfAncestors(WindowPtr pWin);
-void RootlessStartDrawing(WindowPtr pWin);
-void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
-Bool IsFramedWindow(WindowPtr pWin);
-#endif
-
void
miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
{
@@ -518,22 +510,6 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
Bool solid = TRUE;
DrawablePtr drawable = &pWin->drawable;
-#ifdef ROOTLESS
- if (!drawable || drawable->type == UNDRAWABLE_WINDOW)
- return;
-
- if (IsFramedWindow(pWin)) {
- RootlessStartDrawing(pWin);
- RootlessDamageRegion(pWin, prgn);
-
- if (pWin->backgroundState == ParentRelative) {
- if ((what == PW_BACKGROUND) ||
- (what == PW_BORDER && !pWin->borderIsPixel))
- RootlessSetPixmapOfAncestors(pWin);
- }
- }
-#endif
-
if (what == PW_BACKGROUND) {
while (pWin->backgroundState == ParentRelative)
pWin = pWin->parent;
diff --git a/mi/mioverlay.c b/mi/mioverlay.c
index 7f502fa37..0c99ef015 100644
--- a/mi/mioverlay.c
+++ b/mi/mioverlay.c
@@ -844,8 +844,8 @@ miOverlayHandleExposures(WindowPtr pWin)
if ((mival = pTree->valdata)) {
if (!((*pPriv->InOverlay) (pTree->pWin))) {
if (RegionNotEmpty(&mival->borderExposed)) {
- miPaintWindow(pTree->pWin, &mival->borderExposed,
- PW_BORDER);
+ (*pTree->pWin->drawable.pScreen->PaintWindow)(pTree->pWin, &mival->borderExposed,
+ PW_BORDER);
}
RegionUninit(&mival->borderExposed);
@@ -884,7 +884,7 @@ miOverlayHandleExposures(WindowPtr pWin)
}
else {
if (RegionNotEmpty(&val->after.borderExposed)) {
- miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
+ (*pChild->drawable.pScreen->PaintWindow)(pChild, &val->after.borderExposed, PW_BORDER);
}
(*WindowExposures) (pChild, &val->after.exposed, NullRegion);
}
@@ -984,6 +984,7 @@ miOverlayWindowExposures(WindowPtr pWin,
RegionPtr prgn, RegionPtr other_exposed)
{
RegionPtr exposures = prgn;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
if ((prgn && !RegionNil(prgn)) ||
(exposures && !RegionNil(exposures)) || other_exposed) {
@@ -1002,7 +1003,6 @@ miOverlayWindowExposures(WindowPtr pWin,
}
if (clientInterested && exposures &&
(RegionNumRects(exposures) > RECTLIMIT)) {
- ScreenPtr pScreen = pWin->drawable.pScreen;
miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
BoxRec box;
@@ -1028,7 +1028,7 @@ miOverlayWindowExposures(WindowPtr pWin,
RegionIntersect(prgn, prgn, &pWin->clipList);
}
if (prgn && !RegionNil(prgn))
- miPaintWindow(pWin, prgn, PW_BACKGROUND);
+ (*pScreen->PaintWindow)(pWin, prgn, PW_BACKGROUND);
if (clientInterested && exposures && !RegionNil(exposures))
miSendExposures(pWin, exposures,
pWin->drawable.x, pWin->drawable.y);
@@ -1638,7 +1638,7 @@ miOverlayClearToBackground(WindowPtr pWin,
if (generateExposures)
(*pScreen->WindowExposures) (pWin, &reg, pBSReg);
else if (pWin->backgroundState != None)
- miPaintWindow(pWin, &reg, PW_BACKGROUND);
+ (*pScreen->PaintWindow)(pWin, &reg, PW_BACKGROUND);
RegionUninit(&reg);
if (pBSReg)
RegionDestroy(pBSReg);
diff --git a/mi/miscrinit.c b/mi/miscrinit.c
index 00c15f713..4bf6f5284 100644
--- a/mi/miscrinit.c
+++ b/mi/miscrinit.c
@@ -249,6 +249,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits, /* pointer to screen bits */
pScreen->ValidateTree = miValidateTree;
pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0;
pScreen->WindowExposures = miWindowExposures;
+ pScreen->PaintWindow = miPaintWindow;
/* CopyWindow */
pScreen->ClearToBackground = miClearToBackground;
pScreen->ClipNotify = (ClipNotifyProcPtr) 0;
diff --git a/mi/miwindow.c b/mi/miwindow.c
index 57de91bab..9d68f98e1 100644
--- a/mi/miwindow.c
+++ b/mi/miwindow.c
@@ -113,7 +113,7 @@ miClearToBackground(WindowPtr pWin,
if (generateExposures)
(*pWin->drawable.pScreen->WindowExposures) (pWin, &reg, NULL);
else if (pWin->backgroundState != None)
- miPaintWindow(pWin, &reg, PW_BACKGROUND);
+ (*pWin->drawable.pScreen->PaintWindow)(pWin, &reg, PW_BACKGROUND);
RegionUninit(&reg);
}
@@ -219,7 +219,7 @@ miHandleValidateExposures(WindowPtr pWin)
while (1) {
if ((val = pChild->valdata)) {
if (RegionNotEmpty(&val->after.borderExposed))
- miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
+ (*pChild->drawable.pScreen->PaintWindow)(pChild, &val->after.borderExposed, PW_BORDER);
RegionUninit(&val->after.borderExposed);
(*WindowExposures) (pChild, &val->after.exposed, NullRegion);
RegionUninit(&val->after.exposed);
diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h
index fd9c941f4..dadeab3cb 100644
--- a/miext/rootless/rootlessCommon.h
+++ b/miext/rootless/rootlessCommon.h
@@ -96,6 +96,7 @@ typedef struct _RootlessScreenRec {
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
CreateGCProcPtr CreateGC;
+ PaintWindowProcPtr PaintWindow;
CopyWindowProcPtr CopyWindow;
GetImageProcPtr GetImage;
SourceValidateProcPtr SourceValidate;
diff --git a/miext/rootless/rootlessScreen.c b/miext/rootless/rootlessScreen.c
index 6226ee84a..494ae1a4b 100644
--- a/miext/rootless/rootlessScreen.c
+++ b/miext/rootless/rootlessScreen.c
@@ -473,7 +473,7 @@ expose_1(WindowPtr pWin)
if (!pWin->realized)
return;
- miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND);
+ (*pWin->drawable.pScreen->PaintWindow)(pWin, &pWin->borderClip, PW_BACKGROUND);
/* FIXME: comments in windowstr.h indicate that borderClip doesn't
include subwindow visibility. But I'm not so sure.. so we may
@@ -668,6 +668,7 @@ RootlessWrap(ScreenPtr pScreen)
WRAP(CreateScreenResources);
WRAP(CloseScreen);
WRAP(CreateGC);
+ WRAP(PaintWindow);
WRAP(CopyWindow);
WRAP(GetImage);
WRAP(SourceValidate);
diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c
index 3dbd5886a..a31162589 100644
--- a/miext/rootless/rootlessWindow.c
+++ b/miext/rootless/rootlessWindow.c
@@ -1636,3 +1636,38 @@ RootlessSetPixmapOfAncestors(WindowPtr pWin)
pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
}
}
+
+/*
+ * RootlessPaintWindow
+ *
+ * Wrapper for miPaintWindow
+ *
+ * Returns directly if there is nothing more for miPaintWindow() to do
+ *
+ */
+void
+RootlessPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ DrawablePtr drawable = &pWin->drawable;
+
+ if (!drawable || drawable->type == UNDRAWABLE_WINDOW)
+ return;
+
+ if (IsFramedWindow(pWin)) {
+ RootlessStartDrawing(pWin);
+ RootlessDamageRegion(pWin, pRegion);
+
+ // For ParentRelative windows, if painting background, or with
+ // tiled borders, we have to make sure the window pixmap is
+ // set correctly all the way up the ancestor chain.
+ if (pWin->backgroundState == ParentRelative) {
+ if ((what == PW_BACKGROUND) ||
+ (what == PW_BORDER && !pWin->borderIsPixel))
+ RootlessSetPixmapOfAncestors(pWin);
+ }
+ }
+
+ SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindow);
+ pWin->drawable.pScreen->PaintWindow(pWin, pRegion, what);
+ SCREEN_WRAP(pWin->drawable.pScreen, PaintWindow);
+}
diff --git a/miext/rootless/rootlessWindow.h b/miext/rootless/rootlessWindow.h
index d3955fc89..3b7ea42d3 100644
--- a/miext/rootless/rootlessWindow.h
+++ b/miext/rootless/rootlessWindow.h
@@ -53,6 +53,7 @@ void RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib,
void RootlessResizeWindow(WindowPtr pWin, int x, int y, unsigned int w,
unsigned int h, WindowPtr pSib);
void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
+void RootlessPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
#ifdef __APPLE__
diff --git a/os/Makefile.am b/os/Makefile.am
index a1bbb4d1e..0b0eb79d1 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -1,6 +1,6 @@
noinst_LTLIBRARIES = libos.la
-AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) -DBINDIR=\"$(bindir)\"
SECURERPC_SRCS = rpcauth.c
XDMCP_SRCS = xdmcp.c
diff --git a/os/backtrace.c b/os/backtrace.c
index 3d1195b86..fcc8274e4 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -222,10 +222,25 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
}
#endif /* HAVE_WALKCONTEXT */
-#ifdef HAVE_PSTACK
+#include <sys/types.h>
+#if !defined(__WIN32__) || defined(__CYGWIN__)
+#include <sys/wait.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ fork/exec a program to create a backtrace
+ Returns 0 if successful.
+*/
static int
-xorg_backtrace_pstack(void)
+xorg_backtrace_exec_wrapper(const char *path)
{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ ErrorFSigSafe("Backtrace not implemented on Windows");
+ return -1;
+#else
pid_t kidpid;
int pipefd[2];
@@ -233,7 +248,7 @@ xorg_backtrace_pstack(void)
return -1;
}
- kidpid = fork1();
+ kidpid = fork();
if (kidpid == -1) {
/* ERROR */
@@ -246,11 +261,13 @@ xorg_backtrace_pstack(void)
seteuid(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
+ close(STDERR_FILENO);
dup2(pipefd[1], STDOUT_FILENO);
- closefrom(STDERR_FILENO);
+ dup2(pipefd[1], STDERR_FILENO);
+ close(pipefd[1]);
snprintf(parent, sizeof(parent), "%d", getppid());
- execle("/usr/bin/pstack", "pstack", parent, NULL);
+ execl(path, path, parent, NULL);
exit(1);
}
else {
@@ -263,23 +280,55 @@ xorg_backtrace_pstack(void)
close(pipefd[1]);
while (!done) {
- bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
+ bytesread = 0;
+
+ do
+ {
+ int n = read(pipefd[0], &btline[bytesread], 1);
+
+ if (n <= 0)
+ break;
+
+ bytesread = bytesread + n;
+
+ if (btline[bytesread-1] == '\n')
+ break;
+ }
+ while (bytesread < sizeof(btline));
if (bytesread > 0) {
btline[bytesread] = 0;
ErrorFSigSafe("%s", btline);
}
- else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN)))
+ else if ((bytesread == 0) ||
+ ((errno != EINTR) && (errno != EAGAIN)))
done = 1;
}
close(pipefd[0]);
waitpid(kidpid, &kidstat, 0);
- if (kidstat != 0)
+ if (!(WIFEXITED(kidstat) && WEXITSTATUS(kidstat) == 0)) {
+ ErrorFSigSafe("%s failed with returncode %d\n", path,
+ WEXITSTATUS(kidstat));
return -1;
+ }
}
return 0;
+#endif
+}
+
+#ifdef HAVE_PSTACK
+static int
+xorg_backtrace_pstack(void)
+{
+ return xorg_backtrace_exec_wrapper("/usr/bin/pstack");
+}
+#endif
+
+static int
+xorg_backtrace_script(void)
+{
+ return xorg_backtrace_exec_wrapper(BINDIR "/xorg-backtrace");
}
-#endif /* HAVE_PSTACK */
#if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
@@ -316,7 +365,8 @@ xorg_backtrace(void)
void
xorg_backtrace(void)
{
- return;
+ if (xorg_backtrace_script() == 0)
+ return;
}
#endif
diff --git a/os/connection.c b/os/connection.c
index 40d9ff39b..e243e0b6e 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -422,6 +422,7 @@ CreateWellKnownSockets(void)
else { /* -displayfd and no explicit display number */
Bool found = 0;
for (i = 0; i < 65535 - X_TCP_PORT; i++) {
+ ErrorF("Trying to create socket for display number %d\n", i);
if (TryCreateSocket(i, &partial) && !partial) {
found = 1;
break;
diff --git a/os/log.c b/os/log.c
index 2a721b948..9df8aa7e0 100644
--- a/os/log.c
+++ b/os/log.c
@@ -894,9 +894,9 @@ FatalError(const char *f, ...)
static Bool beenhere = FALSE;
if (beenhere)
- ErrorFSigSafe("\nFatalError re-entered, aborting\n");
+ ErrorFSigSafe("FatalError re-entered, aborting\n");
else
- ErrorFSigSafe("\nFatal server error:\n");
+ ErrorFSigSafe("Fatal server error:\n");
va_start(args, f);
@@ -915,7 +915,8 @@ FatalError(const char *f, ...)
#endif
VErrorFSigSafe(f, args);
va_end(args);
- ErrorFSigSafe("\n");
+ if (f[strlen(f) - 1] != '\n')
+ ErrorFSigSafe("\n");
if (!beenhere)
OsVendorFatalError(f, args2);
va_end(args2);
diff --git a/os/osinit.c b/os/osinit.c
index 4d48ea94e..2791b53f2 100644
--- a/os/osinit.c
+++ b/os/osinit.c
@@ -69,10 +69,7 @@ SOFTWARE.
#if !defined(SYSV) && !defined(WIN32)
#include <sys/resource.h>
#endif
-
-#ifndef ADMPATH
-#define ADMPATH "/usr/adm/X%smsgs"
-#endif
+#include <pthread.h>
extern char *display;
@@ -85,6 +82,7 @@ int limitStackSpace = -1;
#ifdef RLIMIT_NOFILE
int limitNoFile = -1;
#endif
+extern Bool install_os_signal_handler;
static OsSigWrapperPtr OsSigWrapper = NULL;
@@ -125,8 +123,7 @@ OsSigHandler(int signo)
}
}
- /* log, cleanup, and abort */
- xorg_backtrace();
+ ErrorF("Fatal signal received in thread 0x%x\n", pthread_self());
#ifdef SA_SIGINFO
if (sip->si_code == SI_USER) {
@@ -144,6 +141,9 @@ OsSigHandler(int signo)
}
#endif
+ /* log, cleanup, and abort */
+ xorg_backtrace();
+
FatalError("Caught signal %d (%s). Server aborting\n",
signo, strsignal(signo));
}
@@ -160,30 +160,33 @@ OsInit(void)
if (!been_here) {
#if !defined(WIN32) || defined(__CYGWIN__)
- struct sigaction act, oact;
- int i;
-
- int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
- SIGSYS,
- SIGXCPU,
- SIGXFSZ,
+ if (install_os_signal_handler) {
+ struct sigaction act, oact;
+ int i;
+
+ int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
+ SIGSYS,
+ SIGXCPU,
+ SIGXFSZ,
#ifdef SIGEMT
- SIGEMT,
+ SIGEMT,
#endif
- 0 /* must be last */
- };
- sigemptyset(&act.sa_mask);
+ 0 /* must be last */
+ };
+ sigemptyset(&act.sa_mask);
#ifdef SA_SIGINFO
- act.sa_sigaction = OsSigHandler;
- act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = OsSigHandler;
+ act.sa_flags = SA_SIGINFO;
#else
- act.sa_handler = OsSigHandler;
- act.sa_flags = 0;
+ act.sa_handler = OsSigHandler;
+ act.sa_flags = 0;
#endif
- for (i = 0; siglist[i] != 0; i++) {
- if (sigaction(siglist[i], &act, &oact)) {
- ErrorF("failed to install signal handler for signal %d: %s\n",
- siglist[i], strerror(errno));
+ for (i = 0; siglist[i] != 0; i++) {
+ if (sigaction(siglist[i], &act, &oact)) {
+ ErrorF
+ ("failed to install signal handler for signal %d: %s\n",
+ siglist[i], strerror(errno));
+ }
}
}
#endif /* !WIN32 || __CYGWIN__ */
@@ -224,40 +227,7 @@ OsInit(void)
# elif !defined(__CYGWIN__)
fclose(stdin);
fclose(stdout);
-# endif
- /*
- * If a write of zero bytes to stderr returns non-zero, i.e. -1,
- * then writing to stderr failed, and we'll write somewhere else
- * instead. (Apparently this never happens in the Real World.)
- */
- if (write(2, fname, 0) == -1) {
- FILE *err;
-
- if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname)
- snprintf(fname, sizeof(fname), ADMPATH, display);
- else
- strcpy(fname, devnull);
- /*
- * uses stdio to avoid os dependencies here,
- * a real os would use
- * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
- */
- if (!(err = fopen(fname, "a+")))
- err = fopen(devnull, "w");
- if (err && (fileno(err) != 2)) {
- dup2(fileno(err), 2);
- fclose(err);
- }
-#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__)
- {
- static char buf[BUFSIZ];
-
- setvbuf(stderr, buf, _IOLBF, BUFSIZ);
- }
-#else
- setlinebuf(stderr);
#endif
- }
#endif /* !XQUARTZ */
#if !defined(WIN32) || defined(__CYGWIN__)
diff --git a/os/utils.c b/os/utils.c
index ed7581e1c..62a3cbc50 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -122,6 +122,8 @@ __stdcall unsigned long GetTickCount(void);
#include "picture.h"
+Bool install_os_signal_handler = TRUE;
+
Bool noTestExtensions;
#ifdef COMPOSITE
@@ -255,7 +257,7 @@ UnlockServer(void)
#else /* LOCK_SERVER */
static Bool StillLocking = FALSE;
static char LockFile[PATH_MAX];
-static Bool nolock = FALSE;
+Bool nolock = FALSE;
/*
* LockServer --
@@ -553,6 +555,7 @@ UseMsg(void)
#ifdef RLIMIT_STACK
ErrorF("-ls int limit stack space to N Kb\n");
#endif
+ ErrorF("-notrapsignals disable catching of fatal signals\n");
#ifdef LOCK_SERVER
ErrorF("-nolock disable the locking mechanism\n");
#endif
@@ -829,6 +832,9 @@ ProcessCommandLine(int argc, char *argv[])
UseMsg();
}
#endif
+ else if (strcmp(argv[i], "-notrapsignals") == 0) {
+ install_os_signal_handler = FALSE;
+ }
#ifdef LOCK_SERVER
else if (strcmp(argv[i], "-nolock") == 0) {
#if !defined(WIN32) && !defined(__CYGWIN__)
@@ -967,6 +973,7 @@ ProcessCommandLine(int argc, char *argv[])
}
else if (strcmp(argv[i], "-schedInterval") == 0) {
if (++i < argc) {
+ SmartScheduleDisable = FALSE;
SmartScheduleInterval = atoi(argv[i]);
SmartScheduleSlice = SmartScheduleInterval;
}
@@ -975,6 +982,7 @@ ProcessCommandLine(int argc, char *argv[])
}
else if (strcmp(argv[i], "-schedMax") == 0) {
if (++i < argc) {
+ SmartScheduleDisable = FALSE;
SmartScheduleMaxSlice = atoi(argv[i]);
}
else
@@ -1372,6 +1380,26 @@ OsAbort(void)
* as well. As it is now, xkbcomp messages don't end up in the log file.
*/
+#ifdef __CYGWIN__
+#include <process.h>
+int
+System(const char *command)
+{
+ int status;
+
+ if (!command)
+ return 1;
+
+ DebugF("System: `%s'\n", command);
+
+ /*
+ Use spawnl() rather than execl() to implement System() on cygwin to
+ avoid fork emulation overhead and brittleness
+ */
+ status = spawnl(_P_WAIT, "/bin/sh", "sh", "-c", command, (char *) NULL);
+ return status;
+}
+#else
int
System(const char *command)
{
@@ -1413,6 +1441,7 @@ System(const char *command)
return p == -1 ? -1 : status;
}
+#endif
static struct pid {
struct pid *next;
@@ -1724,6 +1753,17 @@ System(const char *cmdline)
return dwExitCode;
}
+#elif defined(__CYGWIN__)
+const char*
+Win32TempDir(void)
+{
+ if (getenv("TEMP") != NULL)
+ return getenv("TEMP");
+ else if (getenv("TMP") != NULL)
+ return getenv("TMP");
+ else
+ return "/tmp";
+}
#endif
/*
diff --git a/pseudoramiX/pseudoramiX.h b/pseudoramiX/pseudoramiX.h
index f063919dd..5393062ee 100644
--- a/pseudoramiX/pseudoramiX.h
+++ b/pseudoramiX/pseudoramiX.h
@@ -2,8 +2,6 @@
* Minimal implementation of PanoramiX/Xinerama
*/
-extern int noPseudoramiXExtension;
-
void
PseudoramiXAddScreen(int x, int y, int w, int h);
void
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index 76d728c70..128459850 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -84,6 +84,8 @@ static int ProcRRXineramaIsActive(ClientPtr client);
static int ProcRRXineramaQueryScreens(ClientPtr client);
static int SProcRRXineramaDispatch(ClientPtr client);
+Bool noRRXineramaExtension = FALSE;
+
/* Proc */
int
@@ -480,6 +482,9 @@ RRXineramaExtensionInit(void)
return;
#endif
+ if (noRRXineramaExtension)
+ return;
+
/*
* Xinerama isn't capable enough to have multiple protocol screens each
* with their own output geometry. So if there's more than one protocol
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 1dc0e4eee..78b28c0fc 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -44,6 +44,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <xkbsrv.h>
#include <X11/extensions/XI.h>
#include "xkb.h"
+#include "os.h"
/*
* If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
@@ -113,7 +114,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
const char *xkbbindir = emptystring;
const char *xkbbindirsep = emptystring;
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* WIN32 has no popen. The input must be stored in a file which is
used as input for xkbcomp. xkbcomp does not read from stdin. */
char tmpname[PATH_MAX];
@@ -126,9 +127,9 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
strcpy(tmpname, Win32TempDir());
- strcat(tmpname, "\\xkb_XXXXXX");
+ strcat(tmpname, PATHSEPARATOR "xkb_XXXXXX");
(void) mktemp(tmpname);
#endif
@@ -167,7 +168,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
return NULL;
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
out = Popen(buf, "w");
#else
out = fopen(tmpname, "w");
@@ -177,7 +178,7 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
/* Now write to xkbcomp */
(*callback)(out, userdata);
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
if (Pclose(out) == 0)
#else
if (fclose(out) == 0 && System(buf) >= 0)
@@ -186,14 +187,14 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
if (xkbDebugFlags)
DebugF("[xkb] xkb executes: %s\n", buf);
free(buf);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return xnfstrdup(keymap);
}
else
LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* remove the temporary file */
unlink(tmpname);
#endif