summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2014-01-06 18:17:41 +0000
committerJon TURNEY <jon.turney@dronecode.org.uk>2014-01-06 18:17:41 +0000
commit24cc1f4d9f4475d1b0c256586fb8760dc1d92847 (patch)
treeb9f638ca790a70a511016462fdae12dd4455ad8a
parent2ea973e12f5d954211e1d10085a4c74581b43aca (diff)
parentb1e9e319cb302d138eef484b9878ec670735a340 (diff)
Merge branch 'cygwin-patches-for-1.15' into cygwin-release-1.15xserver-cygwin-1.15.0-1
-rw-r--r--composite/compwindow.c2
-rw-r--r--configure.ac14
-rw-r--r--dix/dispatch.c2
-rw-r--r--dix/globals.c1
-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/glxdricommon.c8
-rw-r--r--glx/glxdriswrast.c36
-rw-r--r--glx/glxext.c1
-rw-r--r--glx/glxscreens.c16
-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.c225
-rw-r--r--hw/xwin/Makefile.am26
-rwxr-xr-xhw/xwin/XWin.exe.manifest14
-rw-r--r--hw/xwin/XWin.rc3
-rwxr-xr-xhw/xwin/glx/gen_gl_wrappers.py45
-rw-r--r--hw/xwin/glx/glthunk.c4
-rw-r--r--hw/xwin/glx/winpriv.c34
-rw-r--r--hw/xwin/man/XWin.man15
-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)90
-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)315
-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.c151
-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.c310
-rw-r--r--hw/xwin/windialogs.c63
-rw-r--r--hw/xwin/windisplay.c60
-rw-r--r--hw/xwin/windisplay.h34
-rw-r--r--hw/xwin/winerror.c10
-rw-r--r--hw/xwin/winglobals.c14
-rw-r--r--hw/xwin/winglobals.h5
-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/winmsgwindow.c4
-rw-r--r--hw/xwin/winmultiwindowicons.c520
-rw-r--r--hw/xwin/winmultiwindowicons.h4
-rw-r--r--hw/xwin/winmultiwindowwindow.c281
-rw-r--r--hw/xwin/winmultiwindowwm.c316
-rw-r--r--hw/xwin/winmultiwindowwndproc.c117
-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.h4
-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.c355
-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/opaque.h1
-rw-r--r--include/os.h6
-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.c54
-rw-r--r--os/connection.c25
-rw-r--r--os/log.c7
-rw-r--r--os/osinit.c86
-rw-r--r--os/utils.c44
-rw-r--r--pseudoramiX/pseudoramiX.h2
-rw-r--r--randr/rrxinerama.c5
-rw-r--r--xkb/ddxLoad.c15
109 files changed, 4493 insertions, 2530 deletions
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 0be7a1b34..f61600e9e 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -104,7 +104,7 @@ compRepaintBorder(ClientPtr pClient, pointer 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 8f823863d..ed650defa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,6 +83,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)'
@@ -2084,7 +2094,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])
@@ -2506,6 +2516,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 8dcd9cbcf..f2a136896 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/globals.c b/dix/globals.c
index ad9145b01..1cc622bba 100644
--- a/dix/globals.c
+++ b/dix/globals.c
@@ -128,6 +128,7 @@ int monitorResolution = 0;
char *display;
int displayfd;
+Bool explicit_display = FALSE;
char *ConnectionInfo;
CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
diff --git a/dix/main.c b/dix/main.c
index 05dcbeddd..bbed32241 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 0e9109e89..7a7b6d3fe 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 b8da04882..291774812 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
@@ -402,7 +409,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/glxdricommon.c b/glx/glxdricommon.c
index fc902729d..191130056 100644
--- a/glx/glxdricommon.c
+++ b/glx/glxdricommon.c
@@ -144,10 +144,14 @@ createModeFromConfig(const __DRIcoreExtension * core,
renderType |= GLX_RGBA_BIT;
if (value & __DRI_ATTRIB_COLOR_INDEX_BIT)
renderType |= GLX_COLOR_INDEX_BIT;
+#ifdef __DRI_ATTRIB_FLOAT_BIT
if (value & __DRI_ATTRIB_FLOAT_BIT)
renderType |= GLX_RGBA_FLOAT_BIT_ARB;
+#endif
+#ifdef __DRI_ATTRIB_UNSIGNED_FLOAT_BIT
if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT)
renderType |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
+#endif
break;
case __DRI_ATTRIB_CONFIG_CAVEAT:
if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
@@ -193,8 +197,12 @@ render_type_is_pbuffer_only(unsigned renderType)
* GLXFBConfig must have the GLX_PBUFFER_BIT bit set and the
* GLX_RENDER_TYPE attribute must have the GLX_RGBA_FLOAT_BIT set."
*/
+#if defined(__DRI_ATTRIB_UNSIGNED_FLOAT_BIT) && defined(__DRI_ATTRIB_FLOAT_BIT)
return !!(renderType & (__DRI_ATTRIB_UNSIGNED_FLOAT_BIT
| __DRI_ATTRIB_FLOAT_BIT));
+#else
+ return 0;
+#endif
}
__GLXconfig *
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index cbc109a6d..67c6547bc 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 {
@@ -406,12 +408,27 @@ 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++) {
+#ifdef __DRI_READ_DRAWABLE
+ 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");
+ }
+#endif
+
#ifdef __DRI_COPY_SUB_BUFFER
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");
}
#endif
@@ -419,6 +436,7 @@ initializeExtensions(__GLXDRIscreen * screen)
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");
}
#endif
/* Ignore unknown extensions */
@@ -433,6 +451,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
{
const char *driverName = "swrast";
__GLXDRIscreen *screen;
+ size_t buffer_size;
screen = calloc(1, sizeof *screen);
if (screen == NULL)
@@ -444,6 +463,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,
@@ -472,6 +493,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 316b4f6e8..f93642b0c 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -140,6 +140,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);
if (c == __glXLastContext)
__glXFlushContextCache();
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/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 d7f259d28..f15c2d8e7 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -315,8 +315,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 5b977c7f9..1a493e178 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 36346b7e1..c42418c23 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 b05ca2736..f187c88c2 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,32 +56,24 @@ 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
+
/*
* 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[]);
@@ -97,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
@@ -122,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 +176,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 +264,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 +290,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 +302,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 +341,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 +355,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
@@ -783,6 +772,9 @@ winUseMsg(void)
ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
+ ErrorF("-hostintitle\n"
+ "\tIn multiwindow mode, add remote host names to window titles.\n");
+
ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
#ifdef XWIN_MULTIWINDOWEXTWM
@@ -951,14 +943,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())
@@ -1010,6 +994,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 */
@@ -1018,11 +1057,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
@@ -1030,70 +1082,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 7f0eaf097..b4fa663d3 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)/Xext/dpmsstubs.c \
$(top_srcdir)/Xi/stubs.c \
@@ -155,12 +152,13 @@ AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless
XWIN_SYS_LIBS += -ldxguid
XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.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_DEPENDENCIES = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
+XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS) \
+ $(CLIPBOARD_LIBS) $(XWIN_GLX_SYS_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) $(MULTIWINDOW_SYS_LIBS)
XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup
.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
@@ -192,5 +190,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) .
+SUBDIRS = man $(GLX_DIR) wmutil winclipboard .
DIST_SUBDIRS = man glx .
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/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py
index 683b9d903..cdbba638a 100755
--- a/hw/xwin/glx/gen_gl_wrappers.py
+++ b/hw/xwin/glx/gen_gl_wrappers.py
@@ -43,35 +43,18 @@ thunkdefs=False
staticwrappers=False
nodebug=False
-#exclude base WGL API
-WinGDI={key: 1 for key in [
- "wglCopyContext"
- ,"wglCreateContext"
- ,"wglCreateLayerContext"
- ,"wglDeleteContext"
- ,"wglGetCurrentContext"
- ,"wglGetCurrentDC"
- ,"wglGetProcAddress"
- ,"wglMakeCurrent"
- ,"wglShareLists"
- ,"wglUseFontBitmapsA"
- ,"wglUseFontBitmapsW"
- ,"wglUseFontBitmaps"
- ,"SwapBuffers"
- ,"wglUseFontOutlinesA"
- ,"wglUseFontOutlinesW"
- ,"wglUseFontOutlines"
- ,"wglDescribeLayerPlane"
- ,"wglSetLayerPaletteEntries"
- ,"wglGetLayerPaletteEntries"
- ,"wglRealizeLayerPalette"
- ,"wglSwapLayerBuffers"
- ,"wglSwapMultipleBuffers"
- ,"ChoosePixelFormat"
- ,"DescribePixelFormat"
- ,"GetEnhMetaFilePixelFormat"
- ,"GetPixelFormat"
- ,"SetPixelFormat"
+# list of WGL extension functions we use
+used_wgl_ext_fns = {key: 1 for key in [
+ "wglSwapIntervalEXT",
+ "wglGetExtensionsStringARB",
+ "wglDestroyPbufferARB",
+ "wglGetPbufferDCARB",
+ "wglReleasePbufferDCARB",
+ "wglCreatePbufferARB",
+ "wglMakeContextCurrentARB",
+ "wglChoosePixelFormatARB",
+ "wglGetPixelFormatAttribivARB",
+ "wglGetPixelFormatAttribivARB"
]}
if __name__ == '__main__':
@@ -162,7 +145,7 @@ class PreResolveOutputGenerator(OutputGenerator):
def genCmd(self, cmd, name):
OutputGenerator.genCmd(self, cmd, name)
- if name in WinGDI:
+ if prefix == 'wgl' and not name in used_wgl_ext_fns:
return
self.outFile.write('RESOLVE_DECL(PFN' + name.upper() + 'PROC);\n')
@@ -190,7 +173,7 @@ class WrapperOutputGenerator(OutputGenerator):
def genCmd(self, cmd, name):
OutputGenerator.genCmd(self, cmd, name)
- if name in WinGDI:
+ if prefix == 'wgl' and not name in used_wgl_ext_fns:
return
proto=noneStr(cmd.elem.find('proto'))
diff --git a/hw/xwin/glx/glthunk.c b/hw/xwin/glx/glthunk.c
index d49fe487c..24dc70d5a 100644
--- a/hw/xwin/glx/glthunk.c
+++ b/hw/xwin/glx/glthunk.c
@@ -34,10 +34,10 @@
#include <X11/Xwindows.h>
#define GL_GLEXT_LEGACY
-#include <GL/gl.h>
+#include <w32api/GL/gl.h>
#undef GL_ARB_imaging
#undef GL_VERSION_1_3
-#include <GL/glext.h>
+#include <w32api/GL/glext.h>
static PROC
glWinResolveHelper(PROC * cache, const char *symbol)
diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c
index 4f6e4ffd5..11612f905 100644
--- a/hw/xwin/glx/winpriv.c
+++ b/hw/xwin/glx/winpriv.c
@@ -14,6 +14,36 @@
void
winCreateWindowsWindow(WindowPtr pWin);
+static void
+winCreateWindowsWindowHierarchy(WindowPtr pWin)
+{
+ winWindowPriv(pWin);
+
+ winDebug("winCreateWindowsWindowHierarchy - pWin:%08x XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ /* recursively ensure parent window exists if it's not the root window */
+ if (pWin->parent) {
+ if (pWin->parent != pWin->drawable.pScreen->root)
+ 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 +80,8 @@ winGetWindowInfo(WindowPtr pWin)
}
if (pWinPriv->hWnd == NULL) {
- winCreateWindowsWindow(pWin);
- ErrorF("winGetWindowInfo: forcing window to exist...\n");
+ ErrorF("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 18ee667d4..9a046d930 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]] ] "
@@ -165,10 +168,16 @@ The maximum dimensions of the screen are the dimensions of the \fIWindows\fP vir
on its own is equivalent to \fB\-resize=randr\fP
.RE
+.SH OPTIONS FOR MULTIWINDOW MODE
+.TP 8
+.B \-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.
+
.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]"
@@ -194,6 +203,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
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..5ff3abad6 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 -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 ce89348fe..5be4659de 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 a6a7366a4..59e023479 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..bcf45ca4d 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,46 +29,19 @@
* 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)
@@ -77,18 +49,8 @@
* 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 +66,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..1653747ea 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);
+ winClipboardWindowDestroy();
}
/* 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 recieve 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_DESTROY, 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..b5566fa5a 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,9 @@ 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;
/* Branch on message type */
switch (message) {
@@ -162,6 +166,11 @@ 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;
+
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
if (first == hwnd)
return 0; /* Make sure it's not us! */
@@ -185,8 +194,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 +250,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 +267,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;
@@ -314,6 +314,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 +354,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 +388,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 +398,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 - "
@@ -409,11 +439,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_RENDERALLFORMATS:
{
int iReturn;
- Display *pDisplay = g_pClipboardDisplay;
- Window iWindow = g_iClipboardWindow;
Bool fConvertToUnicode;
+ Bool pasted = FALSE;
- winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
+ if (message == WM_RENDERALLFORMATS)
+ winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");
+ else
+ winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
+ wParam);
/* Flag whether to convert to Unicode or not */
if (message == WM_RENDERALLFORMATS)
@@ -421,20 +454,89 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
else
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;
}
+ winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");
+
+ /* Request the selection's supported conversion targets */
+ XConvertSelection(pDisplay,
+ selection,
+ atoms->atomTargets,
+ atoms->atomLocalProperty,
+ iWindow, CurrentTime);
+
+ /* Process X events */
+ ClipboardConversionData data;
+ data.fUseUnicode = fConvertToUnicode;
+ iReturn = winProcessXEventsTimeout(hwnd,
+ iWindow,
+ pDisplay,
+ &data,
+ atoms,
+ WIN_POLL_TIMEOUT);
+
+ if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
+ ErrorF
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
+ goto fake_paste;
+ }
+
+ /* 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);
+
/* Special handling for WM_RENDERALLFORMATS */
if (message == WM_RENDERALLFORMATS) {
/* We must open and empty the clipboard */
@@ -445,52 +547,59 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
if (!OpenClipboard(hwnd)) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "OpenClipboard () failed: %08x\n",
- GetLastError());
- break;
+ ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ "OpenClipboard () failed: %08x\n",
+ GetLastError());
}
if (!EmptyClipboard()) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "EmptyClipboard () failed: %08x\n",
- GetLastError());
- break;
+ ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ "EmptyClipboard () failed: %08x\n",
+ GetLastError());
}
}
- /* Process the SelectionNotify event */
+ /* 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) {
+ if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
+ ErrorF
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
+ }
+ else {
+ pasted = TRUE;
+ }
+
+ /*
+ * 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);
-
- ErrorF
- ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\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;
+ ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
+ "CloseClipboard () failed: %08x\n",
+ GetLastError());
}
}
@@ -507,7 +616,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 226c3f055..1861b40cc 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,
@@ -634,7 +736,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);
@@ -651,7 +753,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);
@@ -681,21 +783,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 304e6df9f..79b0f14a4 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;
+
+ /* 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;
+ }
-extern pthread_t g_ptClipboardProc;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
-extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
+ 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,20 @@ winInitClipboard(void)
return TRUE;
}
-/*
- * Create the Windows window that we use to recieve 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 9e38113a5..0a8da9c70 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 94571ff71..4cf7ab1d6 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 a35336a34..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,300 +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 =
- (uint32_t *) 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 =
- (uint32_t *) calloc(pScreenPriv->cursor.sm_cx *
- pScreenPriv->cursor.sm_cy, sizeof(char));
-
- 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 054ee95b5..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
*/
@@ -574,10 +567,7 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
winInitDialog(hwndDialog);
/* Override the URL buttons */
- winOverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
winOverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
- winOverrideURLButton(hwndDialog, ID_ABOUT_UG);
- winOverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
return TRUE;
@@ -608,28 +598,8 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
/* Restore window procedures for URL buttons */
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
-
- return TRUE;
-
- case ID_ABOUT_CHANGELOG:
- {
- INT_PTR iReturn;
-
- const char *pszWinPath = "http://x.cygwin.com/"
- "devel/server/changelog.html";
- iReturn = (INT_PTR) ShellExecute(NULL,
- "open",
- pszWinPath, NULL, NULL, SW_MAXIMIZE);
- if (iReturn < 32) {
- ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
- "ShellExecute failed: %d\n", (int)iReturn);
- }
- }
return TRUE;
case ID_ABOUT_WEBSITE:
@@ -647,36 +617,6 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
}
}
return TRUE;
-
- case ID_ABOUT_UG:
- {
- const char *pszPath = "http://x.cygwin.com/docs/ug/";
- INT_PTR iReturn;
-
- iReturn = (INT_PTR) ShellExecute(NULL,
- "open",
- pszPath, NULL, NULL, SW_MAXIMIZE);
- if (iReturn < 32) {
- ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
- "ShellExecute failed: %d\n", (int)iReturn);
- }
- }
- return TRUE;
-
- case ID_ABOUT_FAQ:
- {
- const char *pszPath = "http://x.cygwin.com/docs/faq/";
- INT_PTR iReturn;
-
- iReturn = (INT_PTR) ShellExecute(NULL,
- "open",
- pszPath, NULL, NULL, SW_MAXIMIZE);
- if (iReturn < 32) {
- ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
- "ShellExecute failed: %d\n", (int)iReturn);
- }
- }
- return TRUE;
}
break;
@@ -690,10 +630,7 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
/* Restore window procedures for URL buttons */
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
- winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
return TRUE;
}
diff --git a/hw/xwin/windisplay.c b/hw/xwin/windisplay.c
new file mode 100644
index 000000000..6f07f97ea
--- /dev/null
+++ b/hw/xwin/windisplay.c
@@ -0,0 +1,60 @@
+/*
+ * 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"
+
+/*
+ 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 (TransIsListening("local")) {
+ snprintf(szDisplay, 512, ":%s.%d", display, screen);
+ }
+ else if (TransIsListening("inet")) {
+ snprintf(szDisplay, 512, "127.0.0.1:%s.%d", display, screen);
+ }
+ else if (TransIsListening("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/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 d28132247..ad82b83f6 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -78,6 +78,7 @@ Bool g_fNoHelpMessageBox = FALSE;
Bool g_fSoftwareCursor = FALSE;
Bool g_fSilentDupError = FALSE;
Bool g_fNativeGl = TRUE;
+Bool g_fHostInTitle = FALSE;
pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
#ifdef XWIN_CLIPBOARD
@@ -85,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
* Wrapped DIX functions
*/
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
-winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
/*
* Clipboard variables
@@ -93,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
/*
@@ -111,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 58a919c65..d7b813dbb 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -54,6 +54,7 @@ extern Bool g_fXdmcpEnabled;
extern Bool g_fNoHelpMessageBox;
extern Bool g_fSilentDupError;
extern Bool g_fNativeGl;
+extern Bool g_fHostInTitle;
extern HWND g_hDlgDepthChange;
extern HWND g_hDlgExit;
@@ -71,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 9c5d4e9cd..1f4518770 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, pointer 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/winmsgwindow.c b/hw/xwin/winmsgwindow.c
index 8067c693c..59f1da503 100644
--- a/hw/xwin/winmsgwindow.c
+++ b/hw/xwin/winmsgwindow.c
@@ -22,6 +22,10 @@
*
*/
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
#include "win.h"
/*
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index 0531ad6c7..4ac8bffdf 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -32,514 +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;
- 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]) {
- /* Find an exact match to the size we require... */
- if (icon[0] == iconSize && icon[1] == iconSize) {
- winDebug("winXIconToHICON: found %lu x %lu NetIcon\n", icon[0],
- icon[1]);
- 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 %lu x %lu NetIcon for scaling to %u x %u\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
*/
@@ -549,16 +57,20 @@ 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);
- /* 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));
+ hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON));
+ hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON));
+ }
/* If we got the small, but not the large one swap them */
if (!hIcon && hIconSmall) {
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 44ad19302..a74577ed9 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(pointer value, XID id, pointer 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;
@@ -513,8 +579,8 @@ winCreateWindowsWindow(WindowPtr pWin)
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) {
@@ -534,7 +600,11 @@ winCreateWindowsWindow(WindowPtr pWin)
}
}
- /* 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 +642,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 +675,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, pointer 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 +791,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 +806,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 +841,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 +1129,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 1dd8ba5b3..4a626161d 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,8 +71,9 @@
#include "winwindow.h"
#include "winprefs.h"
#include "window.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
+#include "winmultiwindowicons.h"
+#include "windisplay.h"
+#include "winglobals.h"
#ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h>
@@ -69,9 +83,16 @@
#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
#endif
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
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
@@ -111,6 +132,7 @@ typedef struct _WMInfo {
WMMsgQueueRec wmMsgQueue;
Atom atmWmProtos;
Atom atmWmDelete;
+ Atom atmWmTakeFocus;
Atom atmPrivMap;
Bool fAllowOtherWM;
} WMInfoRec, *WMInfoPtr;
@@ -166,6 +188,9 @@ static int
static int
winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay);
+static void
+winMultiWindowThreadExit(void *arg);
+
static int
winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -183,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
@@ -429,7 +454,10 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
{
int nResult;
XTextProperty xtpWindowName;
+ XTextProperty xtpClientMachine;
char *pszWindowName;
+ char *pszClientMachine;
+ char hostname[HOST_NAME_MAX + 1];
#if CYGMULTIWINDOW_DEBUG
ErrorF("GetWindowName\n");
@@ -449,10 +477,65 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName);
XFree(xtpWindowName.value);
+
+ if (g_fHostInTitle) {
+ /* Try to get client machine name */
+ nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine);
+ if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) {
+ pszClientMachine =
+ Xutf8TextPropertyToString(pDisplay, &xtpClientMachine);
+ XFree(xtpClientMachine.value);
+
+ /*
+ If we have a client machine name
+ and it's not the local host name...
+ */
+ if (strlen(pszClientMachine) &&
+ !gethostname(hostname, HOST_NAME_MAX + 1) &&
+ strcmp(hostname, pszClientMachine)) {
+ /* ... add ' (on <clientmachine>)' to end of window name */
+ *ppWindowName =
+ malloc(strlen(pszWindowName) +
+ strlen(pszClientMachine) + 7);
+ strcpy(*ppWindowName, pszWindowName);
+ strcat(*ppWindowName, " (on ");
+ strcat(*ppWindowName, pszClientMachine);
+ strcat(*ppWindowName, ")");
+
+ free(pszWindowName);
+ free(pszClientMachine);
+
+ return;
+ }
+ }
+ }
+
+ /* otherwise just return the window name */
*ppWindowName = pszWindowName;
}
/*
+ * Does the client support the specified WM_PROTOCOLS protocol?
+ */
+
+static Bool
+IsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol)
+{
+ int i, n, found = 0;
+ Atom *protocols;
+
+ if (XGetWMProtocols(pDisplay, iWindow, &protocols, &n)) {
+ for (i = 0; i < n; ++i)
+ if (protocols[i] == atmProtocol)
+ ++found;
+
+ XFree(protocols);
+ }
+
+ return found > 0;
+}
+
+/*
* Send a message to the X server from the WM thread
*/
@@ -462,6 +545,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;
@@ -627,6 +711,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
@@ -680,6 +767,8 @@ winMultiWindowWMProc(void *pArg)
WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
/* Initialize the Window Manager */
winInitMultiWindowWM(pWMInfo, pProcArg);
@@ -805,21 +894,10 @@ winMultiWindowWMProc(void *pArg)
ErrorF("\tWM_WM_KILL\n");
#endif
{
- int i, n, found = 0;
- Atom *protocols;
-
- /* --- */
- if (XGetWMProtocols(pWMInfo->pDisplay,
- pNode->msg.iWindow, &protocols, &n)) {
- for (i = 0; i < n; ++i)
- if (protocols[i] == pWMInfo->atmWmDelete)
- ++found;
-
- XFree(protocols);
- }
-
/* --- */
- if (found)
+ if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+ pNode->msg.iWindow,
+ pWMInfo->atmWmDelete))
SendXMessage(pWMInfo->pDisplay,
pNode->msg.iWindow,
pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
@@ -832,11 +910,39 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("\tWM_WM_ACTIVATE\n");
#endif
-
/* Set the input focus */
- XSetInputFocus(pWMInfo->pDisplay,
- pNode->msg.iWindow,
- RevertToPointerRoot, CurrentTime);
+
+ /*
+ ICCCM 4.1.7 is pretty opaque, but it appears that the rules are
+ actually quite simple:
+ -- the WM_HINTS input field determines whether the WM should call
+ XSetInputFocus()
+ -- independently, the WM_TAKE_FOCUS protocol determines whether
+ the WM should send a WM_TAKE_FOCUS ClientMessage.
+ */
+ {
+ Bool neverFocus = FALSE;
+ XWMHints *hints = XGetWMHints(pWMInfo->pDisplay, pNode->msg.iWindow);
+
+ if (hints) {
+ if (hints->flags & InputHint)
+ neverFocus = !hints->input;
+ XFree(hints);
+ }
+
+ if (!neverFocus)
+ XSetInputFocus(pWMInfo->pDisplay,
+ pNode->msg.iWindow,
+ RevertToPointerRoot, CurrentTime);
+
+ if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+ pNode->msg.iWindow,
+ pWMInfo->atmWmTakeFocus))
+ SendXMessage(pWMInfo->pDisplay,
+ pNode->msg.iWindow,
+ pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus);
+
+ }
break;
case WM_WM_NAME_EVENT:
@@ -890,6 +996,9 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+
+ pthread_cleanup_pop(0);
+
return NULL;
}
@@ -913,6 +1022,8 @@ winMultiWindowXMsgProc(void *pArg)
int iReturn;
XIconSize *xis;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
winDebug("winMultiWindowXMsgProc - Hello\n");
/* Check that argument pointer is not invalid */
@@ -933,17 +1044,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);
@@ -971,8 +1071,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);
@@ -1027,7 +1126,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);
}
@@ -1166,6 +1265,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));
@@ -1220,7 +1323,7 @@ winMultiWindowXMsgProc(void *pArg)
}
XCloseDisplay(pProcArg->pDisplay);
- pthread_exit(NULL);
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -1326,17 +1429,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);
@@ -1364,8 +1456,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);
@@ -1404,6 +1495,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
"WM_PROTOCOLS", False);
pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
"WM_DELETE_WINDOW", False);
+ pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay,
+ "WM_TAKE_FOCUS", False);
pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
WINDOWSWM_NATIVE_HWND, False);
@@ -1413,7 +1506,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
if (cursor) {
XDefineCursor(pWMInfo->pDisplay,
- DefaultRootWindow(pWMInfo->pDisplay), cursor);
+ XDefaultRootWindow(pWMInfo->pDisplay), cursor);
XFreeCursor(pWMInfo->pDisplay, cursor);
}
}
@@ -1522,6 +1615,17 @@ winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay)
}
/*
+ * winMultiWindowThreadExit - Thread exit handler
+ */
+
+static void
+winMultiWindowThreadExit(void *arg)
+{
+ /* multiwindow client thread has exited, stop server as well */
+ kill(getpid(), SIGTERM);
+}
+
+/*
* Catch RedirectError to detect other window manager running
*/
@@ -1546,7 +1650,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);
@@ -1558,7 +1662,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);
@@ -1576,6 +1680,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)
@@ -1594,7 +1732,7 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
{
static Atom windowState, motif_wm_hints, windowType;
static Atom hiddenState, fullscreenState, belowState, aboveState,
- skiptaskbarState;
+ skiptaskbarState, vertMaxState, horzMaxState;
static Atom dockWindow;
static int generation;
Atom type, *pAtom = NULL;
@@ -1621,12 +1759,17 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", 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;
@@ -1641,8 +1784,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);
}
}
@@ -1832,57 +1982,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 abb87ee4b..184efa5ab 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);
@@ -316,6 +317,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static Bool s_fTracking = FALSE;
Bool needRestack = FALSE;
LRESULT ret;
+ static Bool hasEnteredSizeMove = FALSE;
#if CYGDEBUG
winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
@@ -872,7 +874,9 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_MOVE:
/* Adjust the X Window to the moved Windows window */
- winAdjustXWindow(pWin, hwnd);
+ if (!hasEnteredSizeMove)
+ winAdjustXWindow(pWin, hwnd);
+ /* else: Wait for WM_EXITSIZEMOVE */
return 0;
case WM_SHOWWINDOW:
@@ -1005,6 +1009,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
*/
break;
+ case WM_ENTERSIZEMOVE:
+ hasEnteredSizeMove = TRUE;
+ return 0;
+
+ case WM_EXITSIZEMOVE:
+ /* Adjust the X Window to the moved Windows window */
+ hasEnteredSizeMove = FALSE;
+ winAdjustXWindow(pWin, hwnd);
+ return 0;
+
case WM_SIZE:
/* see dix/window.c */
#if CYGWINDOWING_DEBUG
@@ -1029,8 +1043,13 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
(int) (GetTickCount()));
}
#endif
- /* Adjust the X Window to the moved Windows window */
- winAdjustXWindow(pWin, hwnd);
+ 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 */
case WM_STYLECHANGING:
@@ -1140,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 15f707766..c51b61035 100644
--- a/hw/xwin/winprefslex.l
+++ b/hw/xwin/winprefslex.l
@@ -91,6 +91,12 @@ DEBUG { return DEBUGOUTPUT; }
RELOAD { return RELOAD; }
TRAYICON { return TRAYICON; }
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 3b376b3e7..72677b54f 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 858be4a56..bb6efc3da 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")
@@ -1074,6 +1107,11 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
+ if (IS_OPTION("-hostintitle")) {
+ g_fHostInTitle = TRUE;
+ return 1;
+ }
+
return 0;
}
@@ -1145,6 +1183,115 @@ winLogCommandLine(int argc, char *argv[])
}
/*
+ * Detect the OS
+ */
+
+typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+static void
+winOS(void)
+{
+ OSVERSIONINFOEX osvi = { 0 };
+ char *windowstype = "Unknown";
+ char *prodName = "Unknown";
+ 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
*/
@@ -1161,8 +1308,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 a14d402e1..37e92ce61 100644
--- a/hw/xwin/winresource.h
+++ b/hw/xwin/winresource.h
@@ -43,10 +43,8 @@
#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_UG 300
-#define ID_ABOUT_FAQ 301
-#define ID_ABOUT_CHANGELOG 302
#define ID_ABOUT_WEBSITE 303
#endif
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 01097f295..9fc3a15ea 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 724976a84..2785323db 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -41,6 +41,7 @@
#include <X11/extensions/windowswmstr.h>
#include "dixevents.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 c73a75c6f..4a4740048 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..be8c96a2d
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.c
@@ -0,0 +1,355 @@
+/*
+ *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 =
+ (uint32_t *) 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 =
+ (uint32_t *) calloc(sm_cx * sm_cy, sizeof(char));
+
+ 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..b127eb1e9
--- /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 may overflow an int and thus is bigger than the
+ property can possibly be */
+ if ((icon[0] > 0xFFFF) || (icon[1] > 0xFFFF)) {
+ winDebug("winXIconToHICON: malformed _NET_WM_ICON data\n");
+ break;
+ }
+
+ /* Icon data size is bigger than amount of data remaining */
+ if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
+ winDebug("winXIconToHICON: malformed _NET_WM_ICON data\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);
+ 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/opaque.h b/include/opaque.h
index b76ab6e6b..5b73a24c7 100644
--- a/include/opaque.h
+++ b/include/opaque.h
@@ -51,6 +51,7 @@ extern _X_EXPORT int defaultScreenSaverBlanking;
extern _X_EXPORT int defaultScreenSaverAllowExposures;
extern _X_EXPORT char *display;
extern _X_EXPORT int displayfd;
+extern _X_EXPORT Bool explicit_display;
extern _X_EXPORT int defaultBackingStore;
extern _X_EXPORT Bool disableBackingStore;
diff --git a/include/os.h b/include/os.h
index 9b6729421..8fdbcc38a 100644
--- a/include/os.h
+++ b/include/os.h
@@ -121,6 +121,8 @@ extern _X_EXPORT int WriteToClient(ClientPtr /*who */ , int /*count */ ,
extern _X_EXPORT void ResetOsBuffers(void);
+extern _X_EXPORT int TransIsListening(char *protocol);
+
extern _X_EXPORT void InitConnectionLimits(void);
extern _X_EXPORT void NotifyParentProcess(void);
@@ -367,6 +369,10 @@ extern _X_EXPORT pointer
Fopen(const char *, const char *);
extern _X_EXPORT int
Fclose(pointer);
+#if defined(__CYGWIN__)
+extern const char *
+Win32TempDir(void);
+#endif
#else
extern const char *
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index df7407391..3885a7771 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 */ );
@@ -403,6 +407,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 b103551fa..a4020139b 100644
--- a/man/Xserver.man
+++ b/man/Xserver.man
@@ -563,9 +563,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 8b7c93fb8..881c9698f 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 2bfd5e401..018f78a15 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 4698b532f..f8e6706ee 100644
--- a/mi/miscrinit.c
+++ b/mi/miscrinit.c
@@ -249,6 +249,7 @@ miScreenInit(ScreenPtr pScreen, pointer 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 8dd99dbf0..4b33ca6a4 100644
--- a/mi/miwindow.c
+++ b/mi/miwindow.c
@@ -112,7 +112,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);
}
@@ -218,7 +218,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 a1af3e7ac..4e7ecf4d3 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 7e3c28130..e4ada0700 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..3100d1a13 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);
+ execle(path, path, parent, NULL, NULL);
exit(1);
}
else {
@@ -269,17 +286,35 @@ xorg_backtrace_pstack(void)
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 +351,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 162e1d93e..20a9f008d 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -269,6 +269,21 @@ lookup_trans_conn(int fd)
return NULL;
}
+int
+TransIsListening(char *protocol)
+{
+ /* look for this transport in the list of listeners */
+ int i;
+
+ for (i = 0; i < ListenTransCount; i++) {
+ if (!strcmp(protocol, ListenTransConns[i]->transptr->TransName)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
void
@@ -351,8 +366,8 @@ void
NotifyParentProcess(void)
{
#if !defined(WIN32)
- if (dynamic_display[0]) {
- write(displayfd, dynamic_display, strlen(dynamic_display));
+ if (displayfd) {
+ write(displayfd, display, strlen(display));
write(displayfd, "\n", 1);
close(displayfd);
}
@@ -404,9 +419,8 @@ CreateWellKnownSockets(void)
FD_ZERO(&WellKnownConnections);
/* display is initialized to "0" by main(). It is then set to the display
- * number if specified on the command line, or to NULL when the -displayfd
- * option is used. */
- if (display) {
+ * number if specified on the command line. */
+ if ((displayfd == 0) || explicit_display) {
if (TryCreateSocket(atoi(display), &partial) &&
ListenTransCount >= 1)
if (!PartialNetwork && partial)
@@ -415,6 +429,7 @@ CreateWellKnownSockets(void)
else { /* -displayfd */
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 53b358629..976f90f40 100644
--- a/os/log.c
+++ b/os/log.c
@@ -881,9 +881,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: ");
va_start(args, f);
@@ -902,7 +902,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 608ee6ab0..d3391215b 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
@@ -253,7 +255,7 @@ UnlockServer(void)
#else /* LOCK_SERVER */
static Bool StillLocking = FALSE;
static char LockFile[PATH_MAX];
-static Bool nolock = FALSE;
+Bool nolock = FALSE;
/*
* LockServer --
@@ -547,6 +549,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
@@ -639,6 +642,7 @@ ProcessCommandLine(int argc, char *argv[])
else if (argv[i][0] == ':') {
/* initialize display */
display = argv[i];
+ explicit_display = TRUE;
display++;
if (!VerifyDisplayName(display)) {
ErrorF("Bad display name: %s\n", display);
@@ -709,7 +713,6 @@ ProcessCommandLine(int argc, char *argv[])
else if (strcmp(argv[i], "-displayfd") == 0) {
if (++i < argc) {
displayfd = atoi(argv[i]);
- display = NULL;
#ifdef LOCK_SERVER
nolock = TRUE;
#endif
@@ -792,6 +795,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__)
@@ -930,6 +936,7 @@ ProcessCommandLine(int argc, char *argv[])
}
else if (strcmp(argv[i], "-schedInterval") == 0) {
if (++i < argc) {
+ SmartScheduleDisable = FALSE;
SmartScheduleInterval = atoi(argv[i]);
SmartScheduleSlice = SmartScheduleInterval;
}
@@ -938,6 +945,7 @@ ProcessCommandLine(int argc, char *argv[])
}
else if (strcmp(argv[i], "-schedMax") == 0) {
if (++i < argc) {
+ SmartScheduleDisable = FALSE;
SmartScheduleMaxSlice = atoi(argv[i]);
}
else
@@ -1335,6 +1343,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)
{
@@ -1376,6 +1404,7 @@ System(const char *command)
return p == -1 ? -1 : status;
}
+#endif
static struct pid {
struct pid *next;
@@ -1687,6 +1716,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 d462957f4..bcfe04d8e 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
@@ -104,7 +105,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
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];
@@ -117,9 +118,9 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
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
@@ -158,7 +159,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
return FALSE;
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
out = Popen(buf, "w");
#else
out = fopen(tmpname, "w");
@@ -172,7 +173,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
}
#endif
XkbWriteXKBKeymapForNames(out, names, xkb, want, need);
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__CYGWIN__)
if (Pclose(out) == 0)
#else
if (fclose(out) == 0 && System(buf) >= 0)
@@ -184,14 +185,14 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
strlcpy(nameRtrn, keymap, nameRtrnLen);
}
free(buf);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
unlink(tmpname);
#endif
return TRUE;
}
else
LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
+#if defined(WIN32) || defined(__CYGWIN__)
/* remove the temporary file */
unlink(tmpname);
#endif