summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/dmx/doc/dmx.xml2
-rw-r--r--hw/xquartz/Makefile.am2
-rw-r--r--hw/xquartz/pseudoramiX.c516
-rw-r--r--hw/xquartz/pseudoramiX.h10
-rw-r--r--hw/xquartz/quartz.c2
-rw-r--r--hw/xwin/InitOutput.c215
-rw-r--r--hw/xwin/Makefile.am17
-rw-r--r--hw/xwin/glx/winpriv.c34
-rw-r--r--hw/xwin/man/XWin.man9
-rw-r--r--hw/xwin/man/XWinrc.man29
-rw-r--r--hw/xwin/system.XWinrc10
-rw-r--r--hw/xwin/win.h55
-rw-r--r--hw/xwin/winclipboard.h1
-rw-r--r--hw/xwin/winclipboardtextconv.c11
-rw-r--r--hw/xwin/winclipboardthread.c58
-rw-r--r--hw/xwin/winclipboardwndproc.c42
-rw-r--r--hw/xwin/winclipboardwrappers.c14
-rw-r--r--hw/xwin/winclipboardxevents.c54
-rw-r--r--hw/xwin/winconfig.c1
-rw-r--r--hw/xwin/winconfig.h3
-rw-r--r--hw/xwin/wincursor.c307
-rw-r--r--hw/xwin/windisplay.c52
-rw-r--r--hw/xwin/winerror.c10
-rw-r--r--hw/xwin/winglobals.c2
-rw-r--r--hw/xwin/winglobals.h3
-rw-r--r--hw/xwin/winkeybd.c326
-rw-r--r--hw/xwin/winmessages.h2
-rw-r--r--hw/xwin/winmouse.c119
-rw-r--r--hw/xwin/winmsg.c10
-rw-r--r--hw/xwin/winmsgwindow.c180
-rw-r--r--hw/xwin/winmultiwindowclass.c28
-rw-r--r--hw/xwin/winmultiwindowicons.c516
-rw-r--r--hw/xwin/winmultiwindowwindow.c279
-rw-r--r--hw/xwin/winmultiwindowwm.c178
-rw-r--r--hw/xwin/winmultiwindowwndproc.c78
-rw-r--r--hw/xwin/winprefs.c153
-rw-r--r--hw/xwin/winprefslex.l6
-rw-r--r--hw/xwin/winprefsyacc.y91
-rw-r--r--hw/xwin/winprocarg.c123
-rw-r--r--hw/xwin/winrandr.c2
-rw-r--r--hw/xwin/winscrinit.c20
-rw-r--r--hw/xwin/winwin32rootlesswndproc.c13
-rw-r--r--hw/xwin/winwindow.h2
-rw-r--r--hw/xwin/winwndproc.c28
-rw-r--r--hw/xwin/wmutil/Makefile.am24
-rw-r--r--hw/xwin/wmutil/cursor_convert.c353
-rw-r--r--hw/xwin/wmutil/cursor_convert.h54
-rw-r--r--hw/xwin/wmutil/icon_convert.c553
-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
55 files changed, 3162 insertions, 2000 deletions
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/xquartz/Makefile.am b/hw/xquartz/Makefile.am
index a7cc012d9..2623a9db0 100644
--- a/hw/xquartz/Makefile.am
+++ b/hw/xquartz/Makefile.am
@@ -28,7 +28,6 @@ libXquartz_la_SOURCES = \
darwinEvents.c \
darwinXinput.c \
keysym2ucs.c \
- pseudoramiX.c \
quartz.c \
quartzCocoa.m \
quartzKeyboard.c \
@@ -44,7 +43,6 @@ EXTRA_DIST = \
darwinfb.h \
darwinEvents.h \
keysym2ucs.h \
- pseudoramiX.h \
quartz.h \
quartzCommon.h \
quartzKeyboard.h \
diff --git a/hw/xquartz/pseudoramiX.c b/hw/xquartz/pseudoramiX.c
deleted file mode 100644
index 23dbc7328..000000000
--- a/hw/xquartz/pseudoramiX.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Minimal implementation of PanoramiX/Xinerama
- *
- * This is used in rootless mode where the underlying window server
- * already provides an abstracted view of multiple screens as one
- * large screen area.
- *
- * This code is largely based on panoramiX.c, which contains the
- * following copyright notice:
- */
-/*****************************************************************
- Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
- 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.
-
- 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
- DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
- BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
- shall not be used in advertising or otherwise to promote the sale, use or other
- dealings in this Software without prior written authorization from Digital
- Equipment Corporation.
- ******************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "pseudoramiX.h"
-#include "extnsionst.h"
-#include "extinit.h"
-#include "dixstruct.h"
-#include "window.h"
-#include <X11/extensions/panoramiXproto.h>
-#include "globals.h"
-
-#define TRACE PseudoramiXTrace("TRACE " __FILE__ ":%s",__FUNCTION__)
-#define DEBUG_LOG PseudoramiXDebug
-
-Bool noPseudoramiXExtension = FALSE;
-
-extern int
-ProcPanoramiXQueryVersion(ClientPtr client);
-
-static void
-PseudoramiXResetProc(ExtensionEntry *extEntry);
-
-static int
-ProcPseudoramiXQueryVersion(ClientPtr client);
-static int
-ProcPseudoramiXGetState(ClientPtr client);
-static int
-ProcPseudoramiXGetScreenCount(ClientPtr client);
-static int
-ProcPseudoramiXGetScreenSize(ClientPtr client);
-static int
-ProcPseudoramiXIsActive(ClientPtr client);
-static int
-ProcPseudoramiXQueryScreens(ClientPtr client);
-static int
-ProcPseudoramiXDispatch(ClientPtr client);
-
-static int
-SProcPseudoramiXQueryVersion(ClientPtr client);
-static int
-SProcPseudoramiXGetState(ClientPtr client);
-static int
-SProcPseudoramiXGetScreenCount(ClientPtr client);
-static int
-SProcPseudoramiXGetScreenSize(ClientPtr client);
-static int
-SProcPseudoramiXIsActive(ClientPtr client);
-static int
-SProcPseudoramiXQueryScreens(ClientPtr client);
-static int
-SProcPseudoramiXDispatch(ClientPtr client);
-
-typedef struct {
- int x;
- int y;
- int w;
- int h;
-} PseudoramiXScreenRec;
-
-static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
-static int pseudoramiXScreensAllocated = 0;
-static int pseudoramiXNumScreens = 0;
-static unsigned long pseudoramiXGeneration = 0;
-
-static void
-PseudoramiXTrace(const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- LogVMessageVerb(X_NONE, 10, format, ap);
- va_end(ap);
-}
-
-static void
-PseudoramiXDebug(const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- LogVMessageVerb(X_NONE, 3, format, ap);
- va_end(ap);
-}
-
-// Add a PseudoramiX screen.
-// The rest of the X server will know nothing about this screen.
-// Can be called before or after extension init.
-// Screens must be re-added once per generation.
-void
-PseudoramiXAddScreen(int x, int y, int w, int h)
-{
- PseudoramiXScreenRec *s;
-
- if (noPseudoramiXExtension) return;
-
- if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
- pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
- pseudoramiXScreens = realloc(pseudoramiXScreens,
- pseudoramiXScreensAllocated *
- sizeof(PseudoramiXScreenRec));
- }
-
- DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h);
-
- s = &pseudoramiXScreens[pseudoramiXNumScreens++];
- s->x = x;
- s->y = y;
- s->w = w;
- s->h = h;
-}
-
-// Initialize PseudoramiX.
-// Copied from PanoramiXExtensionInit
-void
-PseudoramiXExtensionInit(void)
-{
- Bool success = FALSE;
- ExtensionEntry *extEntry;
-
- if (noPseudoramiXExtension) return;
-
- TRACE;
-
- /* Even with only one screen we need to enable PseudoramiX to allow
- dynamic screen configuration changes. */
-#if 0
- if (pseudoramiXNumScreens == 1) {
- // Only one screen - disable Xinerama extension.
- noPseudoramiXExtension = TRUE;
- return;
- }
-#endif
-
- if (pseudoramiXGeneration != serverGeneration) {
- extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
- ProcPseudoramiXDispatch,
- SProcPseudoramiXDispatch,
- PseudoramiXResetProc,
- StandardMinorOpcode);
- if (!extEntry) {
- ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
- }
- else {
- pseudoramiXGeneration = serverGeneration;
- success = TRUE;
- }
- }
-
- if (!success) {
- ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
- PANORAMIX_PROTOCOL_NAME);
- return;
- }
-}
-
-void
-PseudoramiXResetScreens(void)
-{
- TRACE;
-
- pseudoramiXNumScreens = 0;
-}
-
-static void
-PseudoramiXResetProc(ExtensionEntry *extEntry)
-{
- TRACE;
-
- PseudoramiXResetScreens();
-}
-
-// was PanoramiX
-static int
-ProcPseudoramiXQueryVersion(ClientPtr client)
-{
- TRACE;
-
- return ProcPanoramiXQueryVersion(client);
-}
-
-// was PanoramiX
-static int
-ProcPseudoramiXGetState(ClientPtr client)
-{
- REQUEST(xPanoramiXGetStateReq);
- WindowPtr pWin;
- xPanoramiXGetStateReply rep;
- register int rc;
-
- TRACE;
-
- REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.state = !noPseudoramiXExtension;
- rep.window = stuff->window;
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.window);
- }
- WriteToClient(client, sizeof(xPanoramiXGetStateReply),&rep);
- return Success;
-}
-
-// was PanoramiX
-static int
-ProcPseudoramiXGetScreenCount(ClientPtr client)
-{
- REQUEST(xPanoramiXGetScreenCountReq);
- WindowPtr pWin;
- xPanoramiXGetScreenCountReply rep;
- register int rc;
-
- TRACE;
-
- REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.ScreenCount = pseudoramiXNumScreens;
- rep.window = stuff->window;
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.window);
- }
- WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply),&rep);
- return Success;
-}
-
-// was PanoramiX
-static int
-ProcPseudoramiXGetScreenSize(ClientPtr client)
-{
- REQUEST(xPanoramiXGetScreenSizeReq);
- WindowPtr pWin;
- xPanoramiXGetScreenSizeReply rep;
- register int rc;
-
- TRACE;
-
- if (stuff->screen >= pseudoramiXNumScreens)
- return BadMatch;
-
- REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- /* screen dimensions */
- rep.width = pseudoramiXScreens[stuff->screen].w;
- // was screenInfo.screens[stuff->screen]->width;
- rep.height = pseudoramiXScreens[stuff->screen].h;
- // was screenInfo.screens[stuff->screen]->height;
- rep.window = stuff->window;
- rep.screen = stuff->screen;
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.width);
- swapl(&rep.height);
- swapl(&rep.window);
- swapl(&rep.screen);
- }
- WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply),&rep);
- return Success;
-}
-
-// was Xinerama
-static int
-ProcPseudoramiXIsActive(ClientPtr client)
-{
- /* REQUEST(xXineramaIsActiveReq); */
- xXineramaIsActiveReply rep;
-
- TRACE;
-
- REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.state = !noPseudoramiXExtension;
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.state);
- }
- WriteToClient(client, sizeof(xXineramaIsActiveReply),&rep);
- return Success;
-}
-
-// was Xinerama
-static int
-ProcPseudoramiXQueryScreens(ClientPtr client)
-{
- /* REQUEST(xXineramaQueryScreensReq); */
- xXineramaQueryScreensReply rep;
-
- DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n",
- noPseudoramiXExtension,
- pseudoramiXNumScreens);
-
- REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
- rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.number);
- }
- WriteToClient(client, sizeof(xXineramaQueryScreensReply),&rep);
-
- if (!noPseudoramiXExtension) {
- xXineramaScreenInfo scratch;
- int i;
-
- for (i = 0; i < pseudoramiXNumScreens; i++) {
- scratch.x_org = pseudoramiXScreens[i].x;
- scratch.y_org = pseudoramiXScreens[i].y;
- scratch.width = pseudoramiXScreens[i].w;
- scratch.height = pseudoramiXScreens[i].h;
-
- if (client->swapped) {
- swaps(&scratch.x_org);
- swaps(&scratch.y_org);
- swaps(&scratch.width);
- swaps(&scratch.height);
- }
- WriteToClient(client, sz_XineramaScreenInfo,&scratch);
- }
- }
-
- return Success;
-}
-
-// was PanoramiX
-static int
-ProcPseudoramiXDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- TRACE;
- switch (stuff->data) {
- case X_PanoramiXQueryVersion:
- return ProcPseudoramiXQueryVersion(client);
-
- case X_PanoramiXGetState:
- return ProcPseudoramiXGetState(client);
-
- case X_PanoramiXGetScreenCount:
- return ProcPseudoramiXGetScreenCount(client);
-
- case X_PanoramiXGetScreenSize:
- return ProcPseudoramiXGetScreenSize(client);
-
- case X_XineramaIsActive:
- return ProcPseudoramiXIsActive(client);
-
- case X_XineramaQueryScreens:
- return ProcPseudoramiXQueryScreens(client);
- }
- return BadRequest;
-}
-
-static int
-SProcPseudoramiXQueryVersion(ClientPtr client)
-{
- REQUEST(xPanoramiXQueryVersionReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
- return ProcPseudoramiXQueryVersion(client);
-}
-
-static int
-SProcPseudoramiXGetState(ClientPtr client)
-{
- REQUEST(xPanoramiXGetStateReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
- return ProcPseudoramiXGetState(client);
-}
-
-static int
-SProcPseudoramiXGetScreenCount(ClientPtr client)
-{
- REQUEST(xPanoramiXGetScreenCountReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
- return ProcPseudoramiXGetScreenCount(client);
-}
-
-static int
-SProcPseudoramiXGetScreenSize(ClientPtr client)
-{
- REQUEST(xPanoramiXGetScreenSizeReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
- return ProcPseudoramiXGetScreenSize(client);
-}
-
-static int
-SProcPseudoramiXIsActive(ClientPtr client)
-{
- REQUEST(xXineramaIsActiveReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
- return ProcPseudoramiXIsActive(client);
-}
-
-static int
-SProcPseudoramiXQueryScreens(ClientPtr client)
-{
- REQUEST(xXineramaQueryScreensReq);
-
- TRACE;
-
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
- return ProcPseudoramiXQueryScreens(client);
-}
-
-static int
-SProcPseudoramiXDispatch(ClientPtr client)
-{
- REQUEST(xReq);
-
- TRACE;
-
- switch (stuff->data) {
- case X_PanoramiXQueryVersion:
- return SProcPseudoramiXQueryVersion(client);
-
- case X_PanoramiXGetState:
- return SProcPseudoramiXGetState(client);
-
- case X_PanoramiXGetScreenCount:
- return SProcPseudoramiXGetScreenCount(client);
-
- case X_PanoramiXGetScreenSize:
- return SProcPseudoramiXGetScreenSize(client);
-
- case X_XineramaIsActive:
- return SProcPseudoramiXIsActive(client);
-
- case X_XineramaQueryScreens:
- return SProcPseudoramiXQueryScreens(client);
- }
- return BadRequest;
-}
diff --git a/hw/xquartz/pseudoramiX.h b/hw/xquartz/pseudoramiX.h
deleted file mode 100644
index f063919dd..000000000
--- a/hw/xquartz/pseudoramiX.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Minimal implementation of PanoramiX/Xinerama
- */
-
-extern int noPseudoramiXExtension;
-
-void
-PseudoramiXAddScreen(int x, int y, int w, int h);
-void
-PseudoramiXResetScreens(void);
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/InitOutput.c b/hw/xwin/InitOutput.c
index 04c17b702..1b50737e5 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
@@ -54,6 +52,8 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
HANDLE hToken,
DWORD dwFlags, LPTSTR pszPath);
#endif
+#include "winmonitors.h"
+#include "pseudoramiX/pseudoramiX.h"
#include "glx_extinit.h"
/*
@@ -68,6 +68,8 @@ extern HWND g_hwndClipboard;
extern Bool g_fClipboard;
#endif
+extern Bool noRRXineramaExtension;
+
/*
* Function prototypes
*/
@@ -77,8 +79,6 @@ static void
winClipboardShutdown(void);
#endif
-static Bool
- winCheckDisplayNumber(void);
void
winLogCommandLine(int argc, char *argv[]);
@@ -93,6 +93,8 @@ Bool
const char *winGetBaseDir(void);
#endif
+static void winCheckMount(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
@@ -186,6 +188,27 @@ ddxBeforeReset(void)
}
#endif
+int
+main(int argc, char *argv[], char *envp[])
+{
+ int iReturn;
+
+ /* Create & acquire the termination mutex */
+ iReturn = pthread_mutex_init(&g_pmTerminating, NULL);
+ if (iReturn != 0) {
+ ErrorF("ddxMain - pthread_mutex_init () failed: %d\n", iReturn);
+ }
+
+ iReturn = pthread_mutex_lock(&g_pmTerminating);
+ if (iReturn != 0) {
+ ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn);
+ }
+
+ winCheckMount();
+
+ return dix_main(argc, argv, envp);
+}
+
/* See Porting Layer Definition - p. 57 */
void
ddxGiveUp(enum ExitCode error)
@@ -243,6 +266,19 @@ ddxGiveUp(enum ExitCode error)
/* Tell Windows that we want to end the app */
PostQuitMessage(0);
+
+ {
+ winDebug("ddxGiveUp - Releasing termination mutex\n");
+
+ int iReturn = pthread_mutex_unlock(&g_pmTerminating);
+
+ if (iReturn != 0) {
+ ErrorF("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n",
+ iReturn);
+ }
+ }
+
+ winDebug("ddxGiveUp - End\n");
}
/* See Porting Layer Definition - p. 57 */
@@ -256,6 +292,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)
@@ -280,6 +318,9 @@ winCheckMntOpt(const struct mntent *mnt, const char *opt)
return NULL;
}
+/*
+ Check mounts and issue warnings/activate workarounds as needed
+ */
static void
winCheckMount(void)
{
@@ -289,6 +330,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) {
@@ -327,6 +369,11 @@ winCheckMount(void)
binary = FALSE;
else
binary = TRUE;
+
+ if (strcmp(ent->mnt_type, "vfat") == 0)
+ fat = TRUE;
+ else
+ fat = FALSE;
}
if (endmntent(mnt) != 1) {
@@ -336,6 +383,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
@@ -747,6 +800,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
@@ -915,14 +971,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())
@@ -962,6 +1010,10 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
/* Store the instance handle */
g_hInstance = GetModuleHandle(NULL);
+ /* Create the messaging window */
+ if (serverGeneration == 1)
+ winCreateMsgWindowThread();
+
/* Initialize each screen */
for (i = 0; i < g_iNumScreens; ++i) {
/* Initialize the screen */
@@ -970,6 +1022,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(argc, argv);
+
+ /* 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 */
@@ -978,11 +1085,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
@@ -990,70 +1110,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 93ce57038..b5a0228b6 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -15,7 +15,7 @@ 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 +27,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
@@ -92,6 +93,7 @@ SRCS = InitInput.c \
winmonitors.c \
winmouse.c \
winmsg.c \
+ winmsgwindow.c \
winmultiwindowclass.c \
winmultiwindowicons.c \
winprefs.c \
@@ -113,8 +115,6 @@ SRCS = InitInput.c \
winconfig.h \
win.h \
winglobals.h \
- winkeybd.h \
- winkeynames.h \
winlayouts.h \
winmessages.h \
winmonitors.h \
@@ -125,6 +125,7 @@ SRCS = InitInput.c \
winprefs.h \
winresource.h \
winwindow.h \
+ windisplay.c \
XWin.rc \
$(top_srcdir)/Xext/dpmsstubs.c \
$(top_srcdir)/Xi/stubs.c \
@@ -152,9 +153,11 @@ XWin_SOURCES = $(SRCS)
INCLUDES = -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) $(MAIN_LIB) $(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) $(MAIN_LIB) $(XSERVER_LIBS)
+XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) \
+ $(XWIN_GLX_SYS_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) $(MULTIWINDOW_SYS_LIBS)
XWin_LDFLAGS = -mwindows -static
.rc.o:
@@ -188,5 +191,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) .
+SUBDIRS = man $(GLX_DIR) wmutil .
DIST_SUBDIRS = man glx .
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..cf5324131 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,6 +168,12 @@ 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
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 fa774bc00..5e0ca8901 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -42,22 +42,16 @@
#define YES 1
#endif
+/* We can handle WM_MOUSEHWHEEL even though _WIN32_WINNT < 0x0600 */
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+
/* Turn debug messages on or off */
#ifndef CYGDEBUG
#define CYGDEBUG NO
#endif
-/* WM_XBUTTON Messages. They should go into w32api. */
-#ifndef WM_XBUTTONDOWN
-#define WM_XBUTTONDOWN 523
-#endif
-#ifndef WM_XBUTTONUP
-#define WM_XBUTTONUP 524
-#endif
-#ifndef WM_XBUTTONDBLCLK
-#define WM_XBUTTONDBLCLK 525
-#endif
-
#define WIN_DEFAULT_BPP 0
#define WIN_DEFAULT_WHITEPIXEL 255
#define WIN_DEFAULT_BLACKPIXEL 0
@@ -460,6 +454,7 @@ typedef struct _winPrivScreenRec {
Bool fBadDepth;
int iDeltaZ;
+ int iDeltaV;
int iConnectedClients;
@@ -921,9 +916,6 @@ void
* winkeybd.c
*/
-void
- winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode);
-
int
winKeybdProc(DeviceIntPtr pDeviceInt, int iState);
@@ -933,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
*/
@@ -986,13 +964,6 @@ int
winMouseProc(DeviceIntPtr pDeviceInt, int iState);
int
- winMouseWheel(ScreenPtr pScreen, int iDeltaZ);
-
-void
- winMouseButtonsSendEvent(int iEventType, int iButton);
-
-int
-
winMouseButtonsHandle(ScreenPtr pScreen,
int iEventType, int iButton, WPARAM wParam);
@@ -1237,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
/*
@@ -1401,6 +1374,18 @@ void
winDoRandRScreenSetSize(ScreenPtr pScreen,
CARD16 width,
CARD16 height, CARD32 mmWidth, CARD32 mmHeight);
+/*
+ * windisplay.c
+ */
+
+void
+winGetDisplayName(char *szDisplay, unsigned int screen);
+
+/*
+ * winmsgwindow.c
+ */
+Bool
+winCreateMsgWindowThread(void);
/*
* END DDX and DIX Function Prototypes
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index 2cd775d6b..ad994d5ad 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -49,7 +49,6 @@
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
-#include <X11/Xlocale.h>
/* Windows headers */
#include <X11/Xwindows.h>
diff --git a/hw/xwin/winclipboardtextconv.c b/hw/xwin/winclipboardtextconv.c
index fd405a02e..7b8eb9826 100644
--- a/hw/xwin/winclipboardtextconv.c
+++ b/hw/xwin/winclipboardtextconv.c
@@ -48,11 +48,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 +71,8 @@ winClipboardDOStoUNIX(char *pszSrc, int iLength)
/* Move the terminating null */
*pszDest = '\0';
+
+ winDebug("DOStoUNIX() - Final string:'%s'\n", pszData);
}
/*
@@ -101,8 +106,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/winclipboardthread.c
index c8508a9b8..b5ba16f4c 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -76,6 +76,9 @@ static int
static int
winClipboardIOErrorHandler(Display * pDisplay);
+static void
+winClipboardThreadExit(void *arg);
+
/*
* Main thread function
*/
@@ -102,6 +105,8 @@ winClipboardProc(void *pvNotUsed)
char szDisplay[512];
int iSelectError;
+ pthread_cleanup_push(&winClipboardThreadExit, NULL);
+
winDebug("winClipboardProc - Hello\n");
++clipboardRestarts;
@@ -111,16 +116,6 @@ winClipboardProc(void *pvNotUsed)
/* Save the Unicode support flag in a global */
g_fUseUnicode = fUseUnicode;
- /* Allow multiple threads to access Xlib */
- if (XInitThreads() == 0) {
- ErrorF("winClipboardProc - XInitThreads failed.\n");
- goto winClipboardProc_Exit;
- }
-
- /* See if X supports the current locale */
- if (XSupportsLocale() == False) {
- ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
- }
/* Set error handler */
XSetErrorHandler(winClipboardErrorHandler);
@@ -140,7 +135,7 @@ winClipboardProc(void *pvNotUsed)
else if (iReturn == WIN_JMP_ERROR_IO) {
/* TODO: Cleanup the Win32 window and free any allocated memory */
ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
- pthread_exit(NULL);
+ goto winClipboardProc_Done;
}
/* Use our generated cookie for authentication */
@@ -157,7 +152,7 @@ winClipboardProc(void *pvNotUsed)
* 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);
+ winGetDisplayName(szDisplay, 0);
/* Print the display connection string */
ErrorF("winClipboardProc - DISPLAY=%s\n", szDisplay);
@@ -183,7 +178,7 @@ winClipboardProc(void *pvNotUsed)
goto winClipboardProc_Done;
}
- /* Save the display in the screen privates */
+ /* Save the display in a global used by the wndproc */
g_pClipboardDisplay = pDisplay;
ErrorF("winClipboardProc - XOpenDisplay () returned and "
@@ -269,8 +264,10 @@ winClipboardProc(void *pvNotUsed)
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
/* Pre-flush Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd))
- return 0;
+ if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+ ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
+ pthread_exit(NULL);
+ }
/* Signal that the clipboard client has started */
g_fClipboardStarted = TRUE;
@@ -292,6 +289,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 */
@@ -323,8 +322,13 @@ winClipboardProc(void *pvNotUsed)
break;
}
+ winDebug("winClipboardProc - select returned %d\n", iReturn);
+
/* Branch on which descriptor became active */
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
+ winDebug
+ ("winClipboardProc - X connection ready, pumping X event queue\n");
+
/* Process X events */
/* Exit when we see that server is shutting down */
iReturn = winClipboardFlushXEvents(hwnd,
@@ -343,6 +347,9 @@ winClipboardProc(void *pvNotUsed)
if (1)
#endif
{
+ winDebug
+ ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n");
+
/* Process Windows messages */
if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
ErrorF("winClipboardProc - "
@@ -351,6 +358,13 @@ winClipboardProc(void *pvNotUsed)
break;
}
}
+
+#ifdef HAS_DEVWINDOWS
+ if (!(FD_ISSET(iConnectionNumber, &fdsRead)) &&
+ !(FD_ISSET(fdMessageQueue, &fdsRead))) {
+ winDebug("winClipboardProc - Spurious wake\n");
+ }
+#endif
}
winClipboardProc_Exit:
@@ -435,6 +449,7 @@ winClipboardProc(void *pvNotUsed)
raise(SIGTERM);
}
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -461,7 +476,7 @@ winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
static int
winClipboardIOErrorHandler(Display * pDisplay)
{
- ErrorF("winClipboardIOErrorHandler!\n\n");
+ ErrorF("winClipboardIOErrorHandler!\n");
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
/* Restart at the main entry point */
@@ -473,3 +488,14 @@ winClipboardIOErrorHandler(Display * pDisplay)
return 0;
}
+
+/*
+ * winClipboardThreadExit - Thread exit handler
+ */
+
+static void
+winClipboardThreadExit(void *arg)
+{
+ /* clipboard thread has exited, stop server as well */
+ kill(getpid(), SIGTERM);
+}
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index e19f678a7..077b9f0bf 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -151,6 +151,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static HWND s_hwndNextViewer;
static Bool s_fCBCInitialized;
+#if CYGDEBUG
+ winDebugWin32Message("winClipboardWindowProc", hwnd, message, wParam,
+ lParam);
+#endif
+
/* Branch on message type */
switch (message) {
case WM_DESTROY:
@@ -325,6 +330,29 @@ 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());
+ {
+ 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);
+ }
/*
* We need to make sure that the X Server has processed
* previous XSetSelectionOwner messages.
@@ -337,24 +365,24 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
if (iReturn == g_iClipboardWindow) {
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",
+ "XGetSelectionOwner failed for PRIMARY: %d\n",
iReturn);
/* Release CLIPBOARD selection if owned */
iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
if (iReturn == g_iClipboardWindow) {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "CLIPBOARD selection is owned by us.\n");
+ "CLIPBOARD selection is owned by us, releasing\n");
XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "XGetSelection failed for CLIPBOARD: %d\n",
+ "XGetSelectionOwner failed for CLIPBOARD: %d\n",
iReturn);
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
@@ -424,7 +452,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Window iWindow = g_iClipboardWindow;
Bool fConvertToUnicode;
- 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)
diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index 008088b6a..27b9872ff 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -190,7 +190,9 @@ winProcSetSelectionOwner(ClientPtr client)
REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
- winDebug("winProcSetSelectionOwner - Hello.\n");
+ winDebug
+ ("winProcSetSelectionOwner - Hello. atom 0x%08x window XID 0x%08x \n",
+ stuff->selection, stuff->window);
/* Watch for server reset */
if (s_ulServerGeneration != serverGeneration) {
@@ -241,8 +243,9 @@ winProcSetSelectionOwner(ClientPtr client)
/* Save new selection owner or None */
s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
- winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
- stuff->window);
+ winDebug
+ ("winProcSetSelectionOwner - PRIMARY - Now owned by XID 0x%08x\n",
+ stuff->window);
}
else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
/* Look for owned -> not owned transition */
@@ -262,8 +265,9 @@ winProcSetSelectionOwner(ClientPtr client)
/* Save new selection owner or None */
s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
- winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
- stuff->window);
+ winDebug
+ ("winProcSetSelectionOwner - CLIPBOARD - Now owned by XID 0x%08x\n",
+ stuff->window);
}
else
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboardxevents.c
index 226c3f055..a4d193d93 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboardxevents.c
@@ -122,6 +122,7 @@ winClipboardFlushXEvents(HWND hwnd,
atomUTF8String,
XA_STRING
};
+ winDebug("SelectionRequest - populating targets\n");
/* Try to change the property */
iReturn = XChangeProperty(pDisplay,
@@ -367,6 +368,7 @@ winClipboardFlushXEvents(HWND hwnd,
* client when we abort.
*/
if (fAbort) {
+ winDebug("SelectionRequest - aborting\n");
/* Setup selection notify event */
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
@@ -463,6 +465,23 @@ winClipboardFlushXEvents(HWND hwnd,
}
}
+ case SelectionClear:
+ winDebug("SelectionClear - doing nothing\n");
+ break;
+
+ case PropertyNotify:
+ {
+ char *pszAtomName;
+
+ pszAtomName = XGetAtomName(pDisplay, event.xproperty.atom);
+ winDebug("winClipboardFlushXEvents - PropertyNotify - ATOM: %s\n",
+ pszAtomName);
+ XFree(pszAtomName);
+ }
+
+ if (event.xproperty.atom != atomLocalProperty)
+ break;
+
/* Retrieve the size of the stored data */
iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */
False,
@@ -472,12 +491,12 @@ winClipboardFlushXEvents(HWND hwnd,
&xtpText.nitems,
&ulReturnBytesLeft, &xtpText.value);
if (iReturn != Success) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify - "
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
break;
}
- winDebug("SelectionNotify - returned data %d left %d\n",
+ winDebug("PropertyNotify - returned data %d left %d\n",
xtpText.nitems, ulReturnBytesLeft);
/* Request the selection data */
@@ -493,7 +512,7 @@ winClipboardFlushXEvents(HWND hwnd,
&xtpText.nitems,
&ulReturnBytesLeft, &xtpText.value);
if (iReturn != Success) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify - "
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
break;
}
@@ -501,10 +520,11 @@ winClipboardFlushXEvents(HWND hwnd,
{
char *pszAtomName = NULL;
- winDebug("SelectionNotify - returned data %d left %d\n",
+ winDebug("PropertyNotify - returned data %d left %d\n",
xtpText.nitems, ulReturnBytesLeft);
pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
- winDebug("Notify atom name %s\n", pszAtomName);
+ winDebug("PropertyNotify - encoding atom name %s\n",
+ pszAtomName);
XFree(pszAtomName);
pszAtomName = NULL;
}
@@ -536,14 +556,14 @@ winClipboardFlushXEvents(HWND hwnd,
}
}
else {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify - "
"X*TextPropertyToTextList list_return is NULL.\n");
pszReturnData = malloc(1);
pszReturnData[0] = '\0';
}
}
else {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify - "
"X*TextPropertyToTextList returned: ");
switch (iReturn) {
case XNoMemory:
@@ -584,12 +604,12 @@ winClipboardFlushXEvents(HWND hwnd,
pwszUnicodeStr
= (wchar_t *) malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
if (!pwszUnicodeStr) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify "
"malloc failed for pwszUnicodeStr, aborting.\n");
/* Abort */
fAbort = TRUE;
- goto winClipboardFlushXEvents_SelectionNotify_Done;
+ goto winClipboardFlushXEvents_PropertyNotify_Done;
}
/* Do the actual conversion */
@@ -614,12 +634,11 @@ winClipboardFlushXEvents(HWND hwnd,
/* Check that global memory was allocated */
if (!hGlobal) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify "
+ ErrorF("winClipboardFlushXEvents - PropertyNotify "
"GlobalAlloc failed, aborting: %ld\n", GetLastError());
-
/* Abort */
fAbort = TRUE;
- goto winClipboardFlushXEvents_SelectionNotify_Done;
+ goto winClipboardFlushXEvents_PropertyNotify_Done;
}
/* Obtain a pointer to the global memory */
@@ -630,7 +649,7 @@ winClipboardFlushXEvents(HWND hwnd,
/* Abort */
fAbort = TRUE;
- goto winClipboardFlushXEvents_SelectionNotify_Done;
+ goto winClipboardFlushXEvents_PropertyNotify_Done;
}
/* Copy the returned string into the global memory */
@@ -664,7 +683,7 @@ winClipboardFlushXEvents(HWND hwnd,
* Windows after the call to SetClipboardData ().
*/
- winClipboardFlushXEvents_SelectionNotify_Done:
+ winClipboardFlushXEvents_PropertyNotify_Done:
/* Free allocated resources */
if (ppszTextList)
XFreeStringList(ppszTextList);
@@ -683,13 +702,6 @@ winClipboardFlushXEvents(HWND hwnd,
}
return WIN_XEVENTS_NOTIFY;
- case SelectionClear:
- winDebug("SelectionClear - doing nothing\n");
- break;
-
- case PropertyNotify:
- break;
-
case MappingNotify:
break;
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index 9e38113a5..a60802d1f 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 */
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 2962d06ad..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,297 +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;
- unsigned long *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 =
- (unsigned long *) calloc(pScreenPriv->cursor.sm_cx *
- pScreenPriv->cursor.sm_cy,
- sizeof(unsigned long));
-
- if (lpBits) {
- int y;
- for (y = 0; y < nCY; y++) {
- unsigned long *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) {
- /* Bicolor, use a palettized DIB */
- WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n");
- pbmi = (BITMAPINFO *) &bi;
- 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;
- pbmi->bmiColors[0].rgbRed = 0; /* Empty */
- pbmi->bmiColors[0].rgbGreen = 0;
- pbmi->bmiColors[0].rgbBlue = 0;
- pbmi->bmiColors[0].rgbReserved = 0;
- pbmi->bmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
- pbmi->bmiColors[1].rgbGreen = pCursor->backGreen >> 8;
- pbmi->bmiColors[1].rgbBlue = pCursor->backBlue >> 8;
- pbmi->bmiColors[1].rgbReserved = 0;
- pbmi->bmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
- pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
- pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
- pbmi->bmiColors[2].rgbReserved = 0;
-
- lpBits =
- (unsigned long *) 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/windisplay.c b/hw/xwin/windisplay.c
new file mode 100644
index 000000000..9fc4dac68
--- /dev/null
+++ b/hw/xwin/windisplay.c
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ */
+
+#include <opaque.h> // for display
+#include "win.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/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 b34d1a751..fd6c1b490 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -78,6 +78,8 @@ 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
/*
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index d2e2ba2b4..d5da35f4a 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -52,6 +52,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;
@@ -90,4 +91,6 @@ extern Bool g_fButton[3];
extern Bool g_fNoConfigureWindow;
#endif
+extern pthread_mutex_t g_pmTerminating;
+
#endif /* WINGLOBALS_H */
diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c
index 27c114c99..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,65 +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.
- */
-
-void
-winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode)
-{
- 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);
-
- 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)
- *piScanCode = iKeyFixupEx;
- else if (iKeyFixup)
- *piScanCode = iKeyFixup;
- else if (wParam == 0 && iParamScanCode == 0x70)
- *piScanCode = KEY_HKTG;
- else
- switch (iParamScanCode) {
- case 0x70:
- *piScanCode = KEY_HKTG;
- break;
- case 0x73:
- *piScanCode = KEY_BSlash2;
- break;
- default:
- *piScanCode = iParamScanCode;
- break;
- }
-}
-
/* Ring the keyboard bell (system speaker on PCs) */
static void
winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, pointer pCtrl, int iClass)
@@ -264,25 +212,38 @@ winRestoreModeKeyStates(void)
/* Check if modifier keys are pressed, and if so, fake a press */
{
- BOOL ctrl = (GetAsyncKeyState(VK_CONTROL) < 0);
- BOOL shift = (GetAsyncKeyState(VK_SHIFT) < 0);
+
+ BOOL lctrl = (GetAsyncKeyState(VK_LCONTROL) < 0);
+ BOOL rctrl = (GetAsyncKeyState(VK_RCONTROL) < 0);
+ BOOL lshift = (GetAsyncKeyState(VK_LSHIFT) < 0);
+ BOOL rshift = (GetAsyncKeyState(VK_RSHIFT) < 0);
BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0);
BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0);
- if (ctrl && altgr)
- ctrl = FALSE;
+ /*
+ If AltGr and CtrlL appear to be pressed, assume the
+ CtrL is a fake one
+ */
+ if (lctrl && altgr)
+ lctrl = FALSE;
+
+ if (lctrl)
+ winSendKeyEvent(KEY_LCtrl, TRUE);
+
+ if (rctrl)
+ winSendKeyEvent(KEY_RCtrl, TRUE);
- if (LOGICAL_XOR(internalKeyStates & ControlMask, ctrl))
- winSendKeyEvent(KEY_LCtrl, ctrl);
+ if (lshift)
+ winSendKeyEvent(KEY_ShiftL, TRUE);
- if (LOGICAL_XOR(internalKeyStates & ShiftMask, shift))
- winSendKeyEvent(KEY_ShiftL, shift);
+ if (rshift)
+ winSendKeyEvent(KEY_ShiftL, TRUE);
- if (LOGICAL_XOR(internalKeyStates & Mod1Mask, alt))
- winSendKeyEvent(KEY_Alt, alt);
+ if (alt)
+ winSendKeyEvent(KEY_Alt, TRUE);
- if (LOGICAL_XOR(internalKeyStates & Mod5Mask, altgr))
- winSendKeyEvent(KEY_AltLang, altgr);
+ if (altgr)
+ winSendKeyEvent(KEY_AltLang, TRUE);
}
/*
@@ -313,213 +274,54 @@ winRestoreModeKeyStates(void)
winSendKeyEvent(KEY_HKTG, TRUE);
winSendKeyEvent(KEY_HKTG, FALSE);
}
-}
-
-/*
- * 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 UINT lastMessage;
- 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;
- lastMessage = message;
- 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.
+ For strict correctness, we should also press any non-modifier keys
+ which are already down when we gain focus, but nobody has complained
+ yet :-)
*/
- 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/winmessages.h b/hw/xwin/winmessages.h
index 3d3fab274..8282f8b06 100644
--- a/hw/xwin/winmessages.h
+++ b/hw/xwin/winmessages.h
@@ -529,7 +529,7 @@ static const char *MESSAGE_NAMES[1024] = {
"WM_XBUTTONDOWN",
"WM_XBUTTONUP",
"WM_XBUTTONDBLCLK",
- "526",
+ "WM_MOUSEHWHEEL",
"527",
"WM_PARENTNOTIFY",
"WM_ENTERMENULOOP",
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index 9d896c90e..c5de57788 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;
@@ -65,7 +67,7 @@ int
winMouseProc(DeviceIntPtr pDeviceInt, int iState)
{
int lngMouseButtons, i;
- int lngWheelEvents = 2;
+ int lngWheelEvents = 4;
CARD8 *map;
DevicePtr pDevice = (DevicePtr) pDeviceInt;
Atom *btn_labels;
@@ -80,15 +82,23 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
/* Mapping of windows events to X events:
* LEFT:1 MIDDLE:2 RIGHT:3
* SCROLL_UP:4 SCROLL_DOWN:5
- * XBUTTON 1:6 XBUTTON 2:7 ...
+ * TILT_LEFT:6 TILT_RIGHT:7
+ * XBUTTON 1:8 XBUTTON 2:9 (most commonly 'back' and 'forward')
+ * ...
*
+ * The current Windows API only defines 2 extra buttons, so we don't
+ * expect more than 5 buttons to be reported, but more than that
+ * should be handled correctly
+ */
+
+ /*
* To map scroll wheel correctly we need at least the 3 normal buttons
*/
if (lngMouseButtons < 3)
lngMouseButtons = 3;
- /* allocate memory:
- * number of buttons + 2x mouse wheel event + 1 extra (offset for map)
+ /* allocate memory:
+ * number of buttons + 4 x mouse wheel event + 1 extra (offset for map)
*/
map = malloc(sizeof(CARD8) * (lngMouseButtons + lngWheelEvents + 1));
@@ -98,11 +108,16 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
map[i] = i;
btn_labels = calloc((lngMouseButtons + lngWheelEvents), sizeof(Atom));
+
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+ btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+ btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+ btn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK);
+ btn_labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD);
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
@@ -133,90 +148,20 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
return Success;
}
-/* Handle the mouse wheel */
-int
-winMouseWheel(ScreenPtr pScreen, int iDeltaZ)
-{
- winScreenPriv(pScreen);
- int button; /* Button4 or Button5 */
-
- /* Button4 = WheelUp */
- /* Button5 = WheelDown */
-
- /* Do we have any previous delta stored? */
- if ((pScreenPriv->iDeltaZ > 0 && iDeltaZ > 0)
- || (pScreenPriv->iDeltaZ < 0 && iDeltaZ < 0)) {
- /* Previous delta and of same sign as current delta */
- iDeltaZ += pScreenPriv->iDeltaZ;
- pScreenPriv->iDeltaZ = 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 :)
- */
- pScreenPriv->iDeltaZ = 0;
- }
-
- /*
- * Only process this message if the wheel has moved further than
- * WHEEL_DELTA
- */
- if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
- pScreenPriv->iDeltaZ = 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.
- */
- pScreenPriv->iDeltaZ = iDeltaZ;
- return 0;
- }
-
- /* Set the button to indicate up or down wheel delta */
- if (iDeltaZ > 0) {
- button = Button4;
- }
- else {
- button = Button5;
- }
-
- /*
- * 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];
@@ -245,7 +190,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;
}
@@ -282,7 +227,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;
@@ -297,8 +242,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)
@@ -309,7 +254,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
@@ -318,7 +263,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..36dc965e6 100644
--- a/hw/xwin/winmsg.c
+++ b/hw/xwin/winmsg.c
@@ -101,6 +101,16 @@ winErrorFVerb(int verb, const char *format, ...)
}
void
+winError(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ LogVMessageVerb(X_NONE, -1, format, ap);
+ va_end(ap);
+}
+
+void
winDebug(const char *format, ...)
{
va_list ap;
diff --git a/hw/xwin/winmsgwindow.c b/hw/xwin/winmsgwindow.c
new file mode 100644
index 000000000..8067c693c
--- /dev/null
+++ b/hw/xwin/winmsgwindow.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) Jon TURNEY 2011
+ *
+ * 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 "win.h"
+
+/*
+ * This is the messaging window, a hidden top-level window. We never do anything
+ * with it, but other programs may send messages to it.
+ */
+
+/*
+ * winMsgWindowProc - Window procedure for msg window
+ */
+
+static
+LRESULT CALLBACK
+winMsgWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+#if CYGDEBUG
+ winDebugWin32Message("winMsgWindowProc", hwnd, message, wParam, lParam);
+#endif
+
+ switch (message) {
+ case WM_ENDSESSION:
+ if (!wParam)
+ return 0; /* shutdown is being cancelled */
+
+ /*
+ Send a WM_GIVEUP message to the X server thread so it wakes up if
+ blocked in select(), performs GiveUp(), and then notices that GiveUp()
+ has set the DE_TERMINATE flag so exits the msg dispatch loop.
+ */
+ {
+ ScreenPtr pScreen = screenInfo.screens[0];
+
+ winScreenPriv(pScreen);
+ PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
+ }
+
+ /*
+ This process will be terminated by the system almost immediately
+ after the last thread with a message queue returns from processing
+ WM_ENDSESSION, so we cannot rely on any code executing after this
+ message is processed and need to wait here until ddxGiveUp() is called
+ and releases the termination mutex to guarantee that the lock file and
+ unix domain sockets have been removed
+
+ ofc, Microsoft doesn't document this under WM_ENDSESSION, you are supposed
+ to read the source of CRSS to find out how it works :-)
+
+ http://blogs.msdn.com/b/michen/archive/2008/04/04/application-termination-when-user-logs-off.aspx
+ */
+ {
+ int iReturn = pthread_mutex_lock(&g_pmTerminating);
+
+ if (iReturn != 0) {
+ ErrorF("winMsgWindowProc - pthread_mutex_lock () failed: %d\n",
+ iReturn);
+ }
+ winDebug
+ ("winMsgWindowProc - WM_ENDSESSION termination lock acquired\n");
+ }
+
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+static HWND
+winCreateMsgWindow(void)
+{
+ HWND hwndMsg;
+ wATOM winClass;
+
+ // register window class
+ {
+ WNDCLASSEX wcx;
+
+ wcx.cbSize = sizeof(WNDCLASSEX);
+ wcx.style = CS_HREDRAW | CS_VREDRAW;
+ wcx.lpfnWndProc = winMsgWindowProc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = g_hInstance;
+ wcx.hIcon = NULL;
+ wcx.hCursor = 0;
+ wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = WINDOW_CLASS_X_MSG;
+ wcx.hIconSm = NULL;
+ winClass = RegisterClassEx(&wcx);
+ }
+
+ // Create the msg window.
+ hwndMsg = CreateWindowEx(0, // no extended styles
+ WINDOW_CLASS_X_MSG, // class name
+ "XWin Msg Window", // window name
+ WS_OVERLAPPEDWINDOW, // overlapped window
+ CW_USEDEFAULT, // default horizontal position
+ CW_USEDEFAULT, // default vertical position
+ CW_USEDEFAULT, // default width
+ CW_USEDEFAULT, // default height
+ (HWND) NULL, // no parent or owner window
+ (HMENU) NULL, // class menu used
+ GetModuleHandle(NULL), // instance handle
+ NULL); // no window creation data
+
+ if (!hwndMsg) {
+ ErrorF("winCreateMsgWindow - Create msg window failed\n");
+ return NULL;
+ }
+
+ winDebug("winCreateMsgWindow - Created msg window hwnd 0x%x\n", hwndMsg);
+
+ return hwndMsg;
+}
+
+static void *
+winMsgWindowThreadProc(void *arg)
+{
+ HWND hwndMsg;
+
+ winDebug("winMsgWindowThreadProc - Hello\n");
+
+ hwndMsg = winCreateMsgWindow();
+ if (hwndMsg) {
+ MSG msg;
+
+ /* Pump the msg window message queue */
+ while (GetMessage(&msg, hwndMsg, 0, 0) > 0) {
+#if CYGDEBUG
+ winDebugWin32Message("winMsgWindowThread", msg.hwnd, msg.message,
+ msg.wParam, msg.lParam);
+#endif
+ DispatchMessage(&msg);
+ }
+ }
+
+ winDebug("winMsgWindowThreadProc - Exit\n");
+
+ return NULL;
+}
+
+Bool
+winCreateMsgWindowThread(void)
+{
+ pthread_t ptMsgWindowThreadProc;
+
+ /* Spawn a thread for the msg window */
+ if (pthread_create(&ptMsgWindowThreadProc,
+ NULL, winMsgWindowThreadProc, NULL)) {
+ /* Bail if thread creation failed */
+ ErrorF("winCreateMsgWindow - pthread_create failed.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/hw/xwin/winmultiwindowclass.c b/hw/xwin/winmultiwindowclass.c
index 1af104df9..93166fe3b 100644
--- a/hw/xwin/winmultiwindowclass.c
+++ b/hw/xwin/winmultiwindowclass.c
@@ -37,6 +37,12 @@
#include "winmultiwindowclass.h"
#include "win.h"
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+#define strnlen(str, len) \
+ (__extension__ ({ int _len = strlen(str); \
+ _len > len ? len : _len; }))
+#endif
+
/*
* Local function
*/
@@ -68,7 +74,7 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class)
while (prop) {
if (prop->propertyName == XA_WM_CLASS
&& prop->type == XA_STRING && prop->format == 8 && prop->data) {
- len_name = strlen((char *) prop->data);
+ len_name = strnlen((char *) prop->data, prop->size);
(*res_name) = malloc(len_name + 1);
@@ -77,13 +83,17 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class)
return 0;
}
- /* Add one to len_name to allow copying of trailing 0 */
- strncpy((*res_name), prop->data, len_name + 1);
-
- if (len_name == prop->size)
- len_name--;
+ /* Copy name and ensure null terminated */
+ memcpy((*res_name), prop->data, len_name);
+ (*res_name)[len_name] = '\0';
- len_class = strlen(((char *) prop->data) + 1 + len_name);
+ /* Compute length of class name, it could be that it is not null terminated */
+ if (len_name < prop->size - 1) {
+ len_class = strnlen(((char *) prop->data) + 1 + len_name, prop->size - 1 - len_name);
+ }
+ else {
+ len_class = 0;
+ }
(*res_class) = malloc(len_class + 1);
@@ -95,7 +105,9 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class)
return 0;
}
- strcpy((*res_class), ((char *) prop->data) + 1 + len_name);
+ /* Copy class name and ensure null terminated */
+ memcpy((*res_class), ((char *) prop->data) + 1 + len_name, len_class);
+ (*res_class)[len_class] = '\0';
return 1;
}
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index 0322d9816..9684512da 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -32,510 +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);
- 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
*/
@@ -545,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/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c
index c0c7db2b7..66b0c1ae4 100644
--- a/hw/xwin/winmultiwindowwindow.c
+++ b/hw/xwin/winmultiwindowwindow.c
@@ -55,11 +55,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 +99,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 +247,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 +538,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 +577,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, &pDaddy)) {
if (pDaddy) {
@@ -534,7 +598,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 +640,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 +673,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) 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 +789,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 +804,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 +839,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);
}
@@ -929,6 +1130,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 4f6dec78b..c17cb073a 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -30,6 +30,10 @@
* Colin Harrison
*/
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
/* X headers */
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
@@ -48,7 +52,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>
@@ -60,6 +63,7 @@
#include "window.h"
#include "pixmapstr.h"
#include "windowstr.h"
+#include "winglobals.h"
#ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h>
@@ -69,6 +73,10 @@
#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);
@@ -166,6 +174,9 @@ static int
static int
winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay);
+static void
+winMultiWindowThreadExit(void *arg);
+
static int
winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -183,6 +194,9 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
Bool fAllowOtherWM);
static void
+ winApplyUrgency(Display * pDisplay, Window iWindow, HWND hWnd);
+
+static void
winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle);
void
@@ -429,7 +443,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,6 +466,40 @@ 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;
}
@@ -627,6 +678,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 +734,8 @@ winMultiWindowWMProc(void *pArg)
WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
/* Initialize the Window Manager */
winInitMultiWindowWM(pWMInfo, pProcArg);
@@ -890,6 +946,9 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+
+ pthread_cleanup_pop(0);
+
return NULL;
}
@@ -913,6 +972,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 +994,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 +1021,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);
@@ -1168,6 +1217,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));
@@ -1222,7 +1275,7 @@ winMultiWindowXMsgProc(void *pArg)
}
XCloseDisplay(pProcArg->pDisplay);
- pthread_exit(NULL);
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -1328,17 +1381,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);
@@ -1366,8 +1408,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);
@@ -1470,7 +1511,7 @@ winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr)
static int
winMultiWindowWMIOErrorHandler(Display * pDisplay)
{
- ErrorF("winMultiWindowWMIOErrorHandler!\n\n");
+ ErrorF("winMultiWindowWMIOErrorHandler!\n");
if (pthread_equal(pthread_self(), g_winMultiWindowWMThread)) {
if (g_shutdown)
@@ -1510,7 +1551,7 @@ winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr)
static int
winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay)
{
- ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n\n");
+ ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n");
if (pthread_equal(pthread_self(), g_winMultiWindowXMsgProcThread)) {
/* Restart at the main entry point */
@@ -1524,6 +1565,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
*/
@@ -1578,6 +1630,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)
@@ -1626,23 +1712,27 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
}
if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
- 1L, False, XA_ATOM, &type, &format,
+ MAXINT, False, XA_ATOM, &type, &format,
&nitems, &left,
(unsigned char **) &pAtom) == Success) {
- if (pAtom && nitems == 1) {
- if (*pAtom == skiptaskbarState)
- hint |= HINT_SKIPTASKBAR;
- if (*pAtom == hiddenState)
- maxmin |= HINT_MIN;
- else if (*pAtom == fullscreenState)
- maxmin |= HINT_MAX;
- if (*pAtom == belowState)
- *zstyle = HWND_BOTTOM;
- else if (*pAtom == aboveState)
- *zstyle = HWND_TOPMOST;
- }
- if (pAtom)
+ if (pAtom ) {
+ unsigned long i;
+
+ for (i = 0; i < nitems; i++) {
+ if (pAtom[i] == skiptaskbarState)
+ hint |= HINT_SKIPTASKBAR;
+ if (pAtom[i] == hiddenState)
+ maxmin |= HINT_MIN;
+ else if (pAtom[i] == fullscreenState)
+ maxmin |= HINT_MAX;
+ if (pAtom[i] == belowState)
+ *zstyle = HWND_BOTTOM;
+ else if (pAtom[i] == aboveState)
+ *zstyle = HWND_TOPMOST;
+ }
+
XFree(pAtom);
+ }
}
nitems = left = 0;
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 0e46ea7fe..c1efeb73d 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -316,6 +316,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,
@@ -661,7 +662,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
break;
SetCapture(hwnd);
- return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5,
+ return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
wParam);
case WM_XBUTTONUP:
@@ -670,7 +671,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
ReleaseCapture();
winStartMousePolling(s_pScreenPriv);
return winMouseButtonsHandle(s_pScreen, ButtonRelease,
- HIWORD(wParam) + 5, wParam);
+ HIWORD(wParam) + 7, wParam);
case WM_MOUSEWHEEL:
if (SendMessage
@@ -684,6 +685,18 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
else
break;
+ case WM_MOUSEHWHEEL:
+ if (SendMessage
+ (hwnd, WM_NCHITTEST, 0,
+ MAKELONG(GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam))) == HTCLIENT) {
+ /* Pass the message to the root window */
+ SendMessage(hwndScreen, message, wParam, lParam);
+ return 0;
+ }
+ else
+ break;
+
case WM_SETFOCUS:
if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
break;
@@ -860,7 +873,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:
@@ -993,6 +1008,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
@@ -1017,8 +1042,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:
@@ -1128,3 +1158,41 @@ 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);
+}
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c
index 6cbd7ad80..a39aad8f4 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"
@@ -300,6 +302,110 @@ HandleCustomWM_INITMENU(unsigned long hwndIn, unsigned long hmenuIn)
}
+#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 *) status;
+}
+#endif
+
/*
* Searches for the custom WM_COMMAND command ID and performs action.
* Return TRUE if command is proccessed, FALSE otherwise.
@@ -325,24 +431,17 @@ HandleCustomWM_COMMAND(unsigned long hwndIn, 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:
@@ -651,11 +750,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
@@ -686,7 +791,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;
@@ -727,15 +832,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/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..75e901c1a 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"
@@ -938,6 +942,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 +1086,11 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
+ if (IS_OPTION("-hostintitle")) {
+ g_fHostInTitle = TRUE;
+ return 1;
+ }
+
return 0;
}
@@ -1145,6 +1162,100 @@ 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";
+ LPFN_ISWOW64PROCESS fnIsWow64Process;
+
+ /* 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 == 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 (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;
+ }
+
+ /* Check if we are running under WoW64 */
+ 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 = "";
+ }
+
+ ErrorF("OS: %s %s [%s %ld.%ld build %ld]%s\n",
+ prodName, osvi.szCSDVersion,
+ windowstype, osvi.dwMajorVersion, osvi.dwMinorVersion,
+ osvi.dwBuildNumber, isWow);
+}
+
+/*
* winLogVersionInfo - Log version information
*/
@@ -1161,8 +1272,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/winscrinit.c b/hw/xwin/winscrinit.c
index e776bdba6..f61b8e0a4 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/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c
index 13df18677..be2958338 100644
--- a/hw/xwin/winwin32rootlesswndproc.c
+++ b/hw/xwin/winwin32rootlesswndproc.c
@@ -649,13 +649,13 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
SetCapture(hwnd);
- return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 5,
+ return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 7,
wParam);
case WM_XBUTTONUP:
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
ReleaseCapture();
- return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 5,
+ return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 7,
wParam);
case WM_MOUSEWHEEL:
@@ -667,6 +667,15 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
SendMessage(hwndScreen, message, wParam, lParam);
return 0;
+ case WM_MOUSEHWHEEL:
+#if CYGMULTIWINDOW_DEBUG
+ winDebug("winMWExtWMWindowProc - WM_MOUSEHWHEEL\n");
+#endif
+
+ /* Pass the message to the root window */
+ SendMessage(hwndScreen, message, wParam, lParam);
+ return 0;
+
case WM_MOUSEACTIVATE:
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index 25826ecc7..431a127ee 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -49,6 +49,8 @@
#define WINDOW_TITLE_XDMCP "%s:%s.%d"
#define WIN_SCR_PROP "cyg_screen_prop rl"
#define WINDOW_CLASS_X "cygwin/x X rl"
+#define WINDOW_CLASS_X_CHILD "cygwin/x X child"
+#define WINDOW_CLASS_X_MSG "cygwin/x X msg"
#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 7ba028042..906055fd4 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -42,6 +42,7 @@
#include "winmsg.h"
#include "winmonitors.h"
#include "inputstr.h"
+#include "wmutil/mouse.h"
/*
* Global variables
@@ -896,7 +897,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#endif
)
SetCapture(hwnd);
- return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5,
+ return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
wParam);
case WM_XBUTTONUP:
if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
@@ -908,7 +909,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
)
ReleaseCapture();
return winMouseButtonsHandle(s_pScreen, ButtonRelease,
- HIWORD(wParam) + 5, wParam);
+ HIWORD(wParam) + 7, wParam);
case WM_TIMER:
if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
@@ -918,7 +919,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 */
@@ -978,7 +979,20 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGDEBUG
winDebug("winWindowProc - WM_MOUSEWHEEL\n");
#endif
- winMouseWheel(s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam));
+ /* Button4 = WheelUp */
+ /* Button5 = WheelDown */
+ winMouseWheel(&(s_pScreenPriv->iDeltaZ), GET_WHEEL_DELTA_WPARAM(wParam), Button4, Button5);
+ break;
+
+ case WM_MOUSEHWHEEL:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+#if CYGDEBUG
+ winDebug("winWindowProc - WM_MOUSEHWHEEL\n");
+#endif
+ /* Button7 = TiltRight */
+ /* Button6 = TiltLeft */
+ winMouseWheel(&(s_pScreenPriv->iDeltaV), GET_WHEEL_DELTA_WPARAM(wParam), 7, 6);
break;
case WM_SETFOCUS:
@@ -1066,7 +1080,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
/* Translate Windows key code to X scan code */
- winTranslateKey(wParam, lParam, &iScanCode);
+ iScanCode = winTranslateKey(wParam, lParam);
/* Ignore repeats for CapsLock */
if (wParam == VK_CAPITAL)
@@ -1095,7 +1109,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
/* Enqueue a keyup event */
- winTranslateKey(wParam, lParam, &iScanCode);
+ iScanCode = winTranslateKey(wParam, lParam);
winSendKeyEvent(iScanCode, FALSE);
/* Release all pressed shift keys */
@@ -1149,6 +1163,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Clear any lingering wheel delta */
s_pScreenPriv->iDeltaZ = 0;
+ s_pScreenPriv->iDeltaV = 0;
/* Reshow the Windows mouse cursor if we are being deactivated */
if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE && !g_fCursor) {
@@ -1223,7 +1238,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
- case WM_ENDSESSION:
case WM_GIVEUP:
/* Tell X that we are giving up */
#ifdef XWIN_MULTIWINDOW
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..118d9e849
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.c
@@ -0,0 +1,353 @@
+/*
+ *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;
+ unsigned long *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 =
+ (unsigned long *) calloc(sm_cx *
+ sm_cy,
+ sizeof(unsigned long));
+
+ if (lpBits) {
+ int y;
+ for (y = 0; y < nCY; y++) {
+ unsigned long *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) {
+ /* Bicolor, use a palettized DIB */
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying two color cursor\n");
+ pbmi = (BITMAPINFO *) &bi;
+ 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;
+ pbmi->bmiColors[0].rgbRed = 0; /* Empty */
+ pbmi->bmiColors[0].rgbGreen = 0;
+ pbmi->bmiColors[0].rgbBlue = 0;
+ pbmi->bmiColors[0].rgbReserved = 0;
+ pbmi->bmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
+ pbmi->bmiColors[1].rgbGreen = pCursor->backGreen >> 8;
+ pbmi->bmiColors[1].rgbBlue = pCursor->backBlue >> 8;
+ pbmi->bmiColors[1].rgbReserved = 0;
+ pbmi->bmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
+ pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
+ pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
+ pbmi->bmiColors[2].rgbReserved = 0;
+
+ lpBits =
+ (unsigned long *) 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..a2576304f
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.c
@@ -0,0 +1,553 @@
+/*
+ *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 "icon_convert.h"
+
+/*
+ * global variables
+ */
+extern int 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);
+ 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;
+ 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;
+ 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;
+
+ 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]) {
+ /* 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);
+ }
+
+ 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..e4d0bc61b
--- /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"
+
+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 UINT lastMessage;
+ 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;
+ lastMessage = message;
+ 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..b17a89013
--- /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 */