summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/dmx/config/scanner.l2
-rw-r--r--hw/xwin/InitOutput.c191
-rw-r--r--hw/xwin/Makefile.am25
-rw-r--r--hw/xwin/XWin.rc2
-rw-r--r--hw/xwin/dri/Makefile.am8
-rw-r--r--hw/xwin/dri/windowsdri.c274
-rw-r--r--hw/xwin/dri/windowsdri.h30
-rw-r--r--hw/xwin/glx/Makefile.am7
-rw-r--r--hw/xwin/glx/dri_helpers.c119
-rw-r--r--hw/xwin/glx/dri_helpers.h38
-rw-r--r--hw/xwin/glx/indirect.c595
-rw-r--r--hw/xwin/glx/indirect.h94
-rw-r--r--hw/xwin/glx/winpriv.c44
-rw-r--r--hw/xwin/glx/winpriv.h1
-rw-r--r--hw/xwin/layout_mapping_check.c51
-rw-r--r--hw/xwin/man/XWin.man12
-rw-r--r--hw/xwin/man/XWinrc.man41
-rw-r--r--hw/xwin/system.XWinrc54
-rw-r--r--hw/xwin/win.h76
-rw-r--r--hw/xwin/winallpriv.c14
-rw-r--r--hw/xwin/winauth.c25
-rw-r--r--hw/xwin/winblock.c2
-rw-r--r--hw/xwin/winclipboard/internal.h8
-rw-r--r--hw/xwin/winclipboard/thread.c29
-rw-r--r--hw/xwin/winclipboard/wndproc.c111
-rw-r--r--hw/xwin/winconfig.c80
-rw-r--r--hw/xwin/winconfig.h3
-rw-r--r--hw/xwin/wincreatewnd.c6
-rw-r--r--hw/xwin/wincursor.c306
-rw-r--r--hw/xwin/winengine.c2
-rw-r--r--hw/xwin/winerror.c16
-rw-r--r--hw/xwin/winglobals.c7
-rw-r--r--hw/xwin/winglobals.h5
-rw-r--r--hw/xwin/winkeybd.c290
-rw-r--r--hw/xwin/winlayouts.h5
-rw-r--r--hw/xwin/winmouse.c94
-rw-r--r--hw/xwin/winmsg.c31
-rw-r--r--hw/xwin/winmsg.h21
-rw-r--r--hw/xwin/winmultiwindowclass.h28
-rw-r--r--hw/xwin/winmultiwindowicons.c570
-rw-r--r--hw/xwin/winmultiwindowicons.h4
-rw-r--r--hw/xwin/winmultiwindowwindow.c389
-rw-r--r--hw/xwin/winmultiwindowwm.c1857
-rw-r--r--hw/xwin/winmultiwindowwndproc.c309
-rw-r--r--hw/xwin/winos.c105
-rw-r--r--hw/xwin/winprefs.c147
-rw-r--r--hw/xwin/winprefs.h4
-rw-r--r--hw/xwin/winprefslex.l7
-rw-r--r--hw/xwin/winprefsyacc.y107
-rw-r--r--hw/xwin/winprocarg.c42
-rw-r--r--hw/xwin/winrandr.c92
-rw-r--r--hw/xwin/winscrinit.c16
-rw-r--r--hw/xwin/winshadddnl.c7
-rw-r--r--hw/xwin/winshadgdi.c194
-rw-r--r--hw/xwin/wintaskbar.c2
-rw-r--r--hw/xwin/winvalargs.c19
-rw-r--r--hw/xwin/winwin32rootless.c68
-rw-r--r--hw/xwin/winwin32rootlesswindow.c15
-rw-r--r--hw/xwin/winwin32rootlesswndproc.c240
-rw-r--r--hw/xwin/winwindow.h31
-rw-r--r--hw/xwin/winwindowswm.c2
-rw-r--r--hw/xwin/winwndproc.c52
-rw-r--r--hw/xwin/wmutil/Makefile.am24
-rw-r--r--hw/xwin/wmutil/cursor_convert.c351
-rw-r--r--hw/xwin/wmutil/cursor_convert.h54
-rw-r--r--hw/xwin/wmutil/icon_convert.c572
-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
73 files changed, 5357 insertions, 3235 deletions
diff --git a/hw/dmx/config/scanner.l b/hw/dmx/config/scanner.l
index e527d6df5..b75a440a8 100644
--- a/hw/dmx/config/scanner.l
+++ b/hw/dmx/config/scanner.l
@@ -109,7 +109,7 @@ void yyerror(const char *message)
};
fprintf(stderr, "parse error on line %d at token \"%*.*s\"\n",
- lineno, yyleng, yyleng, yytext);
+ lineno, (int)yyleng, (int)yyleng, yytext);
end = message + strlen(message);
for (pt = message; *pt; pt++) {
if (pt[0] == 'T' && pt[1] == '_') {
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index b6f258313..360b3c61c 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
@@ -66,6 +64,7 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
#include "glx_extinit.h"
#ifdef XWIN_GLX_WINDOWS
#include "glx/glwindows.h"
+#include "dri/windowsdri.h"
#endif
/*
@@ -76,9 +75,6 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
* Function prototypes
*/
-static Bool
- winCheckDisplayNumber(void);
-
void
winLogCommandLine(int argc, char *argv[]);
@@ -92,6 +88,11 @@ Bool
const char *winGetBaseDir(void);
#endif
+static void winCheckMount(void);
+
+extern Bool XSupportsLocale(void);
+extern Status XInitThreads(void);
+
/*
* For the depth 24 pixmap we default to 32 bits per pixel, but
* we change this pixmap format later if we detect that the display
@@ -120,6 +121,9 @@ const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
static const ExtensionModule xwinExtensions[] = {
#ifdef GLXEXT
{ GlxExtensionInit, "GLX", &noGlxExtension },
+#ifdef XWIN_WINDOWS_DRI
+ { WindowsDRIExtensionInit, "Windows-DRI", &noDriExtension },
+#endif
#endif
};
@@ -162,6 +166,8 @@ main(int argc, char *argv[], char *envp[])
{
int iReturn;
+ xorg_crashreport_init(NULL);
+
/* Create & acquire the termination mutex */
iReturn = pthread_mutex_init(&g_pmTerminating, NULL);
if (iReturn != 0) {
@@ -173,6 +179,8 @@ main(int argc, char *argv[], char *envp[])
ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn);
}
+ winCheckMount();
+
return dix_main(argc, argv, envp);
}
@@ -212,10 +220,6 @@ ddxGiveUp(enum ExitCode error)
}
#endif
- if (!g_fLogInited) {
- g_pszLogFile = LogInit(g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
LogClose(error);
/*
@@ -259,6 +263,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)
@@ -283,6 +289,9 @@ winCheckMntOpt(const struct mntent *mnt, const char *opt)
return NULL;
}
+/*
+ Check mounts and issue warnings/activate workarounds as needed
+ */
static void
winCheckMount(void)
{
@@ -292,6 +301,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) {
@@ -330,6 +340,12 @@ winCheckMount(void)
binary = FALSE;
else
binary = TRUE;
+
+ if ((strcmp(ent->mnt_type, "vfat") == 0) ||
+ (strcmp(ent->mnt_type, "exfat") == 0))
+ fat = TRUE;
+ else
+ fat = FALSE;
}
if (endmntent(mnt) != 1) {
@@ -339,6 +355,12 @@ winCheckMount(void)
if (!binary)
winMsg(X_WARNING, "/tmp mounted in textmode\n");
+
+ if (fat) {
+ winMsg(X_WARNING,
+ "/tmp mounted on FAT filesystem, activating -nolock\n");
+ nolock = TRUE;
+ }
}
#else
static void
@@ -594,13 +616,13 @@ winFixupPaths(void)
winMsg(X_ERROR, "Can not determine HOME directory\n");
}
}
- if (!g_fLogFileChanged) {
+ if (!g_fLogFile) {
static char buffer[MAX_PATH];
DWORD size = GetTempPath(sizeof(buffer), buffer);
if (size && size < sizeof(buffer)) {
snprintf(buffer + size, sizeof(buffer) - size,
- "XWin.%s.log", display);
+ g_pszLogFileFormat, display);
buffer[sizeof(buffer) - 1] = 0;
g_pszLogFile = buffer;
winMsg(X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
@@ -631,15 +653,16 @@ OsVendorInit(void)
OsVendorVErrorFProc = OsVendorVErrorF;
#endif
- if (!g_fLogInited) {
- /* keep this order. If LogInit fails it calls Abort which then calls
- * ddxGiveUp where LogInit is called again and creates an infinite
- * recursion. If we set g_fLogInited to TRUE before the init we
- * avoid the second call
- */
- g_fLogInited = TRUE;
- g_pszLogFile = LogInit(g_pszLogFile, NULL);
+ if (serverGeneration == 1) {
+ if (g_pszLogFile)
+ g_pszLogFile = LogInit(g_pszLogFile, ".old");
+ else
+ g_pszLogFile = LogInit(g_pszLogFileFormat, ".old");
+
+ /* Tell crashreporter logfile name */
+ xorg_crashreport_init(g_pszLogFile);
}
+
LogSetParameter(XLOG_FLUSH, 1);
LogSetParameter(XLOG_VERBOSITY, g_iLogVerbose);
LogSetParameter(XLOG_FILE_VERBOSITY, g_iLogVerbose);
@@ -692,6 +715,20 @@ OsVendorInit(void)
}
}
}
+
+ /* Work out what the default resize setting should be, and apply it if it
+ was not explicitly specified */
+ {
+ int j;
+ for (j = 0; j < g_iNumScreens; j++) {
+ if (g_ScreenInfo[j].iResizeMode == resizeDefault) {
+ if (g_ScreenInfo[j].fFullScreen)
+ g_ScreenInfo[j].iResizeMode = resizeNotAllowed;
+ else
+ g_ScreenInfo[j].iResizeMode = resizeWithRandr;
+ }
+ }
+ }
}
static void
@@ -748,10 +785,6 @@ winUseMsg(void)
ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
-#ifdef XWIN_MULTIWINDOWEXTWM
- ErrorF("-internalwm\n" "\tRun the internal window manager.\n");
-#endif
-
#ifdef XWIN_XF86CONFIG
ErrorF("-keyboard\n"
"\tSpecify a keyboard device from the configuration file.\n");
@@ -870,24 +903,7 @@ winUseMsg(void)
void
ddxUseMsg(void)
{
- /* Set a flag so that FatalError won't give duplicate warning message */
- g_fSilentFatalError = TRUE;
-
winUseMsg();
-
- /* Log file will not be opened for UseMsg unless we open it now */
- if (!g_fLogInited) {
- g_pszLogFile = LogInit(g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
- LogClose(EXIT_NO_ERROR);
-
- /* Notify user where UseMsg text can be found. */
- if (!g_fNoHelpMessageBox)
- winMessageBoxF("The " PROJECT_NAME " help text has been printed to "
- "%s.\n"
- "Please open %s to read the help text.\n",
- MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
}
/* See Porting Layer Definition - p. 20 */
@@ -918,14 +934,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())
@@ -1038,11 +1046,27 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
/* Perform some one time initialization */
if (1 == serverGeneration) {
+ const char *locale;
+
+ /* 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, "");
+ locale = setlocale(LC_ALL, "");
+ if (!locale) {
+ ErrorF("setlocale failed.\n");
+ }
+
+ /* See if X supports the current locale */
+ if (XSupportsLocale() == FALSE) {
+ ErrorF("Warning: Locale '%s' not supported by X, falling back to 'C' locale.\n", locale);
+ setlocale(LC_ALL, "C");
+ }
}
#endif
@@ -1050,70 +1074,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];
- const 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 4da3d12a4..ceadd9d20 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -9,9 +9,17 @@ CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
endif
if XWIN_GLX_WINDOWS
-GLX_DIR = glx
-DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS
-XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la
+GLX_DIR =
+DEFS_GLX_WINDOWS =
+XWIN_GLX_LIBS =
+if XWIN_WINDOWS_DRI
+GLX_DIR += dri
+DEFS_GLX_WINDOWS += -DXWIN_WINDOWS_DRI
+XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/dri/libWindowsDRI.la
+endif
+GLX_DIR += glx
+DEFS_GLX_WINDOWS += -DXWIN_GLX_WINDOWS
+XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/glx/libXwinGLX.la
XWIN_GLX_SYS_LIBS = -lopengl32
endif
@@ -25,6 +33,7 @@ SRCS_MULTIWINDOW = \
winSetAppUserModelID.c
DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW
MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32
+MULTIWINDOW_LIBS = $(top_builddir)/hw/xwin/wmutil/libXWinWMUtil.la
endif
if XWIN_MULTIWINDOWEXTWM
@@ -89,8 +98,6 @@ SRCS = InitInput.c \
winconfig.h \
win.h \
winglobals.h \
- winkeybd.h \
- winkeynames.h \
winlayouts.h \
winmessages.h \
winmonitors.h \
@@ -134,6 +141,7 @@ XWIN_LIBS += \
$(top_builddir)/Xi/libXistubs.la
XWin_DEPENDENCIES = \
+ $(MULTIWINDOW_LIBS) \
$(MULTIWINDOWEXTWM_LIBS) \
$(XWIN_GLX_LIBS) \
$(XWIN_LIBS) \
@@ -142,6 +150,7 @@ XWin_DEPENDENCIES = \
XWin_LDADD = \
+ $(MULTIWINDOW_LIBS) \
$(MULTIWINDOWEXTWM_LIBS) \
$(XWIN_GLX_LIBS) \
$(XWIN_LIBS) \
@@ -156,7 +165,7 @@ XWin_LDFLAGS = -mwindows -Wl,--disable-stdcall-fixup $(LD_EXPORT_SYMBOLS_FLAG)
.rc.o:
- $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include
+ $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include -DHOST_TRIPLET=\"$(host)\"
XWin.o: XWin.rc XWin.exe.manifest X.ico
@@ -188,5 +197,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) winclipboard .
-DIST_SUBDIRS = man glx winclipboard .
+SUBDIRS = man $(GLX_DIR) winclipboard wmutil .
+DIST_SUBDIRS = man glx winclipboard wmutil .
diff --git a/hw/xwin/XWin.rc b/hw/xwin/XWin.rc
index a54e0fdbb..e74a9a5ef 100644
--- a/hw/xwin/XWin.rc
+++ b/hw/xwin/XWin.rc
@@ -46,7 +46,7 @@ FONT 8, "MS Shell Dlg 2"
BEGIN
CONTROL IDI_XWIN, IDC_STATIC, "Static", SS_ICON, 8, 8, 32, 32
LTEXT XVENDORNAMESHORT " X Server ", IDC_STATIC, 36, 8, 220, 8
- LTEXT VENDOR_MAN_VERSION, IDC_STATIC, 36, 18, 220, 8
+ LTEXT VENDOR_MAN_VERSION " (" HOST_TRIPLET ")", IDC_STATIC, 36, 18, 220, 8
LTEXT BUILDERSTRING, IDC_STATIC, 36, 28, 220, 8
LTEXT "This software is licensed under the terms of the MIT/X11 License.", IDC_STATIC, 36, 48, 220, 20
CONTROL __VENDORDWEBSUPPORT__, ID_ABOUT_WEBSITE, "Button",
diff --git a/hw/xwin/dri/Makefile.am b/hw/xwin/dri/Makefile.am
new file mode 100644
index 000000000..bdcd48aae
--- /dev/null
+++ b/hw/xwin/dri/Makefile.am
@@ -0,0 +1,8 @@
+noinst_LTLIBRARIES = libWindowsDRI.la
+
+libWindowsDRI_la_SOURCES = \
+ windowsdri.c \
+ windowsdri.h
+
+AM_CFLAGS = $(DIX_CFLAGS) \
+ -I$(top_srcdir)/hw/xwin/
diff --git a/hw/xwin/dri/windowsdri.c b/hw/xwin/dri/windowsdri.c
new file mode 100644
index 000000000..ab18a4691
--- /dev/null
+++ b/hw/xwin/dri/windowsdri.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright © 2014 Jon TURNEY
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/windowsdristr.h>
+
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#include "swaprep.h"
+#include "protocol-versions.h"
+#include "windowsdri.h"
+#include "glx/dri_helpers.h"
+
+static int WindowsDRIErrorBase = 0;
+static unsigned char WindowsDRIReqCode = 0;
+static int WindowsDRIEventBase = 0;
+
+static void
+WindowsDRIResetProc(ExtensionEntry* extEntry)
+{
+}
+
+static int
+ProcWindowsDRIQueryVersion(ClientPtr client)
+{
+ xWindowsDRIQueryVersionReply rep;
+
+ REQUEST_SIZE_MATCH(xWindowsDRIQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_WINDOWSDRI_MAJOR_VERSION;
+ rep.minorVersion = SERVER_WINDOWSDRI_MINOR_VERSION;
+ rep.patchVersion = SERVER_WINDOWSDRI_PATCH_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.majorVersion);
+ swaps(&rep.minorVersion);
+ swapl(&rep.patchVersion);
+ }
+ WriteToClient(client, sizeof(xWindowsDRIQueryVersionReply), &rep);
+ return Success;
+}
+
+static int
+ProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client)
+{
+ xWindowsDRIQueryDirectRenderingCapableReply rep;
+
+ REQUEST(xWindowsDRIQueryDirectRenderingCapableReq);
+ REQUEST_SIZE_MATCH(xWindowsDRIQueryDirectRenderingCapableReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ if (!client->local)
+ rep.isCapable = 0;
+ else
+ rep.isCapable = glxWinGetScreenAiglxIsActive(screenInfo.screens[stuff->screen]);
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ }
+
+ WriteToClient(client,
+ sizeof(xWindowsDRIQueryDirectRenderingCapableReply),
+ &rep);
+ return Success;
+}
+
+static int
+ProcWindowsDRIQueryDrawable(ClientPtr client)
+{
+ xWindowsDRIQueryDrawableReply rep;
+ int rc;
+
+ REQUEST(xWindowsDRIQueryDrawableReq);
+ REQUEST_SIZE_MATCH(xWindowsDRIQueryDrawableReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rc = glxWinQueryDrawable(client, stuff->drawable, &(rep.drawable_type), &(rep.handle));
+
+ if (rc)
+ return rc;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.handle);
+ swapl(&rep.drawable_type);
+ }
+
+ WriteToClient(client, sizeof(xWindowsDRIQueryDrawableReply), &rep);
+ return Success;
+}
+
+static int
+ProcWindowsDRIFBConfigToPixelFormat(ClientPtr client)
+{
+ xWindowsDRIFBConfigToPixelFormatReply rep;
+
+ REQUEST(xWindowsDRIFBConfigToPixelFormatReq);
+ REQUEST_SIZE_MATCH(xWindowsDRIFBConfigToPixelFormatReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rep.pixelFormatIndex = glxWinFBConfigIDToPixelFormatIndex(stuff->screen, stuff->fbConfigID);
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.pixelFormatIndex);
+ }
+
+ WriteToClient(client, sizeof(xWindowsDRIFBConfigToPixelFormatReply), &rep);
+ return Success;
+}
+
+/* dispatch */
+
+static int
+ProcWindowsDRIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_WindowsDRIQueryVersion:
+ return ProcWindowsDRIQueryVersion(client);
+
+ case X_WindowsDRIQueryDirectRenderingCapable:
+ return ProcWindowsDRIQueryDirectRenderingCapable(client);
+ }
+
+ if (!client->local)
+ return WindowsDRIErrorBase + WindowsDRIClientNotLocal;
+
+ switch (stuff->data) {
+ case X_WindowsDRIQueryDrawable:
+ return ProcWindowsDRIQueryDrawable(client);
+
+ case X_WindowsDRIFBConfigToPixelFormat:
+ return ProcWindowsDRIFBConfigToPixelFormat(client);
+
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SNotifyEvent(xWindowsDRINotifyEvent *from,
+ xWindowsDRINotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->time, to->time);
+}
+
+static int
+SProcWindowsDRIQueryVersion(ClientPtr client)
+{
+ REQUEST(xWindowsDRIQueryVersionReq);
+ swaps(&stuff->length);
+ return ProcWindowsDRIQueryVersion(client);
+}
+
+static int
+SProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client)
+{
+ REQUEST(xWindowsDRIQueryDirectRenderingCapableReq);
+ swaps(&stuff->length);
+ swapl(&stuff->screen);
+ return ProcWindowsDRIQueryDirectRenderingCapable(client);
+}
+
+static int
+SProcWindowsDRIQueryDrawable(ClientPtr client)
+{
+ REQUEST(xWindowsDRIQueryDrawableReq);
+ swaps(&stuff->length);
+ swapl(&stuff->screen);
+ swapl(&stuff->drawable);
+ return ProcWindowsDRIQueryDrawable(client);
+}
+
+static int
+SProcWindowsDRIFBConfigToPixelFormat(ClientPtr client)
+{
+ REQUEST(xWindowsDRIFBConfigToPixelFormatReq);
+ swaps(&stuff->length);
+ swapl(&stuff->screen);
+ swapl(&stuff->fbConfigID);
+ return ProcWindowsDRIFBConfigToPixelFormat(client);
+}
+
+static int
+SProcWindowsDRIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_WindowsDRIQueryVersion:
+ return SProcWindowsDRIQueryVersion(client);
+
+ case X_WindowsDRIQueryDirectRenderingCapable:
+ return SProcWindowsDRIQueryDirectRenderingCapable(client);
+ }
+
+ if (!client->local)
+ return WindowsDRIErrorBase + WindowsDRIClientNotLocal;
+
+ switch (stuff->data) {
+ case X_WindowsDRIQueryDrawable:
+ return SProcWindowsDRIQueryDrawable(client);
+
+ case X_WindowsDRIFBConfigToPixelFormat:
+ return SProcWindowsDRIFBConfigToPixelFormat(client);
+
+ default:
+ return BadRequest;
+ }
+}
+
+void
+WindowsDRIExtensionInit(void)
+{
+ ExtensionEntry* extEntry;
+
+ if ((extEntry = AddExtension(WINDOWSDRINAME,
+ WindowsDRINumberEvents,
+ WindowsDRINumberErrors,
+ ProcWindowsDRIDispatch,
+ SProcWindowsDRIDispatch,
+ WindowsDRIResetProc,
+ StandardMinorOpcode))) {
+ size_t i;
+ WindowsDRIReqCode = (unsigned char)extEntry->base;
+ WindowsDRIErrorBase = extEntry->errorBase;
+ WindowsDRIEventBase = extEntry->eventBase;
+ for (i = 0; i < WindowsDRINumberEvents; i++)
+ EventSwapVector[WindowsDRIEventBase + i] = (EventSwapPtr)SNotifyEvent;
+ }
+}
diff --git a/hw/xwin/dri/windowsdri.h b/hw/xwin/dri/windowsdri.h
new file mode 100644
index 000000000..a48c72b04
--- /dev/null
+++ b/hw/xwin/dri/windowsdri.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2014 Jon TURNEY
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef windowsdri_h
+#define windowsdri_h
+
+void WindowsDRIExtensionInit(void);
+Bool noDriExtension;
+
+#endif /* windowsdri_h */
diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am
index f2dffbffb..599ec37cc 100644
--- a/hw/xwin/glx/Makefile.am
+++ b/hw/xwin/glx/Makefile.am
@@ -7,9 +7,16 @@ libXwinGLX_la_SOURCES = \
glwindows.h \
glshim.c \
indirect.c \
+ indirect.h \
wgl_ext_api.c \
wgl_ext_api.h
+if XWIN_WINDOWS_DRI
+libXwinGLX_la_SOURCES += \
+ dri_helpers.c \
+ dri_helpers.h
+endif
+
libnativeGLthunk_la_SOURCES = \
glthunk.c
diff --git a/hw/xwin/glx/dri_helpers.c b/hw/xwin/glx/dri_helpers.c
new file mode 100644
index 000000000..7ed9c9532
--- /dev/null
+++ b/hw/xwin/glx/dri_helpers.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2014 Jon TURNEY
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <glx/glxserver.h>
+#include <glx/glxutil.h>
+#include <X11/extensions/windowsdriconst.h>
+
+#include "indirect.h"
+#include "winpriv.h"
+#include "dri_helpers.h"
+#include "win.h"
+
+extern int validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
+ __GLXdrawable ** drawable, int *err);
+
+int
+glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle)
+{
+ __GLXWinDrawable *pDrawable;
+ int err;
+
+ if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
+ DixReadAccess, (__GLXdrawable **)&pDrawable, &err)) {
+
+ switch (pDrawable->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ HWND h = winGetWindowInfo((WindowPtr)(pDrawable->base.pDraw));
+ *handle = (uintptr_t)h;
+ *type = WindowsDRIDrawableWindow;
+ }
+ break;
+
+ case GLX_DRAWABLE_PIXMAP:
+ glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config);
+ *handle = pDrawable->base.pDraw->id;
+ // XXX: We could use DuplicateHandle to make pDrawble->hSection
+ // available to the requesting process... ?
+ *type = WindowsDRIDrawablePixmap;
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
+ glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config);
+ *handle = (uintptr_t)(pDrawable->hPbuffer);
+ *type = WindowsDRIDrawablePbuffer;
+ break;
+
+ default:
+ assert(FALSE);
+ *handle = 0;
+ }
+ }
+ else {
+ HWND h;
+ /* The drawId XID doesn't identify a GLX drawable. The only other valid
+ alternative is that it is the XID of a window drawable that is being
+ used by the pre-GLX 1.3 interface */
+ DrawablePtr pDraw;
+ int rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
+ if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
+ return err;
+ }
+
+ h = winGetWindowInfo((WindowPtr)(pDraw));
+ *handle = (uintptr_t)h;
+ *type = WindowsDRIDrawableWindow;
+ }
+
+ winDebug("glxWinQueryDrawable: type %d, handle %p\n", *type, (void *)(uintptr_t)*handle);
+ return Success;
+}
+
+int
+glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID)
+{
+ __GLXscreen *screen = glxGetScreen(screenInfo.screens[scr]);
+ __GLXconfig *c;
+
+ for (c = screen->fbconfigs;
+ c != NULL;
+ c = c->next) {
+ if (c->fbconfigID == fbConfigID)
+ return ((GLXWinConfig *)c)->pixelFormatIndex;
+ }
+
+ return 0;
+}
+
+Bool
+glxWinGetScreenAiglxIsActive(ScreenPtr pScreen)
+{
+ winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen);
+ return pWinScreen->fNativeGlActive;
+}
diff --git a/hw/xwin/glx/dri_helpers.h b/hw/xwin/glx/dri_helpers.h
new file mode 100644
index 000000000..05bc9bc93
--- /dev/null
+++ b/hw/xwin/glx/dri_helpers.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2014 Jon TURNEY
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef dri_helpers_h
+#define dri_helpers_h
+
+#include "dixstruct.h"
+
+int
+glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle);
+
+int
+glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID);
+
+Bool
+glxWinGetScreenAiglxIsActive(ScreenPtr pScreen);
+
+#endif /* dri_helpers_h */
diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c
index e4be64228..b9881426c 100644
--- a/hw/xwin/glx/indirect.c
+++ b/hw/xwin/glx/indirect.c
@@ -81,12 +81,13 @@
#include "glwindows.h"
#include <glx/glxserver.h>
#include <glx/glxutil.h>
-#include <glx/extension_string.h>
#include <GL/glxtokens.h>
#include <winpriv.h>
#include <wgl_ext_api.h>
#include <winglobals.h>
+#include <indirect.h>
+#include <setjmp.h>
#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
@@ -101,59 +102,13 @@
#define PFD_SUPPORT_COMPOSITION 0x00008000
#endif
-/* ---------------------------------------------------------------------- */
-/*
- * structure definitions
- */
-
-typedef struct __GLXWinContext __GLXWinContext;
-typedef struct __GLXWinDrawable __GLXWinDrawable;
-typedef struct __GLXWinScreen glxWinScreen;
-typedef struct __GLXWinConfig GLXWinConfig;
-
-struct __GLXWinContext {
- __GLXcontext base;
- HGLRC ctx; /* Windows GL Context */
- __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */
- HWND hwnd; /* For detecting when HWND has changed */
-};
-
-struct __GLXWinDrawable {
- __GLXdrawable base;
- __GLXWinContext *drawContext;
- __GLXWinContext *readContext;
-
- /* If this drawable is GLX_DRAWABLE_PBUFFER */
- HPBUFFERARB hPbuffer;
-
- /* If this drawable is GLX_DRAWABLE_PIXMAP */
- HDC dibDC;
- HBITMAP hDIB;
- HBITMAP hOldDIB; /* original DIB for DC */
- void *pOldBits; /* original pBits for this drawable's pixmap */
-};
-
-struct __GLXWinScreen {
- __GLXscreen base;
-
- /* Supported GLX extensions */
- unsigned char glx_enable_bits[__GLX_EXT_BYTES];
-
- Bool has_WGL_ARB_multisample;
- Bool has_WGL_ARB_pixel_format;
- Bool has_WGL_ARB_pbuffer;
- Bool has_WGL_ARB_render_texture;
-
- /* wrapped screen functions */
- RealizeWindowProcPtr RealizeWindow;
- UnrealizeWindowProcPtr UnrealizeWindow;
- CopyWindowProcPtr CopyWindow;
-};
-
-struct __GLXWinConfig {
- __GLXconfig base;
- int pixelFormatIndex;
-};
+typedef struct {
+ int notOpenGL;
+ int rgbaFloat;
+ int unsignedRgbaFloat;
+ int unknownPixelType;
+ int unaccelerated;
+} PixelFormatRejectStats;
/* ---------------------------------------------------------------------- */
/*
@@ -340,13 +295,16 @@ swap_method_name(int mthd)
}
static void
-fbConfigsDump(unsigned int n, __GLXconfig * c)
+fbConfigsDump(unsigned int n, __GLXconfig * c, PixelFormatRejectStats *rejects)
{
LogMessage(X_INFO, "%d fbConfigs\n", n);
+ LogMessage(X_INFO, "ignored pixel formats: %d not OpenGL, %d RBGA float, %d RGBA unsigned float, %d unknown pixel type, %d unaccelerated\n",
+ rejects->notOpenGL, rejects->rgbaFloat, rejects->unsignedRgbaFloat,
+ rejects->unknownPixelType, rejects->unaccelerated);
if (g_iLogVerbose < 3)
return;
- ErrorF("%d fbConfigs\n", n);
+
ErrorF
("pxf vis fb render Ste aux accum MS drawable Group/\n");
ErrorF
@@ -419,13 +377,15 @@ static Bool glxWinRealizeWindow(WindowPtr pWin);
static Bool glxWinUnrealizeWindow(WindowPtr pWin);
static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
-
+static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
+ __GLXscreen *screen, __GLXconfig *config);
static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
HDC * hdc, HWND * hwnd);
static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
static void glxWinCreateConfigs(HDC dc, glxWinScreen * screen);
-static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen);
+static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen,
+ PixelFormatRejectStats * rejects);
static int fbConfigToPixelFormat(__GLXconfig * mode,
PIXELFORMATDESCRIPTOR * pfdret,
int drawableTypeOverride);
@@ -520,6 +480,30 @@ glxLogExtensions(const char *prefix, const char *extensions)
free(str);
}
+static jmp_buf jmp_sig;
+static struct sigaction old_act;
+extern Bool install_os_signal_handler;
+
+static void
+glxWinScreenProbeSigHandler(int signo, siginfo_t * sip, void *context)
+{
+ // log a message
+ ErrorFSigSafe("segfault in WGL during glxWinScreenProbe()\n");
+
+ // show a messagebox
+ MessageBox(NULL,
+ "Windows OpenGL has been disabled as a crash occurred during initialization.\n"
+ "\n"
+ "Please try updating the display driver.\n"
+ "\n"
+ "You can disable the use of Windows OpenGL by starting the X server using the -nowgl option.",
+ XVENDORNAMESHORT,
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+
+ // continue via longjmp()
+ longjmp(jmp_sig, 1);
+}
+
/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
static __GLXscreen *
glxWinScreenProbe(ScreenPtr pScreen)
@@ -531,6 +515,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
HWND hwnd;
HDC hdc;
HGLRC hglrc;
+ PixelFormatRejectStats rejects;
GLWIN_DEBUG_MSG("glxWinScreenProbe");
@@ -551,8 +536,11 @@ glxWinScreenProbe(ScreenPtr pScreen)
return NULL;
// Select the native GL implementation (WGL)
- if (glWinSelectImplementation(1))
+ if (glWinSelectImplementation(1)) {
+ LogMessage(X_ERROR, "AIGLX: WGL not available\n");
+ free(screen);
return NULL;
+ }
// create window class
#define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
@@ -563,7 +551,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
@@ -578,22 +566,79 @@ glxWinScreenProbe(ScreenPtr pScreen)
}
}
+ // The following tests seem particularly prone to crashing somewhere in the
+ // display driver's OpenGL implementation. So temporarily install a special
+ // SIGSEGV handler so can catch that and offer some remedial advice...
+ if (install_os_signal_handler)
+ {
+ struct sigaction act;
+ sigemptyset(&act.sa_mask);
+ act.sa_sigaction = glxWinScreenProbeSigHandler;
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &act, &old_act);
+
+ if (setjmp(jmp_sig)) {
+ LogMessage(X_ERROR, "AIGLX: Not using WGL due to SEGV\n");
+ goto error;
+ }
+ }
+
// create an invisible window for a scratch DC
hwnd = CreateWindowExA(0,
WIN_GL_TEST_WINDOW_CLASS,
"XWin GL Renderer Capabilities Test Window",
0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL),
NULL);
- if (hwnd == NULL)
+ if (hwnd == NULL) {
LogMessage(X_ERROR,
"AIGLX: Couldn't create a window for render capabilities testing\n");
+ goto error;
+ }
hdc = GetDC(hwnd);
+ if (!hdc) {
+ LogMessage(X_ERROR, "AIGLX: Couldn't create a DC for render capabilities testing\n");
+ goto error;
+ }
+
+ // we must set a pixel format before we can create a context
+ {
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DEPTH_DONTCARE | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE,
+ PFD_TYPE_RGBA,
+ 24,
+ 0, 0, 0, 0, 0, 0,
+ 0,
+ 0,
+ 0,
+ 0, 0, 0, 0,
+ 0,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,
+ 0, 0, 0
+ };
+ int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+ if (iPixelFormat == 0) {
+ LogMessage(X_ERROR, "AIGLX: ChoosePixelFormat failed\n");
+ goto error;
+ }
+
+ if (!SetPixelFormat(hdc, iPixelFormat, NULL)) {
+ LogMessage(X_ERROR, "AIGLX: SetPixelFormat %d failed\n", iPixelFormat);
+ goto error;
+ }
+ LogMessage(X_INFO, "AIGLX: Testing pixelFormatIndex %d\n",iPixelFormat);
+ }
- // we must set a pixel format before we can create a context, just use the first one...
- SetPixelFormat(hdc, 1, NULL);
hglrc = wglCreateContext(hdc);
- wglMakeCurrent(hdc, hglrc);
+ if (!wglMakeCurrent(hdc, hglrc)) {
+ ErrorF("glxWinScreenProbe: wglMakeCurrent error: %08x dc %p ctx %p\n",
+ (unsigned)GetLastError(), hdc, hglrc);
+ }
// initialize wgl extension proc pointers (don't call them before here...)
// (but we need to have a current context for them to be resolvable)
@@ -605,6 +650,8 @@ glxWinScreenProbe(ScreenPtr pScreen)
gl_renderer = (const char *) glGetString(GL_RENDERER);
ErrorF("GL_RENDERER: %s\n", gl_renderer);
gl_extensions = (const char *) glGetString(GL_EXTENSIONS);
+ if (!gl_extensions)
+ gl_extensions = "";
wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
if (!wgl_extensions)
wgl_extensions = "";
@@ -614,10 +661,15 @@ glxWinScreenProbe(ScreenPtr pScreen)
glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions);
}
+ if (!gl_renderer) {
+ LogMessage(X_ERROR,
+ "AIGLX: Native renderer not identified\n");
+ goto error;
+ }
+
if (strcasecmp(gl_renderer, "GDI Generic") == 0) {
- free(screen);
LogMessage(X_ERROR,
- "AIGLX: Won't use generic native renderer as it is not accelerated\n");
+ "AIGLX: Won't use the generic native renderer as it is not accelerated\n");
goto error;
}
@@ -704,8 +756,9 @@ glxWinScreenProbe(ScreenPtr pScreen)
screen->base.pScreen = pScreen;
// Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs
+ memset(&rejects, 0, sizeof(rejects));
if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) {
- glxWinCreateConfigsExt(hdc, screen);
+ glxWinCreateConfigsExt(hdc, screen, &rejects);
/*
Some graphics drivers appear to advertise WGL_ARB_pixel_format,
@@ -718,6 +771,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
}
if (screen->base.numFBConfigs <= 0) {
+ memset(&rejects, 0, sizeof(rejects));
glxWinCreateConfigs(hdc, screen);
screen->has_WGL_ARB_pixel_format = FALSE;
}
@@ -726,7 +780,6 @@ glxWinScreenProbe(ScreenPtr pScreen)
If we still didn't get any fbConfigs, we can't provide GLX for this screen
*/
if (screen->base.numFBConfigs <= 0) {
- free(screen);
LogMessage(X_ERROR,
"AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
goto error;
@@ -778,7 +831,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
DestroyWindow(hwnd);
// dump out fbConfigs now fbConfigIds and visualIDs have been assigned
- fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs);
+ fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs, &rejects);
/* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
screen->RealizeWindow = pScreen->RealizeWindow;
@@ -788,9 +841,20 @@ glxWinScreenProbe(ScreenPtr pScreen)
screen->CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = glxWinCopyWindow;
+ // Note that WGL is active on this screen
+ winSetScreenAiglxIsActive(pScreen);
+
+ // Restore the previous sighandler
+ sigaction(SIGSEGV, &old_act, NULL);
+
return &screen->base;
error:
+ // Restore the previous sighandler
+ sigaction(SIGSEGV, &old_act, NULL);
+
+ free(screen);
+
// Something went wrong and we can't use the native GL implementation
// so make sure the mesa GL implementation is selected instead
glWinSelectImplementation(0);
@@ -934,6 +998,10 @@ glxWinDrawableDestroy(__GLXdrawable * base)
}
if (glxPriv->hDIB) {
+ if (!CloseHandle(glxPriv->hSection)) {
+ ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage());
+ }
+
if (!DeleteObject(glxPriv->hDIB)) {
ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
}
@@ -977,6 +1045,179 @@ glxWinCreateDrawable(ClientPtr client,
return &glxPriv->base;
}
+void
+glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config)
+{
+ switch (draw->base.type) {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ WindowPtr pWin = (WindowPtr) draw->base.pDraw;
+
+ if (!(config->drawableType & GLX_WINDOW_BIT)) {
+ ErrorF
+ ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_WINDOW drawable with a fbConfig which doesn't have drawableType GLX_WINDOW_BIT\n");
+ }
+
+ if (pWin == NULL) {
+ GLWIN_DEBUG_MSG("Deferring until X window is created");
+ return;
+ }
+
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateDrawable: pWin %p", pWin);
+
+ if (winGetWindowInfo(pWin) == NULL) {
+ GLWIN_DEBUG_MSG("Deferring until native window is created");
+ return;
+ }
+ }
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
+ {
+ if (draw->hPbuffer == NULL) {
+ __GLXscreen *screen;
+ glxWinScreen *winScreen;
+ int pixelFormat;
+
+ // XXX: which DC are we supposed to use???
+ HDC screenDC = GetDC(NULL);
+
+ if (!(config->drawableType & GLX_PBUFFER_BIT)) {
+ ErrorF
+ ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PBUFFER drawable with a fbConfig which doesn't have drawableType GLX_PBUFFER_BIT\n");
+ }
+
+ screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
+ winScreen = (glxWinScreen *) screen;
+
+ pixelFormat =
+ fbConfigToPixelFormatIndex(screenDC, config,
+ GLX_PBUFFER_BIT, winScreen);
+ if (pixelFormat == 0) {
+ return;
+ }
+
+ draw->hPbuffer =
+ wglCreatePbufferARBWrapper(screenDC, pixelFormat,
+ draw->base.pDraw->width,
+ draw->base.pDraw->height, NULL);
+ ReleaseDC(NULL, screenDC);
+
+ if (draw->hPbuffer == NULL) {
+ ErrorF("wglCreatePbufferARBWrapper error: %s\n",
+ glxWinErrorMessage());
+ return;
+ }
+
+ GLWIN_DEBUG_MSG
+ ("glxWinDeferredCreateDrawable: pBuffer %p created for drawable %p",
+ draw->hPbuffer, draw);
+ }
+ }
+ break;
+
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ if (draw->dibDC == NULL) {
+ BITMAPINFOHEADER bmpHeader;
+ void *pBits;
+ __GLXscreen *screen;
+ DWORD size;
+ char name[MAX_PATH];
+
+ memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
+ bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmpHeader.biWidth = draw->base.pDraw->width;
+ bmpHeader.biHeight = draw->base.pDraw->height;
+ bmpHeader.biPlanes = 1;
+ bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
+ bmpHeader.biCompression = BI_RGB;
+
+ if (!(config->drawableType & GLX_PIXMAP_BIT)) {
+ ErrorF
+ ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PIXMAP drawable with a fbConfig which doesn't have drawableType GLX_PIXMAP_BIT\n");
+ }
+
+ draw->dibDC = CreateCompatibleDC(NULL);
+ if (draw->dibDC == NULL) {
+ ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+#define RASTERWIDTHBYTES(bmi) (((((bmi)->biWidth*(bmi)->biBitCount)+31)&~31)>>3)
+ size = bmpHeader.biHeight * RASTERWIDTHBYTES(&bmpHeader);
+ ErrorF("shared memory region size %zu + %u\n", sizeof(BITMAPINFOHEADER), size);
+
+ // Create unique name for mapping based on XID
+ //
+ // XXX: not quite unique as potentially this name could be used in
+ // another server instance. Not sure how to deal with that.
+ snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", draw->base.pDraw->id);
+ ErrorF("shared memory region name %s\n", name);
+
+ // Create a file mapping backed by the pagefile
+ draw->hSection = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, 0, sizeof(BITMAPINFOHEADER) + size, name);
+ if (draw->hSection == NULL) {
+ ErrorF("CreateFileMapping error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ draw->hDIB =
+ CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader,
+ DIB_RGB_COLORS, &pBits, draw->hSection, sizeof(BITMAPINFOHEADER));
+ if (draw->dibDC == NULL) {
+ ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ // Store a copy of the BITMAPINFOHEADER at the start of the shared
+ // memory for the information of the receiving process
+ {
+ LPVOID pData = MapViewOfFile(draw->hSection, FILE_MAP_WRITE, 0, 0, 0);
+ memcpy(pData, (void *)&bmpHeader, sizeof(BITMAPINFOHEADER));
+ UnmapViewOfFile(pData);
+ }
+
+ // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
+ // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
+ // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
+ // even compatible ...
+ draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr;
+ ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits;
+
+ // Select the DIB into the DC
+ draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
+ if (!draw->hOldDIB) {
+ ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
+ }
+
+ screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
+
+ // Set the pixel format of the bitmap
+ glxWinSetPixelFormat(draw->dibDC,
+ draw->base.pDraw->bitsPerPixel,
+ GLX_PIXMAP_BIT,
+ screen,
+ config);
+
+ GLWIN_DEBUG_MSG
+ ("glxWinDeferredCreateDrawable: DIB bitmap %p created for drawable %p",
+ draw->hDIB, draw);
+ }
+ }
+ break;
+
+ default:
+ {
+ ErrorF
+ ("glxWinDeferredCreateDrawable: tried to attach unhandled drawable type %d\n",
+ draw->base.type);
+ return;
+ }
+ }
+}
+
/* ---------------------------------------------------------------------- */
/*
* Texture functions
@@ -1020,13 +1261,10 @@ glxWinReleaseTexImage(__GLXcontext * baseContext,
*/
static Bool
-glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
- int drawableTypeOverride)
+glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
+ __GLXscreen *screen, __GLXconfig *config)
{
- __GLXscreen *screen = gc->base.pGlxScreen;
glxWinScreen *winScreen = (glxWinScreen *) screen;
-
- __GLXconfig *config = gc->base.config;
GLXWinConfig *winConfig = (GLXWinConfig *) config;
GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
@@ -1072,12 +1310,35 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
(config->redBits + config->greenBits + config->blueBits), bppOverride,
config->drawableType, drawableTypeOverride);
- if (!winScreen->has_WGL_ARB_pixel_format) {
+ if (winScreen->has_WGL_ARB_pixel_format) {
+ int pixelFormat =
+ fbConfigToPixelFormatIndex(hdc, config,
+ drawableTypeOverride, winScreen);
+ if (pixelFormat != 0) {
+ GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d",
+ pixelFormat);
+ ErrorF
+ ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
+ pixelFormat, winConfig->pixelFormatIndex);
+
+ if (!SetPixelFormat(hdc, pixelFormat, NULL)) {
+ ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
+ return FALSE;
+ }
+ }
+ }
+
+ /*
+ For some drivers, wglChoosePixelFormatARB() can fail when the provided
+ DC doesn't belong to the driver (e.g. it's a compatible DC for a bitmap,
+ so allow fallback to ChoosePixelFormat()
+ */
+ {
PIXELFORMATDESCRIPTOR pfd;
int pixelFormat;
/* convert fbConfig to PFD */
- if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) {
+ if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) {
ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
return FALSE;
}
@@ -1108,25 +1369,6 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
return FALSE;
}
}
- else {
- int pixelFormat =
- fbConfigToPixelFormatIndex(hdc, gc->base.config,
- drawableTypeOverride, winScreen);
- if (pixelFormat == 0) {
- return FALSE;
- }
-
- GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d",
- pixelFormat);
- ErrorF
- ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
- pixelFormat, winConfig->pixelFormatIndex);
-
- if (!SetPixelFormat(hdc, pixelFormat, NULL)) {
- ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
- return FALSE;
- }
- }
return TRUE;
}
@@ -1178,7 +1420,7 @@ glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc,
gc->hwnd = *hwnd;
/* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
- if (!glxWinSetPixelFormat(gc, *hdc, 0, GLX_WINDOW_BIT)) {
+ if (!glxWinSetPixelFormat(*hdc, 0, GLX_WINDOW_BIT, gc->base.pGlxScreen, gc->base.config)) {
ErrorF("glxWinSetPixelFormat error: %s\n",
glxWinErrorMessage());
ReleaseDC(*hwnd, *hdc);
@@ -1264,140 +1506,7 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
("glxWinDeferredCreateContext: attach context %p to drawable %p", gc,
draw);
- switch (draw->base.type) {
- case GLX_DRAWABLE_WINDOW:
- {
- WindowPtr pWin = (WindowPtr) draw->base.pDraw;
-
- if (!(gc->base.config->drawableType & GLX_WINDOW_BIT)) {
- ErrorF
- ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n");
- }
-
- if (pWin == NULL) {
- GLWIN_DEBUG_MSG("Deferring until X window is created");
- return;
- }
-
- GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin);
-
- if (winGetWindowInfo(pWin) == NULL) {
- GLWIN_DEBUG_MSG("Deferring until native window is created");
- return;
- }
- }
- break;
-
- case GLX_DRAWABLE_PBUFFER:
- {
- if (draw->hPbuffer == NULL) {
- __GLXscreen *screen;
- glxWinScreen *winScreen;
- int pixelFormat;
-
- // XXX: which DC are we supposed to use???
- HDC screenDC = GetDC(NULL);
-
- if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) {
- ErrorF
- ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n");
- }
-
- screen = gc->base.pGlxScreen;
- winScreen = (glxWinScreen *) screen;
-
- pixelFormat =
- fbConfigToPixelFormatIndex(screenDC, gc->base.config,
- GLX_PBUFFER_BIT, winScreen);
- if (pixelFormat == 0) {
- return;
- }
-
- draw->hPbuffer =
- wglCreatePbufferARBWrapper(screenDC, pixelFormat,
- draw->base.pDraw->width,
- draw->base.pDraw->height, NULL);
- ReleaseDC(NULL, screenDC);
-
- if (draw->hPbuffer == NULL) {
- ErrorF("wglCreatePbufferARBWrapper error: %s\n",
- glxWinErrorMessage());
- return;
- }
-
- GLWIN_DEBUG_MSG
- ("glxWinDeferredCreateContext: pBuffer %p created for drawable %p",
- draw->hPbuffer, draw);
- }
- }
- break;
-
- case GLX_DRAWABLE_PIXMAP:
- {
- if (draw->dibDC == NULL) {
- BITMAPINFOHEADER bmpHeader;
- void *pBits;
-
- memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
- bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmpHeader.biWidth = draw->base.pDraw->width;
- bmpHeader.biHeight = draw->base.pDraw->height;
- bmpHeader.biPlanes = 1;
- bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
- bmpHeader.biCompression = BI_RGB;
-
- if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT)) {
- ErrorF
- ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n");
- }
-
- draw->dibDC = CreateCompatibleDC(NULL);
- if (draw->dibDC == NULL) {
- ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
- return;
- }
-
- draw->hDIB =
- CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader,
- DIB_RGB_COLORS, &pBits, 0, 0);
- if (draw->dibDC == NULL) {
- ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
- return;
- }
-
- // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
- // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
- // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
- // even compatible ...
- draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr;
- ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits;
-
- // Select the DIB into the DC
- draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
- if (!draw->hOldDIB) {
- ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
- }
-
- // Set the pixel format of the bitmap
- glxWinSetPixelFormat(gc, draw->dibDC,
- draw->base.pDraw->bitsPerPixel,
- GLX_PIXMAP_BIT);
-
- GLWIN_DEBUG_MSG
- ("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p",
- draw->hDIB, draw);
- }
- }
- break;
-
- default:
- {
- ErrorF
- ("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n",
- draw->base.type);
- return;
- }
- }
+ glxWinDeferredCreateDrawable(draw, gc->base.config);
dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
gc->ctx = wglCreateContext(dc);
@@ -1913,6 +2022,8 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen)
/* EXT_visual_rating / GLX 1.2 */
if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
+ continue;
}
else {
// PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
@@ -2047,7 +2158,7 @@ getAttrValue(const int attrs[], int values[], unsigned int num, int attr,
// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
//
static void
-glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
+glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, PixelFormatRejectStats * rejects)
{
GLXWinConfig *c, *result, *prev = NULL;
int i = 0;
@@ -2159,6 +2270,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) {
+ rejects->notOpenGL++;
GLWIN_DEBUG_MSG
("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping",
i + 1);
@@ -2195,11 +2307,13 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
break;
case WGL_TYPE_RGBA_FLOAT_ARB:
+ rejects->rgbaFloat++;
GLWIN_DEBUG_MSG
("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i + 1);
continue;
case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
+ rejects->unsignedRgbaFloat++;
GLWIN_DEBUG_MSG
("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping",
i + 1);
@@ -2212,6 +2326,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
break;
default:
+ rejects->unknownPixelType++;
ErrorF
("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n",
ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
@@ -2252,7 +2367,10 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
case WGL_NO_ACCELERATION_ARB:
+ rejects->unaccelerated++;
c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
+ continue;
break;
case WGL_GENERIC_ACCELERATION_ARB:
@@ -2324,11 +2442,16 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
/* SGIX_pbuffer / GLX 1.3 */
if (screen->has_WGL_ARB_pbuffer) {
- c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
- c->base.maxPbufferHeight =
- ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
- c->base.maxPbufferPixels =
- ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
+ // mesa libGL "can't handle the truth" about max pbuffer size.
+ // We must report 0, which exactly matches what it expects
+ //
+ // ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
+ // ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
+ // ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
+ //
+ c->base.maxPbufferWidth = 0;
+ c->base.maxPbufferHeight = 0;
+ c->base.maxPbufferPixels = 0;
}
else {
c->base.maxPbufferWidth = -1;
diff --git a/hw/xwin/glx/indirect.h b/hw/xwin/glx/indirect.h
new file mode 100644
index 000000000..163375556
--- /dev/null
+++ b/hw/xwin/glx/indirect.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2014 Jon TURNEY
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef indirect_h
+#define indirect_h
+
+#include <X11/Xwindows.h>
+#include <GL/wglext.h>
+#include <glx/extension_string.h>
+
+/* ---------------------------------------------------------------------- */
+/*
+ * structure definitions
+ */
+
+typedef struct __GLXWinContext __GLXWinContext;
+typedef struct __GLXWinDrawable __GLXWinDrawable;
+typedef struct __GLXWinScreen glxWinScreen;
+typedef struct __GLXWinConfig GLXWinConfig;
+
+struct __GLXWinContext {
+ __GLXcontext base;
+ HGLRC ctx; /* Windows GL Context */
+ __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */
+ HWND hwnd; /* For detecting when HWND has changed */
+};
+
+struct __GLXWinDrawable {
+ __GLXdrawable base;
+ __GLXWinContext *drawContext;
+ __GLXWinContext *readContext;
+
+ /* If this drawable is GLX_DRAWABLE_PBUFFER */
+ HPBUFFERARB hPbuffer;
+
+ /* If this drawable is GLX_DRAWABLE_PIXMAP */
+ HDC dibDC;
+ HANDLE hSection; /* file mapping handle */
+ HBITMAP hDIB;
+ HBITMAP hOldDIB; /* original DIB for DC */
+ void *pOldBits; /* original pBits for this drawable's pixmap */
+};
+
+struct __GLXWinScreen {
+ __GLXscreen base;
+
+ /* Supported GLX extensions */
+ unsigned char glx_enable_bits[__GLX_EXT_BYTES];
+
+ Bool has_WGL_ARB_multisample;
+ Bool has_WGL_ARB_pixel_format;
+ Bool has_WGL_ARB_pbuffer;
+ Bool has_WGL_ARB_render_texture;
+
+ /* wrapped screen functions */
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ CopyWindowProcPtr CopyWindow;
+};
+
+struct __GLXWinConfig {
+ __GLXconfig base;
+ int pixelFormatIndex;
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * function prototypes
+ */
+
+void
+glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config);
+
+#endif /* indirect_h */
diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c
index e6afbff01..4bb2b3104 100644
--- a/hw/xwin/glx/winpriv.c
+++ b/hw/xwin/glx/winpriv.c
@@ -14,6 +14,41 @@
void
winCreateWindowsWindow(WindowPtr pWin);
+static void
+winCreateWindowsWindowHierarchy(WindowPtr pWin)
+{
+ winWindowPriv(pWin);
+
+ winDebug("winCreateWindowsWindowHierarchy - pWin:%p XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ if (!pWin)
+ return;
+
+ /* stop recursion at root window */
+ if (pWin == pWin->drawable.pScreen->root)
+ return;
+
+ /* recursively ensure parent window exists */
+ if (pWin->parent)
+ winCreateWindowsWindowHierarchy(pWin->parent);
+
+ /* ensure this window exists */
+ if (pWinPriv->hWnd == NULL) {
+ winCreateWindowsWindow(pWin);
+
+ /* ... and if it's already been mapped, make sure it's visible */
+ if (pWin->mapped) {
+ /* Display the window without activating it */
+ if (pWin->drawable.class != InputOnly)
+ ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE);
+
+ /* Send first paint message */
+ UpdateWindow(pWinPriv->hWnd);
+ }
+ }
+}
+
/**
* Return size and handles of a window.
* If pWin is NULL, then the information for the root window is requested.
@@ -50,7 +85,7 @@ winGetWindowInfo(WindowPtr pWin)
}
if (pWinPriv->hWnd == NULL) {
- winCreateWindowsWindow(pWin);
+ winCreateWindowsWindowHierarchy(pWin);
winDebug("winGetWindowInfo: forcing window to exist\n");
}
@@ -119,3 +154,10 @@ winCheckScreenAiglxIsSupported(ScreenPtr pScreen)
return FALSE;
}
+
+void
+winSetScreenAiglxIsActive(ScreenPtr pScreen)
+{
+ winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen);
+ pWinScreen->fNativeGlActive = TRUE;
+}
diff --git a/hw/xwin/glx/winpriv.h b/hw/xwin/glx/winpriv.h
index dce1edf48..6f695a971 100644
--- a/hw/xwin/glx/winpriv.h
+++ b/hw/xwin/glx/winpriv.h
@@ -9,3 +9,4 @@
HWND winGetWindowInfo(WindowPtr pWin);
Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen);
+void winSetScreenAiglxIsActive(ScreenPtr pScreen);
diff --git a/hw/xwin/layout_mapping_check.c b/hw/xwin/layout_mapping_check.c
new file mode 100644
index 000000000..429be9821
--- /dev/null
+++ b/hw/xwin/layout_mapping_check.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2015 Jon TURNEY
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "winlayouts.h"
+
+int main()
+{
+ WinKBLayoutPtr pLayout;
+ for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
+ char cmd[1024];
+ strcpy(cmd, "setxkbmap ");
+ strcat(cmd, "-layout ");
+ strcat(cmd, pLayout->xkblayout);
+ strcat(cmd, " -model ");
+ strcat(cmd, pLayout->xkbmodel);
+ if (pLayout->xkbvariant) {
+ strcat(cmd, " -variant ");
+ strcat(cmd, pLayout->xkbvariant);
+ }
+ if (pLayout->xkboptions) {
+ strcat(cmd, " -options ");
+ strcat(cmd, pLayout->xkboptions);
+ }
+ if (system(cmd)) {
+ printf("'%s' failed\n", cmd);
+ }
+ }
+}
diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man
index d68ee2a41..d28fb3dbc 100644
--- a/hw/xwin/man/XWin.man
+++ b/hw/xwin/man/XWin.man
@@ -124,7 +124,8 @@ Alternative name for \fB\-resize=scrollbars\fP.
.SH OPTIONS CONTROLLING RESIZE BEHAVIOUR
.TP 8
.B \-resize[=none|scrollbars|randr]
-Select the resize mode of an X screen. The default is randr.
+Select the resize mode of an X screen.
+The default is \fBnone\fP if \fB\-fullscreen\fP is used, \fBrandr\fP otherwise.
.RS
.IP \fB\-resize=none\fP 8
@@ -174,6 +175,12 @@ on its own is equivalent to \fB\-resize=randr\fP
Add the host name to the window title for X applications which are running
on remote hosts, when that information is available and it's useful to do so.
The default is enabled.
+.TP 8
+.B \-compositewm
+Experimental.
+Use Composite extension redirection to maintain a bitmap image of each top-level
+X window, so window contents which are occluded show correctly in task bar and
+task switcher previews.
.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
.TP 8
@@ -350,9 +357,6 @@ Color map manipulation is not supported, so the PseudoColor visual will
not have the correct colors.
This option is intended to allow applications which only work with a depth 8
visual to operate in TrueColor modes.
-.TP 8
-.B \-internalwm
-Run the internal window manager.
.SH LOG FILE
As it runs \fIXWin\fP writes messages indicating the most relevant events
diff --git a/hw/xwin/man/XWinrc.man b/hw/xwin/man/XWinrc.man
index 71d8dad23..60b8ce1ec 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.
@@ -171,7 +200,7 @@ will be used.
.SH Style Instructions
.TP 8
.B STYLES {
-\fIclass-or-name-of-window\fP \fIstyle-keyword-1\fP \fIstyle-keyword-2\fP
+\fIclass-or-name-of-window\fP \fIstyle-keyword-1\fP \fIstyle-keyword-2\fP \fIstyle-keyword-3\fP
.br
\fI...\fP
.br
@@ -216,8 +245,14 @@ No Windows title bar and just a thin-line border, for the class or name.
.br
No Windows title bar or border, for the class or name.
-One keyword in \fIstyle-keyword-1\fP can be used with one keyword in \fIstyle-keyword-2\fP,
-or any keyword can be used singly.
+\fIstyle-keyword-3\fP
+
+\fBSKIPTASKBAR\fP
+.br
+Omit the class or name from being listed in the Windows taskbar.
+
+Up to one keyword from each of these three groups can be used. Not all
+groups need be used, and the keywords can be given in any order.
.SH EXAMPLE
diff --git a/hw/xwin/system.XWinrc b/hw/xwin/system.XWinrc
index f0771c610..87d714a68 100644
--- a/hw/xwin/system.XWinrc
+++ b/hw/xwin/system.XWinrc
@@ -81,38 +81,46 @@
// own configuration file.
// Make some menus...
-menu apps {
- xterm exec "xterm"
- "Emacs" exec "emacs"
- notepad exec notepad
- xload exec "xload -display %display%" # Comment
-}
+# menu apps {
+# xterm exec "xterm"
+# "Emacs" exec "emacs"
+# notepad exec notepad
+# xload exec "xload -display %display%" # Comment
+# }
menu root {
+// "Applications" menu apps
// Comments fit here, too...
- "Reload .XWinrc" RELOAD
- "Applications" menu apps
- SEParATOR
-}
+// SEPARATOR
-menu aot {
- Separator
- "Always on Top" alwaysontop
-}
+ FAQ EXEC "cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html"
+ "User's Guide" EXEC "cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html"
+ SEPARATOR
+ "View logfile" EXEC "xterm -title $XWINLOGFILE -e less +F $XWINLOGFILE"
+ SEPARATOR
-menu xtermspecial {
- "Emacs" exec "emacs"
- "Always on Top" alwaysontop
- SepArAtor
+ "Reload .XWinrc" RELOAD
+ SEParATOR
}
RootMenu root
-DefaultSysMenu aot atend
-
-SysMenu {
- "xterm" xtermspecial atstart
-}
+# menu aot {
+# Separator
+# "Always on Top" alwaysontop
+# }
+#
+# menu xtermspecial {
+# "Emacs" exec "emacs"
+# "Always on Top" alwaysontop
+# SepArAtor
+# }
+#
+# DefaultSysMenu aot atend
+#
+# SysMenu {
+# "xterm" xtermspecial atstart
+# }
# IconDirectory "c:\winnt\"
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 5710ea852..eac91bd7c 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -162,7 +162,6 @@
#include "mipointer.h"
#include "X11/keysym.h"
#include "micoord.h"
-#include "dix.h"
#include "miline.h"
#include "shadow.h"
#include "fb.h"
@@ -272,6 +271,8 @@ typedef Bool (*winFinishScreenInitProcPtr) (int, ScreenPtr, int, char **);
typedef Bool (*winBltExposedRegionsProcPtr) (ScreenPtr);
+typedef Bool (*winBltExposedWindowRegionProcPtr) (ScreenPtr, WindowPtr);
+
typedef Bool (*winActivateAppProcPtr) (ScreenPtr);
typedef Bool (*winRedrawScreenProcPtr) (ScreenPtr pScreen);
@@ -287,38 +288,13 @@ typedef Bool (*winCreateColormapProcPtr) (ColormapPtr pColormap);
typedef Bool (*winDestroyColormapProcPtr) (ColormapPtr pColormap);
-typedef Bool (*winHotKeyAltTabProcPtr) (ScreenPtr);
-
typedef Bool (*winCreatePrimarySurfaceProcPtr) (ScreenPtr);
typedef Bool (*winReleasePrimarySurfaceProcPtr) (ScreenPtr);
-typedef Bool (*winFinishCreateWindowsWindowProcPtr) (WindowPtr pWin);
-
typedef Bool (*winCreateScreenResourcesProc) (ScreenPtr);
/*
- * GC (graphics context) privates
- */
-
-typedef struct {
- HDC hdc;
- HDC hdcMem;
-} winPrivGCRec, *winPrivGCPtr;
-
-/*
- * Pixmap privates
- */
-
-typedef struct {
- HDC hdcSelected;
- HBITMAP hBitmap;
- BYTE *pbBits;
- DWORD dwScanlineBytes;
- BITMAPINFOHEADER *pbmih;
-} winPrivPixmapRec, *winPrivPixmapPtr;
-
-/*
* Colormap privates
*/
@@ -329,6 +305,7 @@ typedef struct {
PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES];
} winPrivCmapRec, *winPrivCmapPtr;
+
/*
* Windows Cursor handling.
*/
@@ -348,7 +325,8 @@ typedef struct {
* Resize modes
*/
typedef enum {
- notAllowed,
+ resizeDefault = -1,
+ resizeNotAllowed,
resizeWithScrollbars,
resizeWithRandr
} winResizeMode;
@@ -404,12 +382,11 @@ typedef struct {
Bool fDecoration;
#ifdef XWIN_MULTIWINDOWEXTWM
Bool fMWExtWM;
- Bool fInternalWM;
- Bool fAnotherWMRunning;
#endif
Bool fRootless;
#ifdef XWIN_MULTIWINDOW
Bool fMultiWindow;
+ Bool fCompositeWM;
#endif
#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
Bool fMultiMonitorOverride;
@@ -517,6 +494,7 @@ typedef struct _winPrivScreenRec {
winCreateBoundingWindowProcPtr pwinCreateBoundingWindow;
winFinishScreenInitProcPtr pwinFinishScreenInit;
winBltExposedRegionsProcPtr pwinBltExposedRegions;
+ winBltExposedWindowRegionProcPtr pwinBltExposedWindowRegion;
winActivateAppProcPtr pwinActivateApp;
winRedrawScreenProcPtr pwinRedrawScreen;
winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette;
@@ -524,17 +502,10 @@ typedef struct _winPrivScreenRec {
winStoreColorsProcPtr pwinStoreColors;
winCreateColormapProcPtr pwinCreateColormap;
winDestroyColormapProcPtr pwinDestroyColormap;
- winHotKeyAltTabProcPtr pwinHotKeyAltTab;
winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface;
winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface;
-
winCreateScreenResourcesProc pwinCreateScreenResources;
-#ifdef XWIN_MULTIWINDOW
- /* Window Procedures for MultiWindow mode */
- winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow;
-#endif
-
/* Window Procedures for Rootless mode */
CreateWindowProcPtr CreateWindow;
DestroyWindowProcPtr DestroyWindow;
@@ -554,6 +525,8 @@ typedef struct _winPrivScreenRec {
SetShapeProcPtr SetShape;
winCursorRec cursor;
+
+ Bool fNativeGlActive;
} winPrivScreenRec;
#ifdef XWIN_MULTIWINDOWEXTWM
@@ -828,9 +801,6 @@ void
*/
int
- winTranslateKey(WPARAM wParam, LPARAM lParam);
-
-int
winKeybdProc(DeviceIntPtr pDeviceInt, int iState);
void
@@ -839,20 +809,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
*/
@@ -881,14 +837,7 @@ int
winMouseProc(DeviceIntPtr pDeviceInt, int iState);
int
- winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown);
-
-void
- winMouseButtonsSendEvent(int iEventType, int iButton);
-
-int
-
-winMouseButtonsHandle(ScreenPtr pScreen,
+ winMouseButtonsHandle(ScreenPtr pScreen,
int iEventType, int iButton, WPARAM wParam);
void
@@ -1027,6 +976,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
/*
@@ -1137,9 +1088,6 @@ winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv,
wBOOL CALLBACK winMWExtWMDecorateWindow(HWND hwnd, LPARAM lParam);
-Bool
- winIsInternalWMRunning(winScreenInfoPtr pScreenInfo);
-
void
winMWExtWMRestackWindows(ScreenPtr pScreen);
#endif
diff --git a/hw/xwin/winallpriv.c b/hw/xwin/winallpriv.c
index 816b030ca..d73fc96cd 100644
--- a/hw/xwin/winallpriv.c
+++ b/hw/xwin/winallpriv.c
@@ -79,20 +79,6 @@ winAllocatePrivates(ScreenPtr pScreen)
/* Save the screen private pointer */
winSetScreenPriv(pScreen, pScreenPriv);
- /* Reserve GC memory for our privates */
- if (!dixRegisterPrivateKey
- (g_iGCPrivateKey, PRIVATE_GC, sizeof(winPrivGCRec))) {
- ErrorF("winAllocatePrivates - AllocateGCPrivate () failed\n");
- return FALSE;
- }
-
- /* Reserve Pixmap memory for our privates */
- if (!dixRegisterPrivateKey
- (g_iPixmapPrivateKey, PRIVATE_PIXMAP, sizeof(winPrivPixmapRec))) {
- ErrorF("winAllocatePrivates - AllocatePixmapPrivates () failed\n");
- return FALSE;
- }
-
/* Reserve Window memory for our privates */
if (!dixRegisterPrivateKey
(g_iWindowPrivateKey, PRIVATE_WINDOW, sizeof(winPrivWinRec))) {
diff --git a/hw/xwin/winauth.c b/hw/xwin/winauth.c
index 7efa1c00f..fcad49e9f 100644
--- a/hw/xwin/winauth.c
+++ b/hw/xwin/winauth.c
@@ -38,6 +38,16 @@
#include "securitysrv.h"
#include "os/osdep.h"
+#include <xcb/xcb.h>
+
+/* Need to get this from Xlib.h */
+extern void XSetAuthorization(
+ const char * /* name */,
+ int /* namelen */,
+ const char * /* data */,
+ int /* datalen */
+);
+
/*
* Constants
*/
@@ -51,6 +61,7 @@
static XID g_authId = 0;
static unsigned int g_uiAuthDataLen = 0;
static char *g_pAuthData = NULL;
+static xcb_auth_info_t auth_info;
/*
* Code to generate a MIT-MAGIC-COOKIE-1, copied from under XCSECURITY
@@ -132,6 +143,11 @@ winGenerateAuthorization(void)
g_uiAuthDataLen, g_pAuthData);
}
+ auth_info.name = AUTH_NAME;
+ auth_info.namelen = strlen(AUTH_NAME);
+ auth_info.data = g_pAuthData;
+ auth_info.datalen = g_uiAuthDataLen;
+
#ifdef XCSECURITY
/* Allocate structure for additional auth information */
pAuth = (SecurityAuthorizationPtr)
@@ -179,3 +195,12 @@ winSetAuthorization(void)
XSetAuthorization(AUTH_NAME,
strlen(AUTH_NAME), g_pAuthData, g_uiAuthDataLen);
}
+
+xcb_auth_info_t *
+winGetXcbAuthInfo(void)
+{
+ if (g_pAuthData)
+ return &auth_info;
+
+ return NULL;
+}
diff --git a/hw/xwin/winblock.c b/hw/xwin/winblock.c
index 07e907828..8b846520c 100644
--- a/hw/xwin/winblock.c
+++ b/hw/xwin/winblock.c
@@ -70,7 +70,7 @@ winBlockHandler(ScreenPtr pScreen,
if (pScreenPriv != NULL && !pScreenPriv->fServerStarted) {
int iReturn;
- ErrorF("winBlockHandler - pthread_mutex_unlock()\n");
+ winDebug("winBlockHandler - pthread_mutex_unlock()\n");
/* Flag that modules are to be started */
pScreenPriv->fServerStarted = TRUE;
diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index 6c26caf2e..d0d8fbda1 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -77,6 +77,14 @@ typedef struct
Atom atomTargets;
} ClipboardAtoms;
+/* Modern clipboard API functions */
+typedef wBOOL WINAPI (*ADDCLIPBOARDFORMATLISTENERPROC)(HWND hwnd);
+typedef wBOOL WINAPI (*REMOVECLIPBOARDFORMATLISTENERPROC)(HWND hwnd);
+
+extern Bool g_fHasModernClipboardApi;
+extern ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
+extern REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
+
/*
* winclipboardwndproc.c
*/
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 50e1e8cb5..58b3bf74d 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -84,6 +84,10 @@ static pthread_t g_winClipboardProcThread;
int xfixes_event_base;
int xfixes_error_base;
+Bool g_fHasModernClipboardApi = FALSE;
+ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
+REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
+
/*
* Local function prototypes
*/
@@ -127,16 +131,10 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
winDebug("winClipboardProc - Hello\n");
- /* 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");
- }
+ g_fpAddClipboardFormatListener = (ADDCLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"AddClipboardFormatListener");
+ g_fpRemoveClipboardFormatListener = (REMOVECLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"RemoveClipboardFormatListener");
+ g_fHasModernClipboardApi = g_fpAddClipboardFormatListener && g_fpRemoveClipboardFormatListener;
+ ErrorF("OS maintains clipboard viewer chain: %s\n", g_fHasModernClipboardApi ? "yes" : "no");
g_winClipboardProcThread = pthread_self();
@@ -165,7 +163,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
"successfully opened the display.\n");
/* Get our connection number */
- iConnectionNumber = ConnectionNumber(pDisplay);
+ iConnectionNumber = XConnectionNumber(pDisplay);
#ifdef HAS_DEVWINDOWS
/* Open a file descriptor for the windows message queue */
@@ -193,12 +191,12 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
/* Create a messaging window */
iWindow = XCreateSimpleWindow(pDisplay,
- DefaultRootWindow(pDisplay),
+ XDefaultRootWindow(pDisplay),
1, 1,
500, 500,
0,
- BlackPixel(pDisplay, 0),
- BlackPixel(pDisplay, 0));
+ XBlackPixel(pDisplay, 0),
+ XBlackPixel(pDisplay, 0));
if (iWindow == 0) {
ErrorF("winClipboardProc - Could not create an X window.\n");
goto winClipboardProc_Done;
@@ -344,7 +342,6 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
#endif
}
- winClipboardProc_Exit:
/* broke out of while loop on a shutdown message */
fShutdown = TRUE;
@@ -382,7 +379,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
XSync(pDisplay, TRUE);
/* Select event types to watch */
- XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
+ XSelectInput(pDisplay, XDefaultRootWindow(pDisplay), None);
/* Close our X display */
if (pDisplay) {
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index d17cf2e86..91f874f61 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -58,6 +58,9 @@
#define WIN_POLL_TIMEOUT 1
+#ifndef WM_CLIPBOARDUPDATE
+#define WM_CLIPBOARDUPDATE 0x031D
+#endif
/*
* Process X events up to specified timeout
@@ -76,7 +79,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
iTimeoutSec);
/* Get our connection number */
- iConnNumber = ConnectionNumber(pDisplay);
+ iConnNumber = XConnectionNumber(pDisplay);
/* Loop for X events */
while (1) {
@@ -151,8 +154,16 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
winDebug("winClipboardWindowProc - WM_DESTROY\n");
- /* Remove ourselves from the clipboard chain */
- ChangeClipboardChain(hwnd, s_hwndNextViewer);
+ if (g_fHasModernClipboardApi)
+ {
+ /* Remove clipboard listener */
+ g_fpRemoveClipboardFormatListener(hwnd);
+ }
+ else
+ {
+ /* Remove ourselves from the clipboard chain */
+ ChangeClipboardChain(hwnd, s_hwndNextViewer);
+ }
s_hwndNextViewer = NULL;
}
@@ -168,8 +179,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_CREATE:
{
- HWND first, next;
- DWORD error_code = 0;
ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
winDebug("winClipboardWindowProc - WM_CREATE\n");
@@ -179,16 +188,26 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
atoms = cwcp->atoms;
fRunning = TRUE;
- first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
- if (first == hwnd)
- return 0; /* Make sure it's not us! */
- /* Add ourselves to the clipboard viewer chain */
- next = SetClipboardViewer(hwnd);
- error_code = GetLastError();
- if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */
- s_hwndNextViewer = next; /* it returned must have been the first window in the chain */
+ if (g_fHasModernClipboardApi)
+ {
+ g_fpAddClipboardFormatListener(hwnd);
+ }
else
- s_fCBCInitialized = FALSE;
+ {
+ HWND first, next;
+ DWORD error_code = 0;
+
+ first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
+ if (first == hwnd)
+ return 0; /* Make sure it's not us! */
+ /* Add ourselves to the clipboard viewer chain */
+ next = SetClipboardViewer(hwnd);
+ error_code = GetLastError();
+ if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */
+ s_hwndNextViewer = next; /* it returned must have been the first window in the chain */
+ else
+ s_fCBCInitialized = FALSE;
+ }
}
return 0;
@@ -233,6 +252,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
+ if (g_fHasModernClipboardApi)
+ {
+ return 0;
+ }
+
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
if (first == hwnd)
return 0; /* Make sure it's not us! */
@@ -257,38 +281,45 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
case WM_DRAWCLIPBOARD:
+ case WM_CLIPBOARDUPDATE:
{
static Bool s_fProcessingDrawClipboard = FALSE;
int iReturn;
- winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
+ if (message == WM_DRAWCLIPBOARD)
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
+ else
+ winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n");
- /*
- * We've occasionally seen a loop in the clipboard chain.
- * Try and fix it on the first hint of recursion.
- */
- if (!s_fProcessingDrawClipboard) {
- s_fProcessingDrawClipboard = TRUE;
- }
- else {
- /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
- s_fCBCInitialized = FALSE;
- ChangeClipboardChain(hwnd, s_hwndNextViewer);
- winFixClipboardChain();
- ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Nested calls detected. Re-initing.\n");
- winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
- s_fProcessingDrawClipboard = FALSE;
- return 0;
- }
+ if (!g_fHasModernClipboardApi)
+ {
+ /*
+ * We've occasionally seen a loop in the clipboard chain.
+ * Try and fix it on the first hint of recursion.
+ */
+ if (!s_fProcessingDrawClipboard) {
+ s_fProcessingDrawClipboard = TRUE;
+ }
+ else {
+ /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
+ s_fCBCInitialized = FALSE;
+ ChangeClipboardChain(hwnd, s_hwndNextViewer);
+ winFixClipboardChain();
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Nested calls detected. Re-initing.\n");
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ s_fProcessingDrawClipboard = FALSE;
+ return 0;
+ }
- /* Bail on first message */
- if (!s_fCBCInitialized) {
- s_fCBCInitialized = TRUE;
- s_fProcessingDrawClipboard = FALSE;
- winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
- return 0;
- }
+ /* Bail on first message */
+ if (!s_fCBCInitialized) {
+ s_fCBCInitialized = TRUE;
+ s_fProcessingDrawClipboard = FALSE;
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ return 0;
+ }
+ }
/*
* NOTE: We cannot bail out when NULL == GetClipboardOwner ()
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index d26cc9376..488171b8a 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 */
@@ -224,7 +225,8 @@ winConfigKeyboard(DeviceIntPtr pDevice)
{
char layoutName[KL_NAMELENGTH];
unsigned char layoutFriendlyName[256];
- static unsigned int layoutNum = 0;
+ unsigned int layoutNum = 0;
+ unsigned int deviceIdentifier = 0;
int keyboardType;
#ifdef XWIN_XF86CONFIG
@@ -263,8 +265,9 @@ winConfigKeyboard(DeviceIntPtr pDevice)
break;
}
g_winInfo.keyboard.rate = (kbd_speed > 0) ? kbd_speed : 1;
- winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%ld, rate=%ld\n",
- g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
+ winMsg(X_PROBED, "Setting autorepeat to delay=%ld, rate=%ld\n",
+ g_winInfo.keyboard.delay, g_winInfo.keyboard.rate);
+
}
}
@@ -272,15 +275,10 @@ winConfigKeyboard(DeviceIntPtr pDevice)
if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) {
WinKBLayoutPtr pLayout;
Bool bfound = FALSE;
+ int pass;
- if (!layoutNum)
- layoutNum = strtoul(layoutName, (char **) NULL, 16);
+ layoutNum = strtoul(layoutName, (char **) NULL, 16);
if ((layoutNum & 0xffff) == 0x411) {
- /* The japanese layouts know a lot of different IMEs which all have
- different layout numbers set. Map them to a single entry.
- Same might apply for chinese, korean and other symbol languages
- too */
- layoutNum = (layoutNum & 0xffff);
if (keyboardType == 7) {
/* Japanese layouts have problems with key event messages
such as the lack of WM_KEYUP for Caps Lock key.
@@ -318,31 +316,47 @@ winConfigKeyboard(DeviceIntPtr pDevice)
"Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n",
layoutName, layoutNum, layoutFriendlyName, keyboardType);
- for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
- if (pLayout->winlayout != layoutNum)
- continue;
- if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
- continue;
-
- bfound = TRUE;
- winMsg(X_PROBED,
- "Found matching XKB configuration \"%s\"\n",
- pLayout->layoutname);
-
- winMsg(X_PROBED,
- "Model = \"%s\" Layout = \"%s\""
- " Variant = \"%s\" Options = \"%s\"\n",
- pLayout->xkbmodel ? pLayout->xkbmodel : "none",
- pLayout->xkblayout ? pLayout->xkblayout : "none",
- pLayout->xkbvariant ? pLayout->xkbvariant : "none",
- pLayout->xkboptions ? pLayout->xkboptions : "none");
+ deviceIdentifier = layoutNum >> 16;
+ for (pass = 0; pass < 2; pass++) {
+ /* If we didn't find an exact match for the input locale identifer,
+ try to find an match on the language identifier part only */
+ if (pass == 1)
+ layoutNum = (layoutNum & 0xffff);
+
+ for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) {
+ if (pLayout->winlayout != layoutNum)
+ continue;
+ if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType)
+ continue;
+
+ bfound = TRUE;
+ winMsg(X_PROBED,
+ "Found matching XKB configuration \"%s\"\n",
+ pLayout->layoutname);
+
+ winMsg(X_PROBED,
+ "Model = \"%s\" Layout = \"%s\""
+ " Variant = \"%s\" Options = \"%s\"\n",
+ pLayout->xkbmodel ? pLayout->xkbmodel : "none",
+ pLayout->xkblayout ? pLayout->xkblayout : "none",
+ pLayout->xkbvariant ? pLayout->xkbvariant : "none",
+ pLayout->xkboptions ? pLayout->xkboptions : "none");
+
+ g_winInfo.xkb.model = pLayout->xkbmodel;
+ g_winInfo.xkb.layout = pLayout->xkblayout;
+ g_winInfo.xkb.variant = pLayout->xkbvariant;
+ g_winInfo.xkb.options = pLayout->xkboptions;
+
+ if (deviceIdentifier == 0xa000) {
+ winMsg(X_PROBED, "Windows keyboard layout device identifier indicates Macintosh, setting Model = \"macintosh\"");
+ g_winInfo.xkb.model = "macintosh";
+ }
- g_winInfo.xkb.model = pLayout->xkbmodel;
- g_winInfo.xkb.layout = pLayout->xkblayout;
- g_winInfo.xkb.variant = pLayout->xkbvariant;
- g_winInfo.xkb.options = pLayout->xkboptions;
+ break;
+ }
- break;
+ if (bfound)
+ break;
}
if (!bfound) {
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index f079368c7..2edaf4df2 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -159,6 +159,7 @@ typedef struct {
#ifdef XWIN_XF86CONFIG
char *keyboard;
#endif
+ Bool customDPI;
char *xkbRules;
char *xkbModel;
char *xkbLayout;
@@ -199,7 +200,7 @@ typedef union {
unsigned long num;
char *str;
double realnum;
- Bool bool;
+ Bool bool_;
OptFrequency freq;
} ValueUnion;
diff --git a/hw/xwin/wincreatewnd.c b/hw/xwin/wincreatewnd.c
index b2f797c51..e6e587f9f 100644
--- a/hw/xwin/wincreatewnd.c
+++ b/hw/xwin/wincreatewnd.c
@@ -171,7 +171,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen)
fForceShowWindow = TRUE;
}
dwWindowStyle |= WS_CAPTION;
- if (pScreenInfo->iResizeMode != notAllowed)
+ if (pScreenInfo->iResizeMode != resizeNotAllowed)
dwWindowStyle |= WS_THICKFRAME | WS_MAXIMIZEBOX;
}
else
@@ -226,7 +226,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen)
)
&& (pScreenInfo->iResizeMode == resizeWithScrollbars)) {
/* We cannot have scrollbars if we do not have a window border */
- pScreenInfo->iResizeMode = notAllowed;
+ pScreenInfo->iResizeMode = resizeNotAllowed;
}
/* Did the user specify a height and width? */
@@ -253,7 +253,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen)
#endif
/* Are we resizable */
- if (pScreenInfo->iResizeMode != notAllowed) {
+ if (pScreenInfo->iResizeMode != resizeNotAllowed) {
#if CYGDEBUG
winDebug
("winCreateBoundingWindowWindowed - Window is resizable\n");
diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c
index bddd6b7ed..285da3b6f 100644
--- a/hw/xwin/wincursor.c
+++ b/hw/xwin/wincursor.c
@@ -34,14 +34,14 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "winmsg.h"
#include <cursorstr.h>
#include <mipointrst.h>
#include <servermd.h>
#include "misc.h"
-
-#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114)
+#include "wmutil/cursor_convert.h"
#if 0
#define WIN_DEBUG_MSG winDebug
@@ -128,296 +128,30 @@ winCrossScreen(ScreenPtr pScreen, Bool fEntering)
{
}
-static unsigned char
-reverse(unsigned char c)
-{
- int i;
- unsigned char ret = 0;
-
- for (i = 0; i < 8; ++i) {
- ret |= ((c >> i) & 1) << (7 - i);
- }
- return ret;
-}
-
/*
* Convert X cursor to Windows cursor
- * FIXME: Perhaps there are more smart code
*/
static HCURSOR
winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen)
{
- winScreenPriv(pScreen);
- HCURSOR hCursor = NULL;
- unsigned char *pAnd;
- unsigned char *pXor;
- int nCX, nCY;
- int nBytes;
- double dForeY, dBackY;
- BOOL fReverse;
- HBITMAP hAnd, hXor;
- ICONINFO ii;
- unsigned char *pCur;
- unsigned char bit;
- HDC hDC;
- BITMAPV4HEADER bi;
- BITMAPINFO *pbmi;
- uint32_t *lpBits;
-
- WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height,
- pCursor->bits->xhot, pCursor->bits->yhot);
-
- /* We can use only White and Black, so calc brightness of color
- * Also check if the cursor is inverted */
- dForeY = BRIGHTNESS(pCursor->fore);
- dBackY = BRIGHTNESS(pCursor->back);
- fReverse = dForeY < dBackY;
-
- /* Check wether the X11 cursor is bigger than the win32 cursor */
- if (pScreenPriv->cursor.sm_cx < pCursor->bits->width ||
- pScreenPriv->cursor.sm_cy < pCursor->bits->height) {
- winErrorFVerb(3,
- "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height);
- }
-
- /* Get the number of bytes required to store the whole cursor image
- * This is roughly (sm_cx * sm_cy) / 8
- * round up to 8 pixel boundary so we can convert whole bytes */
- nBytes =
- bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy;
-
- /* Get the effective width and height */
- nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width);
- nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height);
-
- /* Allocate memory for the bitmaps */
- pAnd = malloc(nBytes);
- memset(pAnd, 0xFF, nBytes);
- pXor = calloc(1, nBytes);
-
- /* Convert the X11 bitmap to a win32 bitmap
- * The first is for an empty mask */
- if (pCursor->bits->emptyMask) {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- pAnd[nWinPix] = 0;
- if (fReverse)
- pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]);
- else
- pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]);
- }
- }
- else {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- unsigned char mask = pCursor->bits->mask[nXPix];
-
- pAnd[nWinPix] = reverse(~mask);
- if (fReverse)
- pXor[nWinPix] =
- reverse(~pCursor->bits->source[nXPix] & mask);
- else
- pXor[nWinPix] =
- reverse(pCursor->bits->source[nXPix] & mask);
- }
- }
-
- /* prepare the pointers */
- hCursor = NULL;
- lpBits = NULL;
-
- /* We have a truecolor alpha-blended cursor and can use it! */
- if (pCursor->bits->argb) {
- WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n");
- memset(&bi, 0, sizeof(BITMAPV4HEADER));
- bi.bV4Size = sizeof(BITMAPV4HEADER);
- bi.bV4Width = pScreenPriv->cursor.sm_cx;
- bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */
- bi.bV4Planes = 1;
- bi.bV4BitCount = 32;
- bi.bV4V4Compression = BI_BITFIELDS;
- bi.bV4RedMask = 0x00FF0000;
- bi.bV4GreenMask = 0x0000FF00;
- bi.bV4BlueMask = 0x000000FF;
- bi.bV4AlphaMask = 0xFF000000;
-
- lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy,
- sizeof(uint32_t));
-
- if (lpBits) {
- int y;
- for (y = 0; y < nCY; y++) {
- void *src, *dst;
- src = &(pCursor->bits->argb[y * pCursor->bits->width]);
- dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]);
- memcpy(dst, src, 4 * nCX);
- }
- }
- } /* End if-truecolor-icon */
-
- if (!lpBits) {
- RGBQUAD *pbmiColors;
- /* Bicolor, use a palettized DIB */
- WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n");
- pbmi = (BITMAPINFO *) &bi;
- pbmiColors = &(pbmi->bmiColors[0]);
-
- memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx;
- pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */
- pbmi->bmiHeader.biPlanes = 1;
- pbmi->bmiHeader.biBitCount = 8;
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biClrUsed = 3;
- pbmi->bmiHeader.biClrImportant = 3;
-
- pbmiColors[0].rgbRed = 0; /* Empty */
- pbmiColors[0].rgbGreen = 0;
- pbmiColors[0].rgbBlue = 0;
- pbmiColors[0].rgbReserved = 0;
- pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
- pbmiColors[1].rgbGreen = pCursor->backGreen >> 8;
- pbmiColors[1].rgbBlue = pCursor->backBlue >> 8;
- pbmiColors[1].rgbReserved = 0;
- pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
- pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
- pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
- pbmiColors[2].rgbReserved = 0;
-
- lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1);
-
- pCur = (unsigned char *) lpBits;
- if (lpBits) {
- int x, y;
- for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) {
- for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) {
- if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */
- (*pCur++) = 0;
- else { /* Within X11 icon bounds */
-
- int nWinPix =
- bits_to_bytes(pScreenPriv->cursor.sm_cx) * y +
- (x / 8);
-
- bit = pAnd[nWinPix];
- bit = bit & (1 << (7 - (x & 7)));
- if (!bit) { /* Within the cursor mask? */
- int nXPix =
- BitmapBytePad(pCursor->bits->width) * y +
- (x / 8);
- bit =
- ~reverse(~pCursor->bits->
- source[nXPix] & pCursor->bits->
- mask[nXPix]);
- bit = bit & (1 << (7 - (x & 7)));
- if (bit) /* Draw foreground */
- (*pCur++) = 2;
- else /* Draw background */
- (*pCur++) = 1;
- }
- else /* Outside the cursor mask */
- (*pCur++) = 0;
- }
- } /* end for (x) */
- } /* end for (y) */
- } /* end if (lpbits) */
- }
-
- /* If one of the previous two methods gave us the bitmap we need, make a cursor */
- if (lpBits) {
- WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n",
- pCursor->bits->xhot, pCursor->bits->yhot);
-
- hAnd = NULL;
- hXor = NULL;
-
- hAnd =
- CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- 1, 1, pAnd);
-
- hDC = GetDC(NULL);
- if (hDC) {
- hXor =
- CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx,
- pScreenPriv->cursor.sm_cy);
- SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits,
- (BITMAPINFO *) &bi, DIB_RGB_COLORS);
- ReleaseDC(NULL, hDC);
- }
- free(lpBits);
-
- if (hAnd && hXor) {
- ii.fIcon = FALSE;
- ii.xHotspot = pCursor->bits->xhot;
- ii.yHotspot = pCursor->bits->yhot;
- ii.hbmMask = hAnd;
- ii.hbmColor = hXor;
- hCursor = (HCURSOR) CreateIconIndirect(&ii);
-
- if (hCursor == NULL)
- winW32Error(2, "winLoadCursor - CreateIconIndirect failed:");
- else {
- if (GetIconInfo(hCursor, &ii)) {
- if (ii.fIcon) {
- WIN_DEBUG_MSG
- ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n");
-
- DestroyCursor(hCursor);
-
- ii.fIcon = FALSE;
- ii.xHotspot = pCursor->bits->xhot;
- ii.yHotspot = pCursor->bits->yhot;
- hCursor = (HCURSOR) CreateIconIndirect(&ii);
-
- if (hCursor == NULL)
- winW32Error(2,
- "winLoadCursor - CreateIconIndirect failed:");
- }
- /* GetIconInfo creates new bitmaps. Destroy them again */
- if (ii.hbmMask)
- DeleteObject(ii.hbmMask);
- if (ii.hbmColor)
- DeleteObject(ii.hbmColor);
- }
- }
- }
-
- if (hAnd)
- DeleteObject(hAnd);
- if (hXor)
- DeleteObject(hXor);
- }
-
- if (!hCursor) {
- /* We couldn't make a color cursor for this screen, use
- black and white instead */
- hCursor = CreateCursor(g_hInstance,
- pCursor->bits->xhot, pCursor->bits->yhot,
- pScreenPriv->cursor.sm_cx,
- pScreenPriv->cursor.sm_cy, pAnd, pXor);
- if (hCursor == NULL)
- winW32Error(2, "winLoadCursor - CreateCursor failed:");
- }
- free(pAnd);
- free(pXor);
-
- return hCursor;
+ WMUTIL_CURSOR cursor;
+
+ cursor.width = pCursor->bits->width;
+ cursor.height = pCursor->bits->height;
+ cursor.xhot = pCursor->bits->xhot;
+ cursor.yhot = pCursor->bits->yhot;
+ cursor.argb = (uint32_t *)pCursor->bits->argb;
+ cursor.source = pCursor->bits->source;
+ cursor.mask = pCursor->bits->mask;
+ cursor.emptyMask = pCursor->bits->emptyMask;
+ cursor.foreRed = pCursor->foreRed;
+ cursor.foreGreen = pCursor->foreGreen;
+ cursor.foreBlue = pCursor->foreBlue;
+ cursor.backRed = pCursor->backRed;
+ cursor.backGreen = pCursor->backGreen;
+ cursor.backBlue = pCursor->backBlue;
+
+ return winXCursorToHCURSOR(&cursor);
}
/*
diff --git a/hw/xwin/winengine.c b/hw/xwin/winengine.c
index b8f8da06b..d816851e2 100644
--- a/hw/xwin/winengine.c
+++ b/hw/xwin/winengine.c
@@ -203,7 +203,7 @@ winSetEngine(ScreenPtr pScreen)
return TRUE;
}
- return TRUE;
+ return FALSE;
}
/*
diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c
index 1318b0f36..09b8dda0c 100644
--- a/hw/xwin/winerror.c
+++ b/hw/xwin/winerror.c
@@ -69,14 +69,20 @@ OsVendorFatalError(const char *f, va_list args)
{
char errormsg[1024] = "";
- /* Don't give duplicate warning if UseMsg was called */
+ /* If we want to silence it,
+ * detect if we are going to abort due to duplication error */
+ if (g_fSilentDupError) {
+ if ((strcmp(f, "InitOutput - Duplicate invocation on display number: %s. Exiting.\n") == 0)
+ || (strcmp(f, "Server is already active for display %s\n%s %s\n%s\n") == 0)
+ || (strcmp(f, "MakeAllCOTSServerListeners: server already running\n") == 0)) {
+ g_fSilentFatalError = TRUE;
+ }
+ }
+
+ /* Don't give warning if it's been silenced */
if (g_fSilentFatalError)
return;
- if (!g_fLogInited) {
- g_fLogInited = TRUE;
- g_pszLogFile = LogInit(g_pszLogFile, NULL);
- }
LogClose(EXIT_ERR_ABORT);
/* Format the error message */
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index 1382c8972..8a699f236 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -63,13 +63,12 @@ HICON g_hIconX = NULL;
HICON g_hSmallIconX = NULL;
#ifndef RELOCATE_PROJECTROOT
-const char *g_pszLogFile = DEFAULT_LOGDIR "/XWin.%s.log";
+const char *g_pszLogFileFormat = DEFAULT_LOGDIR "/XWin.%s.log";
#else
-const char *g_pszLogFile = "XWin.log";
-Bool g_fLogFileChanged = FALSE;
+const char *g_pszLogFileFormat = "XWin.%s.log";
#endif
+const char *g_pszLogFile = NULL;
int g_iLogVerbose = 2;
-Bool g_fLogInited = FALSE;
char *g_pszCommandLine = NULL;
Bool g_fSilentFatalError = FALSE;
DWORD g_dwCurrentThreadID = 0;
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index d7b813dbb..a20f266c2 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -40,13 +40,10 @@ extern int g_iNumScreens;
extern int g_iLastScreen;
extern char *g_pszCommandLine;
extern Bool g_fSilentFatalError;
+extern const char *g_pszLogFileFormat;
extern const char *g_pszLogFile;
-#ifdef RELOCATE_PROJECTROOT
-extern Bool g_fLogFileChanged;
-#endif
extern int g_iLogVerbose;
-extern Bool g_fLogInited;
extern Bool g_fAuthEnabled;
extern Bool g_fXdmcpEnabled;
diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c
index ab53af4ba..ec03f0c84 100644
--- a/hw/xwin/winkeybd.c
+++ b/hw/xwin/winkeybd.c
@@ -34,17 +34,24 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
-#include "winkeybd.h"
+#include "wmutil/scancodes.h"
+#include "wmutil/keyboard.h"
#include "winconfig.h"
#include "winmsg.h"
#include "xkbsrv.h"
+#include "dixgrabs.h"
/* C does not have a logical XOR operator, so we use a macro instead */
#define LOGICAL_XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
-static Bool g_winKeyState[NUM_KEYCODES];
+#define AltMask Mod1Mask
+#define NumLockMask Mod2Mask
+#define AltLangMask Mod3Mask
+#define KanaMask Mod4Mask
+#define ScrollLockMask Mod5Mask
/*
* Local prototypes
@@ -56,68 +63,6 @@ static void
static void
winKeybdCtrl(DeviceIntPtr pDevice, KeybdCtrl * pCtrl);
-/*
- * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
- * into an ASCII scan code.
- *
- * We do this ourselves, rather than letting Windows handle it,
- * because Windows tends to munge the handling of special keys,
- * like AltGr on European keyboards.
- */
-
-int
-winTranslateKey(WPARAM wParam, LPARAM lParam)
-{
- int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
- int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
- int iParam = HIWORD(lParam);
- int iParamScanCode = LOBYTE(iParam);
- int iScanCode;
-
- winDebug("winTranslateKey: wParam %08x lParam %08x\n", (int)wParam, (int)lParam);
-
-/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
- * scan code.
- *
- * Vocola 3 (Rick Mohr's supplement to WSR) uses
- * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
- * scan code of 1
- */
- if (iParamScanCode <= 1) {
- if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
- /* Trigger special case table to translate to extended
- * keycode, otherwise if num_lock is on, we can get keypad
- * numbers instead of navigation keys. */
- iParam |= KF_EXTENDED;
- else
- iParamScanCode = MapVirtualKeyEx(wParam,
- /*MAPVK_VK_TO_VSC */ 0,
- GetKeyboardLayout(0));
- }
-
- /* Branch on special extended, special non-extended, or normal key */
- if ((iParam & KF_EXTENDED) && iKeyFixupEx)
- iScanCode = iKeyFixupEx;
- else if (iKeyFixup)
- iScanCode = iKeyFixup;
- else if (wParam == 0 && iParamScanCode == 0x70)
- iScanCode = KEY_HKTG;
- else
- switch (iParamScanCode) {
- case 0x70:
- iScanCode = KEY_HKTG;
- break;
- case 0x73:
- iScanCode = KEY_BSlash2;
- break;
- default:
- iScanCode = iParamScanCode;
- break;
- }
-
- return iScanCode;
-}
-
/* Ring the keyboard bell (system speaker on PCs) */
static void
winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, void *pCtrl, int iClass)
@@ -337,209 +282,46 @@ winRestoreModeKeyStates(void)
*/
}
-/*
- * Look for the lovely fake Control_L press/release generated by Windows
- * when AltGr is pressed/released on a non-U.S. keyboard.
- */
-
-Bool
-winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
-{
- MSG msgNext;
- LONG lTime;
- Bool fReturn;
-
- static Bool lastWasControlL = FALSE;
- static LONG lastTime;
-
- /*
- * Fake Ctrl_L presses will be followed by an Alt_R press
- * with the same timestamp as the Ctrl_L press.
- */
- if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
- /* Got a Ctrl_L press */
-
- /* Get time of current message */
- lTime = GetMessageTime();
-
- /* Look for next press message */
- fReturn = PeekMessage(&msgNext, NULL,
- WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
-
- if (fReturn && msgNext.message != WM_KEYDOWN &&
- msgNext.message != WM_SYSKEYDOWN)
- fReturn = 0;
-
- if (!fReturn) {
- lastWasControlL = TRUE;
- lastTime = lTime;
- }
- else {
- lastWasControlL = FALSE;
- }
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
- /*
- * Next key press is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L press is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
- /*
- * Sometimes, the Alt_R press message is not yet posted when the
- * fake Ctrl_L press message arrives (even though it has the
- * same timestamp), so check for an Alt_R press message that has
- * arrived since the last Ctrl_L message.
- */
- else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
- /* Got a Alt_R press */
-
- if (lastWasControlL) {
- lTime = GetMessageTime();
-
- if (lastTime == lTime) {
- /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */
- winSendKeyEvent(KEY_LCtrl, FALSE);
- }
- lastWasControlL = FALSE;
- }
- }
- /*
- * Fake Ctrl_L releases will be followed by an Alt_R release
- * with the same timestamp as the Ctrl_L release.
- */
- else if ((message == WM_KEYUP || message == WM_SYSKEYUP)
- && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
- /* Got a Ctrl_L release */
-
- /* Get time of current message */
- lTime = GetMessageTime();
-
- /* Look for next release message */
- fReturn = PeekMessage(&msgNext, NULL,
- WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE);
-
- if (fReturn && msgNext.message != WM_KEYUP &&
- msgNext.message != WM_SYSKEYUP)
- fReturn = 0;
-
- lastWasControlL = FALSE;
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn
- && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP)
- && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
- /*
- * Next key release is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L release is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
- else {
- /* On any other press or release message, we don't have a
- potentially fake Ctrl_L to worry about anymore... */
- lastWasControlL = FALSE;
- }
-
- /* Not a fake control left press/release */
- return FALSE;
-}
-
-/*
- * Lift any modifier keys that are pressed
- */
-
void
-winKeybdReleaseKeys(void)
+winSendKeyEventCallback(DWORD dwKey, bool fDown)
{
- int i;
-
#ifdef HAS_DEVWINDOWS
/* Verify that the mi input system has been initialized */
if (g_fdMessageQueue == WIN_FD_INVALID)
return;
#endif
- /* Loop through all keys */
- for (i = 0; i < NUM_KEYCODES; ++i) {
- /* Pop key if pressed */
- if (g_winKeyState[i])
- winSendKeyEvent(i, FALSE);
-
- /* Reset pressed flag for keys */
- g_winKeyState[i] = FALSE;
- }
+ QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease,
+ dwKey);
}
/*
- * 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);
-
- winDebug("winSendKeyEvent: dwKey: %u, fDown: %u\n", (unsigned int)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/winlayouts.h b/hw/xwin/winlayouts.h
index a61fd7ac1..c7905e3c2 100644
--- a/hw/xwin/winlayouts.h
+++ b/hw/xwin/winlayouts.h
@@ -42,7 +42,8 @@ typedef struct {
*/
WinKBLayoutRec winKBLayouts[] = {
- {0x00000404, -1, "pc105", "zh_TW", NULL, NULL, "Chinese (Taiwan)"},
+ {0x00000404, -1, "pc105", "cn", NULL, NULL, "Chinese (Traditional)"},
+ {0x00000804, -1, "pc105", "cn", NULL, NULL, "Chinese (Simplified)"},
{0x00000405, -1, "pc105", "cz", NULL, NULL, "Czech"},
{0x00010405, -1, "pc105", "cz_qwerty", NULL, NULL, "Czech (QWERTY)"},
{0x00000406, -1, "pc105", "dk", NULL, NULL, "Danish"},
@@ -72,8 +73,8 @@ WinKBLayoutRec winKBLayouts[] = {
{0x0000040f, -1, "pc105", "is", NULL, NULL, "Icelandic"},
{0x00000410, -1, "pc105", "it", NULL, NULL, "Italian"},
{0x00010410, -1, "pc105", "it", NULL, NULL, "Italian (142)"},
- {0xa0000410, -1, "macbook79", "it", "mac", NULL, "Italiano (Apple)"},
{0x00000411, 7, "jp106", "jp", NULL, NULL, "Japanese"},
+ {0x00000412, -1, "kr106", "kr", NULL, NULL, "Korean"},
{0x00000413, -1, "pc105", "nl", NULL, NULL, "Dutch"},
{0x00000813, -1, "pc105", "be", NULL, NULL, "Dutch (Belgian)"},
{0x00000414, -1, "pc105", "no", NULL, NULL, "Norwegian"},
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index bbe21cba6..59705e655 100644
--- a/hw/xwin/winmouse.c
+++ b/hw/xwin/winmouse.c
@@ -41,6 +41,8 @@
#include "xserver-properties.h"
#include "inpututils.h"
+#include "wmutil/mouse.h"
+
/* Peek the internal button mapping */
static CARD8 const *g_winMouseButtonMap = NULL;
@@ -143,86 +145,20 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
return Success;
}
-/* Handle the mouse wheel */
-int
-winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown)
-{
- int button;
-
- /* Do we have any previous delta stored? */
- if ((*iTotalDeltaZ > 0 && iDeltaZ > 0)
- || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) {
- /* Previous delta and of same sign as current delta */
- iDeltaZ += *iTotalDeltaZ;
- *iTotalDeltaZ = 0;
- }
- else {
- /*
- * Previous delta of different sign, or zero.
- * We will set it to zero for either case,
- * as blindly setting takes just as much time
- * as checking, then setting if necessary :)
- */
- *iTotalDeltaZ = 0;
- }
-
- /*
- * Only process this message if the wheel has moved further than
- * WHEEL_DELTA
- */
- if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
- *iTotalDeltaZ = 0;
-
- /* Figure out how many whole deltas of the wheel we have */
- iDeltaZ /= WHEEL_DELTA;
- }
- else {
- /*
- * Wheel has not moved past WHEEL_DELTA threshold;
- * we will store the wheel delta until the threshold
- * has been reached.
- */
- *iTotalDeltaZ = iDeltaZ;
- return 0;
- }
-
- /* Set the button to indicate up or down wheel delta */
- if (iDeltaZ > 0) {
- button = iButtonUp;
- }
- else {
- button = iButtonDown;
- }
-
- /*
- * Flip iDeltaZ to positive, if negative,
- * because always need to generate a *positive* number of
- * button clicks for the Z axis.
- */
- if (iDeltaZ < 0) {
- iDeltaZ *= -1;
- }
-
- /* Generate X input messages for each wheel delta we have seen */
- while (iDeltaZ--) {
- /* Push the wheel button */
- winMouseButtonsSendEvent(ButtonPress, button);
-
- /* Release the wheel button */
- winMouseButtonsSendEvent(ButtonRelease, button);
- }
-
- return 0;
-}
-
/*
* Enqueue a mouse button event
*/
void
-winMouseButtonsSendEvent(int iEventType, int iButton)
+winMouseButtonsSendEvent(bool bPress, int iButton)
{
ValuatorMask mask;
+ int iEventType;
+
+ if (bPress)
+ iEventType = ButtonPress;
+ else
+ iEventType = ButtonRelease;
if (g_winMouseButtonMap)
iButton = g_winMouseButtonMap[iButton];
@@ -251,7 +187,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
/* Send button events right away if emulate 3 buttons is off */
if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF) {
/* Emulate 3 buttons is off, send the button event */
- winMouseButtonsSendEvent(iEventType, iButton);
+ winMouseButtonsSendEvent((iEventType == ButtonPress), iButton);
return 0;
}
@@ -288,7 +224,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send fake middle button */
- winMouseButtonsSendEvent(ButtonPress, Button2);
+ winMouseButtonsSendEvent(TRUE, Button2);
/* Indicate that a fake middle button event was sent */
pScreenPriv->fE3BFakeButton2Sent = TRUE;
@@ -303,8 +239,8 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send cached press, then send release */
- winMouseButtonsSendEvent(ButtonPress, iButton);
- winMouseButtonsSendEvent(ButtonRelease, iButton);
+ winMouseButtonsSendEvent(TRUE, iButton);
+ winMouseButtonsSendEvent(FALSE, iButton);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->fE3BFakeButton2Sent && !(wParam & MK_LBUTTON)
@@ -315,7 +251,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->fE3BFakeButton2Sent = FALSE;
/* Send middle mouse button release */
- winMouseButtonsSendEvent(ButtonRelease, Button2);
+ winMouseButtonsSendEvent(FALSE, Button2);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->iE3BCachedPress == 0
@@ -324,7 +260,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
* Button was release, no button is cached,
* and there is no fake button 2 release is pending.
*/
- winMouseButtonsSendEvent(ButtonRelease, iButton);
+ winMouseButtonsSendEvent(FALSE, iButton);
}
return 0;
diff --git a/hw/xwin/winmsg.c b/hw/xwin/winmsg.c
index 575bc47b2..1d3a387d8 100644
--- a/hw/xwin/winmsg.c
+++ b/hw/xwin/winmsg.c
@@ -38,17 +38,7 @@
#endif
#include <stdarg.h>
-void
-winVMsg(int, MessageType, int verb, const char *, va_list)
-_X_ATTRIBUTE_PRINTF(4, 0);
-
-void
-winVMsg(int scrnIndex, MessageType type, int verb, const char *format,
- va_list ap)
-{
- LogVMessageVerb(type, verb, format, ap);
-}
-
+#ifdef XWIN_XF86CONFIG
void
winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
{
@@ -60,16 +50,6 @@ winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
}
void
-winMsg(MessageType type, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- LogVMessageVerb(type, 1, format, ap);
- va_end(ap);
-}
-
-void
winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
...)
{
@@ -79,24 +59,25 @@ winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
LogVMessageVerb(type, verb, format, ap);
va_end(ap);
}
+#endif
void
-winMsgVerb(MessageType type, int verb, const char *format, ...)
+winErrorFVerb(int verb, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- LogVMessageVerb(type, verb, format, ap);
+ LogVMessageVerb(X_NONE, verb, format, ap);
va_end(ap);
}
void
-winErrorFVerb(int verb, const char *format, ...)
+winError(const char *format, ...)
{
va_list ap;
va_start(ap, format);
- LogVMessageVerb(X_NONE, verb, format, ap);
+ LogVMessageVerb(X_NONE, -1, format, ap);
va_end(ap);
}
diff --git a/hw/xwin/winmsg.h b/hw/xwin/winmsg.h
index 6c96c4070..25d887510 100644
--- a/hw/xwin/winmsg.h
+++ b/hw/xwin/winmsg.h
@@ -1,5 +1,3 @@
-#ifndef __WIN_MSG_H__
-#define __WIN_MSG_H__
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*
@@ -30,12 +28,17 @@
* Authors: Alexander Gottwald
*/
+#ifndef __WIN_MSG_H__
+#define __WIN_MSG_H__
+
#include <X11/Xwindows.h>
+#include <X11/Xfuncproto.h>
/*
* Function prototypes
*/
+#ifdef XWIN_XF86CONFIG
void
winDrvMsgVerb(int scrnIndex,
MessageType type, int verb, const char *format, ...)
@@ -43,12 +46,10 @@ _X_ATTRIBUTE_PRINTF(4, 5);
void
winDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
_X_ATTRIBUTE_PRINTF(3, 4);
-void
-winMsgVerb(MessageType type, int verb, const char *format, ...)
-_X_ATTRIBUTE_PRINTF(3, 4);
-void
-winMsg(MessageType type, const char *format, ...)
-_X_ATTRIBUTE_PRINTF(2, 3);
+#endif
+
+#define winMsg LogMessage
+
void
winDebug(const char *format, ...)
_X_ATTRIBUTE_PRINTF(1, 2);
@@ -59,6 +60,10 @@ _X_ATTRIBUTE_PRINTF(1, 2);
void
winErrorFVerb(int verb, const char *format, ...)
_X_ATTRIBUTE_PRINTF(2, 3);
+void
+winError(const char *format, ...)
+_X_ATTRIBUTE_PRINTF(1, 2);
+
void winW32Error(int verb, const char *message);
void winW32ErrorEx(int verb, const char *message, DWORD errorcode);
void winDebugWin32Message(const char *function, HWND hwnd, UINT message,
diff --git a/hw/xwin/winmultiwindowclass.h b/hw/xwin/winmultiwindowclass.h
index 3244f78e3..37ee9fb13 100644
--- a/hw/xwin/winmultiwindowclass.h
+++ b/hw/xwin/winmultiwindowclass.h
@@ -31,11 +31,24 @@
*/
/*
+ * The next block of definitions are for window manager properties that
+ * clients and applications use for communication.
+ */
+
+/*
* Structures
*/
+/*
+ * WM_HINTS structure
+ *
+ * NOTE: this structure represents the internal format stored in the property
+ * after it is marshalled by libX11, converting the flags field from an
+ * arch-dependent long to a 32-bit int.
+ */
+
typedef struct {
- long flags; /* marks which fields in this structure are defined */
+ int flags; /* marks which fields in this structure are defined */
Bool input; /* does this application rely on the window manager to
get keyboard input? */
int initial_state; /* see below */
@@ -59,11 +72,15 @@ typedef struct {
#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint|IconPositionHint|IconMaskHint|WindowGroupHint)
/*
- * new version containing base_width, base_height, and win_gravity fields;
+ * ICCCM 1.0 version containing base_width, base_height, and win_gravity fields;
* used with WM_NORMAL_HINTS.
+ *
+ * NOTE: this structure represents the internal format stored in the property
+ * after it is marshalled by libX11, converting the flags field from an
+ * arch-dependent long to a 32-bit int.
*/
typedef struct {
- long flags; /* marks which fields in this structure are defined */
+ int flags; /* marks which fields in this structure are defined */
int x, y; /* obsolete for new window mgrs, but clients */
int width, height; /* should set so old wm's don't mess up */
int min_width, min_height;
@@ -77,11 +94,6 @@ typedef struct {
int win_gravity; /* added by ICCCM version 1 */
} WinXSizeHints;
-/*
- * The next block of definitions are for window manager properties that
- * clients and applications use for communication.
- */
-
/* flags argument in size hints */
#define USPosition (1L << 0) /* user specified x, y */
#define USSize (1L << 1) /* user specified width, height */
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index cc4538709..02884cbe4 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -32,564 +32,68 @@
#include <xwin-config.h>
#endif
-#ifndef WINVER
-#define WINVER 0x0500
-#endif
-
#include <X11/Xwindows.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include "winresource.h"
#include "winprefs.h"
-#include "winmsg.h"
#include "winmultiwindowicons.h"
#include "winglobals.h"
+#include "wmutil/icon_convert.h"
+
/*
* global variables
*/
extern HINSTANCE g_hInstance;
/*
- * Scale an X icon ZPixmap into a Windoze icon bitmap
- */
-
-static void
-winScaleXImageToWindowsIcon(int iconSize,
- int effBPP,
- int stride, XImage * pixmap, unsigned char *image)
-{
- int row, column, effXBPP, effXDepth;
- unsigned char *outPtr;
- unsigned char *iconData = 0;
- int xStride;
- float factX, factY;
- int posX, posY;
- unsigned char *ptr;
- unsigned int zero;
- unsigned int color;
-
- effXBPP = pixmap->bits_per_pixel;
- if (pixmap->bits_per_pixel == 15)
- effXBPP = 16;
-
- effXDepth = pixmap->depth;
- if (pixmap->depth == 15)
- effXDepth = 16;
-
- xStride = pixmap->bytes_per_line;
- if (stride == 0 || xStride == 0) {
- ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. "
- "Bailing.\n");
- return;
- }
-
- /* Get icon data */
- iconData = (unsigned char *) pixmap->data;
-
- /* Keep aspect ratio */
- factX = ((float) pixmap->width) / ((float) iconSize);
- factY = ((float) pixmap->height) / ((float) iconSize);
- if (factX > factY)
- factY = factX;
- else
- factX = factY;
-
- /* Out-of-bounds, fill icon with zero */
- zero = 0;
-
- for (row = 0; row < iconSize; row++) {
- outPtr = image + stride * row;
- for (column = 0; column < iconSize; column++) {
- posX = factX * column;
- posY = factY * row;
-
- ptr = (unsigned char *) iconData + posY * xStride;
- if (effXBPP == 1) {
- ptr += posX / 8;
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
-
- if ((*ptr) & (1 << (posX & 7)))
- switch (effBPP) {
- case 32:
- *(outPtr++) = 0;
- case 24:
- *(outPtr++) = 0;
- case 16:
- *(outPtr++) = 0;
- case 8:
- *(outPtr++) = 0;
- break;
- case 1:
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- }
- else
- switch (effBPP) {
- case 32:
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 0;
- break;
- case 24:
- *(outPtr++) = 255;
- case 16:
- *(outPtr++) = 255;
- case 8:
- *(outPtr++) = 255;
- break;
- case 1:
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- break;
- }
- }
- else if (effXDepth == 24 || effXDepth == 32) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = (((*ptr) << 16)
- + ((*(ptr + 1)) << 8)
- + ((*(ptr + 2)) << 0));
- switch (effBPP) {
- case 32:
- *(outPtr++) = *(ptr++); /* b */
- *(outPtr++) = *(ptr++); /* g */
- *(outPtr++) = *(ptr++); /* r */
- *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
- break;
- case 24:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 16:
- color = ((((*ptr) >> 2) << 10)
- + (((*(ptr + 1)) >> 2) << 5)
- + (((*(ptr + 2)) >> 2)));
- *(outPtr++) = (color >> 8);
- *(outPtr++) = (color & 255);
- break;
- case 8:
- color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
- color /= 3;
- *(outPtr++) = color;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- }
- }
- else if (effXDepth == 16) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = ((*ptr) << 8) + (*(ptr + 1));
- switch (effBPP) {
- case 32:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- *(outPtr++) = 0; /* resvd */
- break;
- case 24:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- break;
- case 16:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 8:
- *(outPtr++) = (((color & 31)
- + ((color >> 5) & 31)
- + ((color >> 10) & 31)) / 3) << 2;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- } /* end switch(effbpp) */
- } /* end if effxbpp==16) */
- } /* end for column */
- } /* end for row */
-}
-
-static HICON
-NetWMToWinIconAlpha(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- HICON result;
- HDC hdc = GetDC(NULL);
- uint32_t *DIB_pixels;
- ICONINFO ii;
- BITMAPV4HEADER bmh = { sizeof(bmh) };
-
- /* Define an ARGB pixel format used for Color+Alpha icons */
- bmh.bV4Width = width;
- bmh.bV4Height = -height; /* Invert the image */
- bmh.bV4Planes = 1;
- bmh.bV4BitCount = 32;
- bmh.bV4V4Compression = BI_BITFIELDS;
- bmh.bV4AlphaMask = 0xFF000000;
- bmh.bV4RedMask = 0x00FF0000;
- bmh.bV4GreenMask = 0x0000FF00;
- bmh.bV4BlueMask = 0x000000FF;
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh,
- DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
- 0);
- ReleaseDC(NULL, hdc);
-
- if (!ii.hbmColor)
- return NULL;
-
- ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
- memcpy(DIB_pixels, pixels, height * width * 4);
-
- /* CreateIconIndirect() traditionally required DDBitmaps */
- /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
- /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
- return result;
-}
-
-static HICON
-NetWMToWinIconThreshold(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- int row, col;
- HICON result;
- ICONINFO ii;
-
- HDC hdc = GetDC(NULL);
- HDC xorDC = CreateCompatibleDC(hdc);
- HDC andDC = CreateCompatibleDC(hdc);
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
- ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
- ReleaseDC(NULL, hdc);
- SelectObject(xorDC, ii.hbmColor);
- SelectObject(andDC, ii.hbmMask);
-
- for (row = 0; row < height; row++) {
- for (col = 0; col < width; col++) {
- if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
- SetPixelV(xorDC, col, row,
- RGB(((char *) pixels)[2], ((char *) pixels)[1],
- ((char *) pixels)[0]));
- SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
- }
- else {
- SetPixelV(xorDC, col, row, RGB(0, 0, 0));
- SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
- }
- pixels++;
- }
- }
- DeleteDC(xorDC);
- DeleteDC(andDC);
-
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
- result);
- return result;
-}
-
-static HICON
-NetWMToWinIcon(int bpp, uint32_t * icon)
-{
- static Bool hasIconAlphaChannel = FALSE;
- static BOOL versionChecked = FALSE;
-
- if (!versionChecked) {
- OSVERSIONINFOEX osvi = { 0 };
- ULONGLONG dwlConditionMask = 0;
-
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- osvi.dwMajorVersion = 5;
- osvi.dwMinorVersion = 1;
-
- /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
- VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
- VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
- VER_GREATER_EQUAL);
- hasIconAlphaChannel =
- VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
- dwlConditionMask);
- versionChecked = TRUE;
-
- ErrorF("OS has icon alpha channel support: %s\n",
- hasIconAlphaChannel ? "yes" : "no");
- }
-
- if (hasIconAlphaChannel && (bpp == 32))
- return NetWMToWinIconAlpha(icon);
- else
- return NetWMToWinIconThreshold(icon);
-}
-
-/*
- * Attempt to create a custom icon from the WM_HINTS bitmaps
- */
-
-static
- HICON
-winXIconToHICON(Display * pDisplay, Window id, int iconSize)
-{
- unsigned char *mask, *image = NULL, *imageMask;
- unsigned char *dst, *src;
- int planes, bpp, i;
- unsigned int biggest_size = 0;
- HDC hDC;
- ICONINFO ii;
- XWMHints *hints;
- HICON hIcon = NULL;
- uint32_t *biggest_icon = NULL;
- static Atom _XA_NET_WM_ICON;
- static int generation;
- uint32_t *icon, *icon_data = NULL;
- unsigned long int size;
- Atom type;
- int format;
- unsigned long int left;
-
- hDC = GetDC(GetDesktopWindow());
- planes = GetDeviceCaps(hDC, PLANES);
- bpp = GetDeviceCaps(hDC, BITSPIXEL);
- ReleaseDC(GetDesktopWindow(), hDC);
-
- /* Always prefer _NET_WM_ICON icons */
- if (generation != serverGeneration) {
- generation = serverGeneration;
- _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE);
- }
-
- if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON,
- 0, MAXINT, FALSE,
- AnyPropertyType, &type, &format, &size, &left,
- (unsigned char **) &icon_data) == Success) &&
- (icon_data != NULL)) {
- for (icon = icon_data; icon < &icon_data[size] && *icon;
- icon = &icon[icon[0] * icon[1] + 2]) {
- winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
-
- /* Icon data size will overflow an int and thus is bigger than the
- property can possibly be */
- if ((INT_MAX/icon[0]) < icon[1]) {
- winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
- break;
- }
-
- /* Icon data size is bigger than amount of data remaining */
- if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
- winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
- break;
- }
-
- /* Found an exact match to the size we require... */
- if (icon[0] == iconSize && icon[1] == iconSize) {
- winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
- iconSize, iconSize);
- hIcon = NetWMToWinIcon(bpp, icon);
- break;
- }
- /* Otherwise, find the biggest icon and let Windows scale the size */
- else if (biggest_size < icon[0]) {
- biggest_icon = icon;
- biggest_size = icon[0];
- }
- }
-
- if (!hIcon && biggest_icon) {
- winDebug
- ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
- biggest_icon[0], biggest_icon[1], iconSize, iconSize);
-
- hIcon = NetWMToWinIcon(bpp, biggest_icon);
- }
-
- XFree(icon_data);
- }
-
- if (!hIcon) {
- winDebug("winXIconToHICON: no suitable NetIcon\n");
-
- hints = XGetWMHints(pDisplay, id);
- if (hints) {
- winDebug("winXIconToHICON: id 0x%x icon_pixmap hint 0x%x\n",
- (unsigned int)id,
- (unsigned int)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%p\n",
- (unsigned int)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
*/
#ifdef XWIN_MULTIWINDOW
void
-winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew)
+winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew)
{
HICON hIcon, hIconSmall = NULL, hIconOld;
- /* Start with the icon from preferences, if any */
- hIcon = hIconNew;
- hIconSmall = hIconNew;
-
- /* If we still need an icon, try and get the icon from WM_HINTS */
- if (!hIcon)
- hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON));
- if (!hIconSmall)
- hIconSmall =
- winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON));
+ if (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 */
+ 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) {
+ hIcon = hIconSmall;
+ hIconSmall = NULL;
+ }
+ }
- /* If we got the small, but not the large one swap them */
- if (!hIcon && hIconSmall) {
- hIcon = hIconSmall;
- hIconSmall = NULL;
+ /* If we still need an icon, use the default one */
+ if (!hIcon) {
+ hIcon = g_hIconX;
+ hIconSmall = g_hSmallIconX;
}
- /* Set the large icon */
- hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
- /* Delete the old icon if its not the default */
- winDestroyIcon(hIconOld);
+ if (hIcon) {
+ /* Set the large icon */
+ hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+ /* Delete the old icon if its not the default */
+ winDestroyIcon(hIconOld);
+ }
- /* Same for the small icon */
- hIconOld =
- (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
- winDestroyIcon(hIconOld);
+ if (hIconSmall) {
+ /* Same for the small icon */
+ hIconOld =
+ (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
+ winDestroyIcon(hIconOld);
+ }
}
void
diff --git a/hw/xwin/winmultiwindowicons.h b/hw/xwin/winmultiwindowicons.h
index bf7f6eda7..87ba8d1cf 100644
--- a/hw/xwin/winmultiwindowicons.h
+++ b/hw/xwin/winmultiwindowicons.h
@@ -27,8 +27,10 @@
#ifndef WINMULTIWINDOWICONS_H
#define WINMULTIWINDOWICONS_H
+#include <xcb/xcb.h>
+
void
- winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
+ winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew);
void
winInitGlobalIcons(void);
diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c
index f4de91242..28828af8a 100644
--- a/hw/xwin/winmultiwindowwindow.c
+++ b/hw/xwin/winmultiwindowwindow.c
@@ -35,9 +35,11 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "dixevents.h"
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
/*
* Prototypes for local functions
@@ -55,11 +57,27 @@ static void
static void
winFindWindow(void *value, XID id, void *cdata);
+static Bool
+isToplevelWindow(WindowPtr pWin)
+{
+ assert(pWin->parent); /* root window isn't expected here */
+
+ /* If the immediate parent is the root window, this is a top-level window */
+ if ((pWin->parent) && (pWin->parent->parent == NULL)) {
+ assert(pWin->parent == pWin->drawable.pScreen->root);
+ return TRUE;
+ }
+
+ /* otherwise, a child window */
+ return FALSE;
+}
+
static
void
winInitMultiWindowClass(void)
{
static wATOM atomXWinClass = 0;
+ static wATOM atomXWinChildClass = 0;
WNDCLASSEX wcx;
if (atomXWinClass == 0) {
@@ -83,11 +101,40 @@ winInitMultiWindowClass(void)
wcx.hIconSm = hIconSmall;
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
+ ErrorF("winInitMultiWindowClass - Creating class: %s\n",
+ WINDOW_CLASS_X);
#endif
atomXWinClass = RegisterClassEx(&wcx);
}
+
+ if (atomXWinChildClass == 0) {
+ HICON hIcon, hIconSmall;
+
+ /* Load the default icons */
+ winSelectIcons(&hIcon, &hIconSmall);
+
+ /* Setup our window class */
+ wcx.cbSize = sizeof(WNDCLASSEX);
+ wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
+ wcx.lpfnWndProc = winChildWindowProc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = g_hInstance;
+ wcx.hIcon = hIcon;
+ wcx.hCursor = 0;
+ wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = WINDOW_CLASS_X_CHILD;
+ wcx.hIconSm = hIconSmall;
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF("winInitMultiWindowClass - Creating class: %s\n",
+ WINDOW_CLASS_X_CHILD);
+#endif
+
+ atomXWinChildClass = RegisterClassEx(&wcx);
+ }
}
/*
@@ -202,6 +249,29 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y)
return fResult;
}
+ if (!isToplevelWindow(pWin)) {
+ POINT parentOrigin;
+
+ /* Get the X and Y location of the X window */
+ iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ /* Get the height and width of the X window */
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Convert screen coordinates into client area co-ordinates of the parent */
+ parentOrigin.x = 0;
+ parentOrigin.y = 0;
+ ClientToScreen(GetParent(hWnd), &parentOrigin);
+
+ MoveWindow(hWnd,
+ iX - parentOrigin.x, iY - parentOrigin.y, iWidth, iHeight,
+ TRUE);
+
+ return fResult;
+ }
+
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
@@ -471,12 +541,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;
@@ -485,7 +551,6 @@ winCreateWindowsWindow(WindowPtr pWin)
HWND hFore = NULL;
winWindowPriv(pWin);
- winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
WinXSizeHints hints;
Window daddyId;
DWORD dwStyle, dwExStyle;
@@ -503,39 +568,63 @@ winCreateWindowsWindow(WindowPtr pWin)
iHeight = pWin->drawable.height;
/* If it's an InputOutput window, and so is going to end up being made visible,
- make sure the window actually ends up somewhere where it will be visible */
- if (pWin->drawable.class != InputOnly) {
- if ((iX < GetSystemMetrics(SM_XVIRTUALSCREEN)) ||
- (iX > GetSystemMetrics(SM_CXVIRTUALSCREEN)))
- iX = CW_USEDEFAULT;
+ make sure the window actually ends up somewhere where it will be visible
- if ((iY < GetSystemMetrics(SM_YVIRTUALSCREEN)) ||
- (iY > GetSystemMetrics(SM_CYVIRTUALSCREEN)))
- iY = CW_USEDEFAULT;
+ To handle arrangements of monitors which form a non-rectangular virtual
+ desktop, check if the window will end up with it's top-left corner on any
+ monitor
+ */
+ if (pWin->drawable.class != InputOnly) {
+ POINT pt = { iX, iY };
+ if (MonitorFromPoint(pt, MONITOR_DEFAULTTONULL) == NULL)
+ {
+ iX = CW_USEDEFAULT;
+ iY = CW_USEDEFAULT;
+ }
}
- winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX,
- iY);
+ winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth,
+ iHeight, iX, iY);
if (winMultiWindowGetTransientFor(pWin, &daddyId)) {
if (daddyId) {
- hFore = GetForegroundWindow();
- if (hFore && (daddyId != (Window) (INT_PTR) GetProp(hFore, WIN_WID_PROP)))
- hFore = NULL;
+ WindowPtr pParent;
+ int res = dixLookupWindow(&pParent, daddyId, serverClient, DixReadAccess);
+ if (res == Success)
+ {
+ winPrivWinPtr pParentPriv = winGetWindowPriv(pParent);
+ hFore = pParentPriv->hWnd;
+ }
}
}
else {
- /* Default positions if none specified */
- if (!winMultiWindowGetWMNormalHints(pWin, &hints))
- hints.flags = 0;
- if (!(hints.flags & (USPosition | PPosition)) &&
- !pWin->overrideRedirect) {
- iX = CW_USEDEFAULT;
- iY = CW_USEDEFAULT;
+ if (!pWin->overrideRedirect) {
+ /* Default positions if none specified */
+ if (!winMultiWindowGetWMNormalHints(pWin, &hints))
+ hints.flags = 0;
+
+ if ((hints.flags & USPosition) ||
+ ((hints.flags & PPosition) &&
+ ((pWin->drawable.x - pWin->borderWidth != 0) ||
+ (pWin->drawable.y - pWin->borderWidth != 0)))) {
+ /*
+ Always respect user specified position, respect program
+ specified position if it's not the origin
+ */
+ }
+ else {
+ /* Use default position */
+ iX = CW_USEDEFAULT;
+ iY = CW_USEDEFAULT;
+ }
}
}
- /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */
+ winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth,
+ iHeight, iX, iY);
+
+ /* Create the window */
+ /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */
/* CW_USEDEFAULT, change back to popup after creation */
dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
dwExStyle = WS_EX_TOOLWINDOW;
@@ -573,11 +662,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%p\n", hWnd);
+
/* Change style back to popup, already placed... */
SetWindowLongPtr(hWnd, GWL_STYLE,
WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
@@ -598,9 +690,107 @@ winCreateWindowsWindow(WindowPtr pWin)
/* Flag that this Windows window handles its own activation */
SetProp(hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0);
+}
+
+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:%p 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:%p XID:0x%08x hWnd:0x%p\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%p\n", hWnd);
+ pWinPriv->hWnd = hWnd;
+
+ SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin));
+}
+
+/*
+ * winCreateWindowsWindow - Create a Windows window associated with an X window
+ */
+
+void
+winCreateWindowsWindow(WindowPtr pWin)
+{
+ winDebug("winCreateWindowsWindow - pWin:%p XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ if (isToplevelWindow(pWin)) {
+ winCreateWindowsTopLevelWindow(pWin);
+ }
+ else {
+ winCreateWindowsChildWindow(pWin);
+ }
+}
+
+static int
+winDestroyChildWindowsWindow(WindowPtr pWin, void *data)
+{
+ winWindowPriv(pWin);
+
+ winDebug("winDestroyChildWindowsWindow - pWin:%p XID:0x%x \n", pWin,
+ pWin->drawable.id);
+
+ /* Null our handle to the Window so referencing it will cause an error */
+ pWinPriv->hWnd = NULL;
- /* Call engine-specific create window procedure */
- (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin);
+#ifdef XWIN_GLX_WINDOWS
+ /* No longer note WGL used on this window */
+ pWinPriv->fWglUsed = FALSE;
+#endif
+
+ return WT_WALKCHILDREN; /* continue enumeration */
}
Bool winInDestroyWindowsWindow = FALSE;
@@ -618,6 +808,7 @@ winDestroyWindowsWindow(WindowPtr pWin)
BOOL oldstate = winInDestroyWindowsWindow;
HICON hIcon;
HICON hIconSm;
+ HWND hWnd;
winDebug("winDestroyWindowsWindow - pWin:%p XID:0x%x \n", pWin,
(unsigned int)pWin->drawable.id);
@@ -632,21 +823,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)) {
@@ -668,29 +858,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);
}
@@ -794,56 +1013,6 @@ winReorderWindowsMultiWindow(void)
}
/*
- * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE
- */
-
-void
-winMinimizeWindow(Window id)
-{
- WindowPtr pWin;
- winPrivWinPtr pWinPriv;
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- win32RootlessWindowPtr pRLWinPriv;
-#endif
- HWND hWnd;
- ScreenPtr pScreen = NULL;
- winPrivScreenPtr pScreenPriv = NULL;
-
-#if CYGWINDOWING_DEBUG
- ErrorF("winMinimizeWindow\n");
-#endif
-
- dixLookupResourceByType((void *) &pWin, id, RT_WINDOW, NullClient,
- DixUnknownAccess);
- if (!pWin) {
- ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__);
- return;
- }
-
- pScreen = pWin->drawable.pScreen;
- if (pScreen)
- pScreenPriv = winGetScreenPriv(pScreen);
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- if (pScreenPriv && pScreenPriv->pScreenInfo->fInternalWM) {
- pRLWinPriv =
- (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE);
- hWnd = pRLWinPriv->hWnd;
- }
- else
-#else
- if (pScreenPriv)
-#endif
- {
- pWinPriv = winGetWindowPriv(pWin);
- hWnd = pWinPriv->hWnd;
- }
-
- ShowWindow(hWnd, SW_MINIMIZE);
-}
-
-/*
* CopyWindow - See Porting Layer Definition - p. 39
*/
void
@@ -927,6 +1096,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 1efe96a15..ac5a58309 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -30,10 +30,24 @@
* Colin Harrison
*/
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
/* X headers */
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -45,31 +59,26 @@
#define HANDLE void *
#include <pthread.h>
#undef HANDLE
-#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>
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/composite.h>
+
#include <X11/Xwindows.h>
/* Local headers */
+#include "X11/Xdefs.h" // for Bool type
#include "winwindow.h"
#include "winprefs.h"
#include "window.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
#include "winglobals.h"
#include "windisplay.h"
+#include "winmultiwindowicons.h"
-#ifdef XWIN_MULTIWINDOWEXTWM
-#include <X11/extensions/windowswmstr.h>
-#else
/* We need the native HWND atom for intWM, so for consistency use the
- same name as extWM would if we were building with enabled... */
+ same name as extWM does */
#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
-#endif
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
@@ -78,6 +87,8 @@
extern void winDebug(const char *format, ...);
extern void winReshapeMultiWindow(WindowPtr pWin);
extern void winUpdateRgnMultiWindow(WindowPtr pWin);
+extern xcb_auth_info_t *winGetXcbAuthInfo(void);
+extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
#ifndef CYGDEBUG
#define CYGDEBUG NO
@@ -92,8 +103,6 @@ extern void winUpdateRgnMultiWindow(WindowPtr pWin);
#ifdef HAS_DEVWINDOWS
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
#endif
-#define WIN_JMP_OKAY 0
-#define WIN_JMP_ERROR_IO 2
/*
* Local structures
@@ -113,13 +122,20 @@ typedef struct _WMMsgQueueRec {
} WMMsgQueueRec, *WMMsgQueuePtr;
typedef struct _WMInfo {
- Display *pDisplay;
+ xcb_connection_t *conn;
WMMsgQueueRec wmMsgQueue;
- Atom atmWmProtos;
- Atom atmWmDelete;
- Atom atmWmTakeFocus;
- Atom atmPrivMap;
- Bool fAllowOtherWM;
+ xcb_atom_t atmWmProtos;
+ xcb_atom_t atmWmDelete;
+ xcb_atom_t atmWmTakeFocus;
+ xcb_atom_t atmPrivMap;
+ xcb_atom_t atmUtf8String;
+ xcb_atom_t atmNetWmName;
+ xcb_atom_t atmCurrentDesktop;
+ xcb_atom_t atmNumberDesktops;
+ xcb_atom_t atmDesktopNames;
+ xcb_atom_t atmWmState;
+ xcb_ewmh_connection_t ewmh;
+ Bool fCompositeWM;
} WMInfoRec, *WMInfoPtr;
typedef struct _WMProcArgRec {
@@ -129,7 +145,7 @@ typedef struct _WMProcArgRec {
} WMProcArgRec, *WMProcArgPtr;
typedef struct _XMsgProcArgRec {
- Display *pDisplay;
+ xcb_connection_t *conn;
DWORD dwScreen;
WMInfoPtr pWMInfo;
pthread_mutex_t *ppmServerStarted;
@@ -149,65 +165,101 @@ static Bool
InitQueue(WMMsgQueuePtr pQueue);
static void
- GetWindowName(Display * pDpy, Window iWin, char **ppWindowName);
+ GetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName);
-static int
- SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData);
+static void
+ SendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData);
static void
- UpdateName(WMInfoPtr pWMInfo, Window iWindow);
+ UpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow);
static void *winMultiWindowWMProc(void *pArg);
-static int
- winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr);
-
-static int
- winMultiWindowWMIOErrorHandler(Display * pDisplay);
-
static void *winMultiWindowXMsgProc(void *pArg);
-static int
- winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr);
-
-static int
- winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay);
-
-static int
- winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr);
+static void
+winMultiWindowThreadExit(void *arg);
static void
winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
#if 0
static void
- PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction);
+ PreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction);
#endif
static Bool
-
-CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
- Bool fAllowOtherWM);
+CheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen);
static void
- winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle);
+ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, Bool onCreate);
-void
- winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
+static void
+ winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd);
/*
* Local globals
*/
-static jmp_buf g_jmpWMEntry;
-static XIOErrorHandler g_winMultiWindowWMOldIOErrorHandler;
-static pthread_t g_winMultiWindowWMThread;
-static jmp_buf g_jmpXMsgProcEntry;
-static XIOErrorHandler g_winMultiWindowXMsgProcOldIOErrorHandler;
-static pthread_t g_winMultiWindowXMsgProcThread;
static Bool g_shutdown = FALSE;
-static Bool redirectError = FALSE;
-static Bool g_fAnotherWMRunning = FALSE;
+
+/*
+ * Translate msg id to text, for debug purposes
+ */
+
+static const char *
+MessageName(winWMMessagePtr msg)
+{
+ switch (msg->msg)
+ {
+ case WM_WM_MOVE:
+ return "WM_WM_MOVE";
+ break;
+ case WM_WM_SIZE:
+ return "WM_WM_SIZE";
+ break;
+ case WM_WM_RAISE:
+ return "WM_WM_RAISE";
+ break;
+ case WM_WM_LOWER:
+ return "WM_WM_LOWER";
+ break;
+ case WM_WM_UNMAP:
+ return "WM_WM_UNMAP";
+ break;
+ case WM_WM_KILL:
+ return "WM_WM_KILL";
+ break;
+ case WM_WM_ACTIVATE:
+ return "WM_WM_ACTIVATE";
+ break;
+ case WM_WM_NAME_EVENT:
+ return "WM_WM_NAME_EVENT";
+ break;
+ case WM_WM_ICON_EVENT:
+ return "WM_WM_ICON_EVENT";
+ break;
+ case WM_WM_CHANGE_STATE:
+ return "WM_WM_CHANGE_STATE";
+ break;
+ case WM_WM_MAP:
+ return "WM_WM_MAP";
+ break;
+ case WM_WM_MAP_UNMANAGED:
+ return "WM_WM_MAP_UNMANAGED";
+ break;
+ case WM_WM_MAP_MANAGED:
+ return "WM_WM_MAP_MANAGED";
+ break;
+ case WM_WM_HINTS_EVENT:
+ return "WM_WM_HINTS_EVENT";
+ break;
+ default:
+ return "Unknown Message";
+ break;
+ }
+}
+
/*
* PushMessage - Push a message onto the queue
@@ -231,44 +283,6 @@ PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
pQueue->pHead = pNode;
}
-#if 0
- switch (pNode->msg.msg) {
- case WM_WM_MOVE:
- ErrorF("\tWM_WM_MOVE\n");
- break;
- case WM_WM_SIZE:
- ErrorF("\tWM_WM_SIZE\n");
- break;
- case WM_WM_RAISE:
- ErrorF("\tWM_WM_RAISE\n");
- break;
- case WM_WM_LOWER:
- ErrorF("\tWM_WM_LOWER\n");
- break;
- case WM_WM_MAP:
- ErrorF("\tWM_WM_MAP\n");
- break;
- case WM_WM_MAP2:
- ErrorF("\tWM_WM_MAP2\n");
- break;
- case WM_WM_MAP3:
- ErrorF("\tWM_WM_MAP3\n");
- break;
- case WM_WM_UNMAP:
- ErrorF("\tWM_WM_UNMAP\n");
- break;
- case WM_WM_KILL:
- ErrorF("\tWM_WM_KILL\n");
- break;
- case WM_WM_ACTIVATE:
- ErrorF("\tWM_WM_ACTIVATE\n");
- break;
- default:
- ErrorF("\tUnknown Message.\n");
- break;
- }
-#endif
-
/* Increase the count of elements in the queue by one */
++(pQueue->nQueueSize);
@@ -343,7 +357,7 @@ PopMessage(WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo)
*/
static Bool
-HaveMessage(WMMsgQueuePtr pQueue, UINT msg, Window iWindow)
+HaveMessage(WMMsgQueuePtr pQueue, UINT msg, xcb_window_t iWindow)
{
WMMsgNodePtr pNode;
@@ -399,29 +413,20 @@ InitQueue(WMMsgQueuePtr pQueue)
static
char *
-Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
+Xutf8TextPropertyToString(WMInfoPtr pWMInfo, xcb_icccm_get_text_property_reply_t *xtp)
{
- int nNum;
- char **ppList;
char *pszReturnData;
- if (Xutf8TextPropertyToTextList(pDisplay, xtp, &ppList, &nNum) >= Success &&
- nNum > 0 && *ppList) {
- int i;
- int iLen = 0;
-
- for (i = 0; i < nNum; i++)
- iLen += strlen(ppList[i]);
- pszReturnData = malloc(iLen + 1);
- pszReturnData[0] = '\0';
- for (i = 0; i < nNum; i++)
- strcat(pszReturnData, ppList[i]);
- if (ppList)
- XFreeStringList(ppList);
+ if ((xtp->encoding == XCB_ATOM_STRING) || // Latin1 ISO 8859-1
+ (xtp->encoding == pWMInfo->atmUtf8String)) { // UTF-8 ISO 10646
+ pszReturnData = strndup(xtp->name, xtp->name_len);
}
else {
- pszReturnData = malloc(1);
- pszReturnData[0] = '\0';
+ // Converting from COMPOUND_TEXT to UTF-8 properly is complex to
+ // implement, and not very much use unless you have an old
+ // application which isn't UTF-8 aware.
+ ErrorF("Xutf8TextPropertyToString: text encoding %d is not implemented\n", xtp->encoding);
+ pszReturnData = strdup("");
}
return pszReturnData;
@@ -432,51 +437,81 @@ Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
*/
static void
-GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
+GetWindowName(WMInfoPtr pWMInfo, xcb_window_t iWin, char **ppWindowName)
{
- int nResult;
- XTextProperty xtpWindowName;
- XTextProperty xtpClientMachine;
- char *pszWindowName;
- char *pszClientMachine;
- char hostname[HOST_NAME_MAX + 1];
+ xcb_connection_t *conn = pWMInfo->conn;
+ char *pszWindowName = NULL;
#if CYGMULTIWINDOW_DEBUG
ErrorF("GetWindowName\n");
#endif
- /* Intialize ppWindowName to NULL */
- *ppWindowName = NULL;
-
- /* Try to get window name */
- nResult = XGetWMName(pDisplay, iWin, &xtpWindowName);
- if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) {
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("GetWindowName - XGetWMName failed. No name.\n");
-#endif
- return;
+ /* Try to get window name from _NET_WM_NAME */
+ {
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *reply;
+
+ cookie = xcb_get_property(pWMInfo->conn, FALSE, iWin,
+ pWMInfo->atmNetWmName,
+ XCB_GET_PROPERTY_TYPE_ANY, 0, INT_MAX);
+ reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
+ if (reply && (reply->type != XCB_NONE)) {
+ pszWindowName = strndup(xcb_get_property_value(reply),
+ xcb_get_property_value_length(reply));
+ free(reply);
+ }
}
- pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName);
- XFree(xtpWindowName.value);
+ /* Otherwise, try to get window name from WM_NAME */
+ if (!pszWindowName)
+ {
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_get_text_property_reply_t reply;
+
+ cookie = xcb_icccm_get_wm_name(conn, iWin);
+ if (!xcb_icccm_get_wm_name_reply(conn, cookie, &reply, NULL)) {
+ ErrorF("GetWindowName - xcb_icccm_get_wm_name_reply failed. No name.\n");
+ *ppWindowName = NULL;
+ return;
+ }
+
+ pszWindowName = Xutf8TextPropertyToString(pWMInfo, &reply);
+ xcb_icccm_get_text_property_reply_wipe(&reply);
+ }
+
+ /* return the window name, unless... */
+ *ppWindowName = pszWindowName;
if (g_fHostInTitle) {
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_get_text_property_reply_t reply;
+
/* Try to get client machine name */
- nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine);
- if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) {
- pszClientMachine =
- Xutf8TextPropertyToString(pDisplay, &xtpClientMachine);
- XFree(xtpClientMachine.value);
+ cookie = xcb_icccm_get_wm_client_machine(conn, iWin);
+ if (xcb_icccm_get_wm_client_machine_reply(conn, cookie, &reply, NULL)) {
+ char *pszClientMachine;
+ char *pszClientHostname;
+ char *dot;
+ char hostname[HOST_NAME_MAX + 1];
+
+ pszClientMachine = Xutf8TextPropertyToString(pWMInfo, &reply);
+ xcb_icccm_get_text_property_reply_wipe(&reply);
+
+ /* If client machine name looks like a FQDN, find the hostname */
+ pszClientHostname = strdup(pszClientMachine);
+ dot = strchr(pszClientHostname, '.');
+ if (dot)
+ *dot = '\0';
/*
- If we have a client machine name
- and it's not the local host name
+ If we have a client machine hostname
+ and it's not the local hostname
and it's not already in the window title...
*/
- if (strlen(pszClientMachine) &&
+ if (strlen(pszClientHostname) &&
!gethostname(hostname, HOST_NAME_MAX + 1) &&
- strcmp(hostname, pszClientMachine) &&
- (strstr(pszWindowName, pszClientMachine) == 0)) {
+ strcmp(hostname, pszClientHostname) &&
+ (strstr(pszWindowName, pszClientHostname) == 0)) {
/* ... add '@<clientmachine>' to end of window name */
*ppWindowName =
malloc(strlen(pszWindowName) +
@@ -486,15 +521,12 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
strcat(*ppWindowName, pszClientMachine);
free(pszWindowName);
- free(pszClientMachine);
-
- return;
}
+
+ free(pszClientMachine);
+ free(pszClientHostname);
}
}
-
- /* otherwise just return the window name */
- *ppWindowName = pszWindowName;
}
/*
@@ -502,17 +534,21 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
*/
static Bool
-IsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol)
+IsWmProtocolAvailable(WMInfoPtr pWMInfo, xcb_window_t iWindow, xcb_atom_t atmProtocol)
{
- int i, n, found = 0;
- Atom *protocols;
-
- if (XGetWMProtocols(pDisplay, iWindow, &protocols, &n)) {
- for (i = 0; i < n; ++i)
- if (protocols[i] == atmProtocol)
- ++found;
-
- XFree(protocols);
+ int i, found = 0;
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_get_wm_protocols_reply_t reply;
+ xcb_connection_t *conn = pWMInfo->conn;
+
+ cookie = xcb_icccm_get_wm_protocols(conn, iWindow, pWMInfo->ewmh.WM_PROTOCOLS);
+ if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &reply, NULL)) {
+ for (i = 0; i < reply.atoms_len; ++i)
+ if (reply.atoms[i] == atmProtocol) {
+ ++found;
+ break;
+ }
+ xcb_icccm_get_wm_protocols_reply_wipe(&reply);
}
return found > 0;
@@ -522,49 +558,46 @@ IsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol)
* Send a message to the X server from the WM thread
*/
-static int
-SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData)
+static void
+SendXMessage(xcb_connection_t *conn, xcb_window_t iWin, xcb_atom_t atmType, long nData)
{
- XEvent e;
+ xcb_client_message_event_t e;
/* Prepare the X event structure */
- e.type = ClientMessage;
- e.xclient.window = iWin;
- e.xclient.message_type = atmType;
- e.xclient.format = 32;
- e.xclient.data.l[0] = nData;
- e.xclient.data.l[1] = CurrentTime;
+ memset(&e, 0, sizeof(e));
+ e.response_type = XCB_CLIENT_MESSAGE;
+ e.window = iWin;
+ e.type = atmType;
+ e.format = 32;
+ e.data.data32[0] = nData;
+ e.data.data32[1] = XCB_CURRENT_TIME;
/* Send the event to X */
- return XSendEvent(pDisplay, iWin, False, NoEventMask, &e);
+ xcb_send_event(conn, FALSE, iWin, XCB_EVENT_MASK_NO_EVENT, (const char *)&e);
}
/*
* See if we can get the stored HWND for this window...
*/
static HWND
-getHwnd(WMInfoPtr pWMInfo, Window iWindow)
+getHwnd(WMInfoPtr pWMInfo, xcb_window_t iWindow)
{
- Atom atmType;
- int fmtRet;
- unsigned long items, remain;
- HWND *retHwnd, hWnd = NULL;
-
- if (XGetWindowProperty(pWMInfo->pDisplay,
- iWindow,
- pWMInfo->atmPrivMap,
- 0,
- sizeof(HWND)/4,
- False,
- XA_INTEGER,
- &atmType,
- &fmtRet,
- &items,
- &remain, (unsigned char **) &retHwnd) == Success) {
- if (retHwnd) {
- hWnd = *retHwnd;
- XFree(retHwnd);
+ HWND hWnd = NULL;
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *reply;
+
+ cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow, pWMInfo->atmPrivMap,
+ XCB_ATOM_INTEGER, 0L, sizeof(HWND)/4L);
+ reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
+
+ if (reply) {
+ int length = xcb_get_property_value_length(reply);
+ HWND *value = xcb_get_property_value(reply);
+
+ if (value && (length == sizeof(HWND))) {
+ hWnd = *value;
}
+ free(reply);
}
/* Some sanity checks */
@@ -577,26 +610,81 @@ getHwnd(WMInfoPtr pWMInfo, Window iWindow)
}
/*
+ * Helper function to check for override-redirect
+ */
+static Bool
+IsOverrideRedirect(xcb_connection_t *conn, xcb_window_t iWin)
+{
+ Bool result = FALSE;
+ xcb_get_window_attributes_reply_t *reply;
+ xcb_get_window_attributes_cookie_t cookie;
+
+ cookie = xcb_get_window_attributes(conn, iWin);
+ reply = xcb_get_window_attributes_reply(conn, cookie, NULL);
+ if (reply) {
+ result = (reply->override_redirect != 0);
+ free(reply);
+ }
+ else {
+ ErrorF("IsOverrideRedirect: Failed to get window attributes\n");
+ }
+
+ return result;
+}
+
+/*
+ * Helper function to get class and window names
+*/
+static void
+GetClassNames(WMInfoPtr pWMInfo, xcb_window_t iWindow, char **res_name,
+ char **res_class, char **window_name)
+{
+ xcb_get_property_cookie_t cookie1;
+ xcb_icccm_get_wm_class_reply_t reply1;
+ xcb_get_property_cookie_t cookie2;
+ xcb_icccm_get_text_property_reply_t reply2;
+
+ cookie1 = xcb_icccm_get_wm_class(pWMInfo->conn, iWindow);
+ if (xcb_icccm_get_wm_class_reply(pWMInfo->conn, cookie1, &reply1,
+ NULL)) {
+ *res_name = strdup(reply1.instance_name);
+ *res_class = strdup(reply1.class_name);
+ xcb_icccm_get_wm_class_reply_wipe(&reply1);
+ }
+ else {
+ *res_name = strdup("");
+ *res_class = strdup("");
+ }
+
+ cookie2 = xcb_icccm_get_wm_name(pWMInfo->conn, iWindow);
+ if (xcb_icccm_get_wm_name_reply(pWMInfo->conn, cookie2, &reply2, NULL)) {
+ *window_name = strndup(reply2.name, reply2.name_len);
+ xcb_icccm_get_text_property_reply_wipe(&reply2);
+ }
+ else {
+ *window_name = strdup("");
+ }
+}
+
+/*
* Updates the name of a HWND according to its X WM_NAME property
*/
static void
-UpdateName(WMInfoPtr pWMInfo, Window iWindow)
+UpdateName(WMInfoPtr pWMInfo, xcb_window_t iWindow)
{
HWND hWnd;
- XWindowAttributes attr;
hWnd = getHwnd(pWMInfo, iWindow);
if (!hWnd)
return;
/* If window isn't override-redirect */
- XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
- if (!attr.override_redirect) {
+ if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) {
char *pszWindowName;
/* Get the X windows window name */
- GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName);
+ GetWindowName(pWMInfo, iWindow, &pszWindowName);
if (pszWindowName) {
/* Convert from UTF-8 to wide char */
@@ -621,39 +709,30 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow)
*/
static void
-UpdateIcon(WMInfoPtr pWMInfo, Window iWindow)
+UpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow)
{
HWND hWnd;
HICON hIconNew = NULL;
- XWindowAttributes attr;
hWnd = getHwnd(pWMInfo, iWindow);
if (!hWnd)
return;
/* If window isn't override-redirect */
- XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
- if (!attr.override_redirect) {
- XClassHint class_hint = { 0, 0 };
+ if (!IsOverrideRedirect(pWMInfo->conn, iWindow)) {
char *window_name = 0;
+ char *res_name = 0;
+ char *res_class = 0;
- if (XGetClassHint(pWMInfo->pDisplay, iWindow, &class_hint)) {
- XFetchName(pWMInfo->pDisplay, iWindow, &window_name);
+ GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name);
- hIconNew =
- (HICON) winOverrideIcon(class_hint.res_name,
- class_hint.res_class, window_name);
+ hIconNew = winOverrideIcon(res_name, res_class, window_name);
- if (class_hint.res_name)
- XFree(class_hint.res_name);
- if (class_hint.res_class)
- XFree(class_hint.res_class);
- if (window_name)
- XFree(window_name);
- }
+ free(res_name);
+ free(res_class);
+ free(window_name);
+ winUpdateIcon(hWnd, pWMInfo->conn, iWindow, hIconNew);
}
-
- winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew);
}
/*
@@ -661,7 +740,7 @@ UpdateIcon(WMInfoPtr pWMInfo, Window iWindow)
*/
static void
-UpdateStyle(WMInfoPtr pWMInfo, Window iWindow)
+UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, Bool onCreate)
{
HWND hWnd;
HWND zstyle = HWND_NOTOPMOST;
@@ -672,7 +751,7 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow)
return;
/* Determine the Window style, which determines borders and clipping region... */
- winApplyHints(pWMInfo->pDisplay, iWindow, hWnd, &zstyle);
+ winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, onCreate);
winUpdateWindowPosition(hWnd, &zstyle);
/* Apply the updated window style, without changing it's show or activation state */
@@ -693,6 +772,155 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow)
winShowWindowOnTaskbar(hWnd,
(GetWindowLongPtr(hWnd, GWL_EXSTYLE) &
WS_EX_APPWINDOW) ? TRUE : FALSE);
+
+ /* Check urgency hint */
+ winApplyUrgency(pWMInfo, iWindow, hWnd);
+}
+
+/*
+ * Updates the state of a HWND
+ */
+
+static void
+UpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow, int state)
+{
+ HWND hWnd;
+ int current_state = -1;
+
+ winDebug("UpdateState: iWindow 0x%08x %d\n", (int)iWindow, state);
+
+ hWnd = getHwnd(pWMInfo, iWindow);
+ if (hWnd)
+ {
+ // Keep track of the Window state, do nothing if it's not changing
+ current_state = (intptr_t)GetProp(hWnd, WIN_STATE_PROP);
+
+ if (current_state == state)
+ return;
+
+ SetProp(hWnd, WIN_STATE_PROP, (HANDLE)(intptr_t)state);
+
+ switch (state)
+ {
+ case XCB_ICCCM_WM_STATE_ICONIC:
+ ShowWindow(hWnd, SW_SHOWMINNOACTIVE);
+ break;
+
+#define XCB_ICCCM_WM_STATE_ZOOM 2
+ case XCB_ICCCM_WM_STATE_ZOOM:
+ // There doesn't seem to be a SW_SHOWMAXNOACTIVE. Hopefully
+ // always activating a maximized window isn't so bad...
+ ShowWindow(hWnd, SW_SHOWMAXIMIZED);
+ break;
+
+ case XCB_ICCCM_WM_STATE_NORMAL:
+ ShowWindow(hWnd, SW_SHOWNOACTIVATE);
+ break;
+
+ case XCB_ICCCM_WM_STATE_WITHDRAWN:
+ ShowWindow(hWnd, SW_HIDE);
+ break;
+ }
+ }
+
+ // Update WM_STATE property
+ {
+ // ZoomState is obsolete in ICCCM, so map it to NormalState
+ int icccm_state = state;
+ int icccm_current_state = current_state;
+
+ if (icccm_state == XCB_ICCCM_WM_STATE_ZOOM)
+ icccm_state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if (icccm_current_state == XCB_ICCCM_WM_STATE_ZOOM)
+ icccm_current_state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ // Don't change property unnecessarily
+ //
+ // (Note that we do not take notice of WM_STATE PropertyNotify, only
+ // WM_CHANGE_STATE ClientMessage, so this should not cause the state to
+ // change itself)
+ if (icccm_current_state != icccm_state)
+ {
+ struct
+ {
+ CARD32 state;
+ XID icon;
+ } wmstate;
+
+ wmstate.state = icccm_state;
+ wmstate.icon = None;
+
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ iWindow, pWMInfo->atmWmState,
+ pWMInfo->atmWmState, 32,
+ sizeof(wmstate)/sizeof(int),
+ (unsigned char *) &wmstate);
+ }
+ }
+
+ // Update _NET_WM_STATE property
+ if (state == XCB_ICCCM_WM_STATE_WITHDRAWN) {
+ xcb_delete_property(pWMInfo->conn, iWindow, pWMInfo->ewmh._NET_WM_STATE);
+ }
+ else {
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *reply;
+
+ cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow,
+ pWMInfo->ewmh._NET_WM_STATE,
+ XCB_ATOM_ATOM,
+ 0, INT_MAX);
+ reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
+ if (reply) {
+ int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
+ xcb_atom_t *pAtom = xcb_get_property_value(reply);
+ unsigned long i, o = 0;
+ xcb_atom_t netwmstate[nitems + 2];
+ Bool changed = FALSE;
+
+ // Make a copy with _NET_WM_HIDDEN, _NET_WM_MAXIMIZED_{VERT,HORZ}
+ // removed
+ for (i = 0; i < nitems; i++) {
+ if ((pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_HIDDEN) &&
+ (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ netwmstate[o++] = pAtom[i];
+ }
+ free(reply);
+
+ // if iconized, add _NET_WM_HIDDEN
+ if (state == XCB_ICCCM_WM_STATE_ICONIC) {
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_HIDDEN;
+ }
+
+ // if maximized, add _NET_WM_MAXIMIZED_{VERT,HORZ}
+ if (state == XCB_ICCCM_WM_STATE_ZOOM) {
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT;
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ;
+ }
+
+ // Don't change property unnecessarily
+ if (nitems != o)
+ changed = TRUE;
+ else
+ for (i = 0; i < nitems; i++)
+ {
+ if (pAtom[i] != netwmstate[i])
+ {
+ changed = TRUE;
+ break;
+ }
+ }
+
+ if (changed)
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ iWindow,
+ pWMInfo->ewmh._NET_WM_STATE,
+ XCB_ATOM_ATOM, 32,
+ o, (unsigned char *) &netwmstate);
+ }
+ }
}
#if 0
@@ -701,11 +929,11 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow)
* starting at the window passed in
*/
static void
-PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction)
+PreserveWin32Stack(WMInfoPtr pWMInfo, xcb_window_t iWindow, UINT direction)
{
HWND hWnd;
DWORD myWinProcID, winProcID;
- Window xWindow;
+ xcb_window_t xWindow;
WINDOWPLACEMENT wndPlace;
hWnd = getHwnd(pWMInfo, iWindow);
@@ -746,6 +974,8 @@ winMultiWindowWMProc(void *pArg)
WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
/* Initialize the Window Manager */
winInitMultiWindowWM(pWMInfo, pProcArg);
@@ -757,11 +987,6 @@ winMultiWindowWMProc(void *pArg)
for (;;) {
WMMsgNodePtr pNode;
- if (g_fAnotherWMRunning) { /* Another Window manager exists. */
- Sleep(1000);
- continue;
- }
-
/* Pop a message off of our queue */
pNode = PopMessage(&pWMInfo->wmMsgQueue, pWMInfo);
if (pNode == NULL) {
@@ -772,77 +997,72 @@ winMultiWindowWMProc(void *pArg)
}
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winMultiWindowWMProc - MSG: %d ID: %d\n",
- (int) pNode->msg.msg, (int) pNode->msg.dwID);
+ ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n",
+ MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID);
#endif
/* Branch on the message type */
switch (pNode->msg.msg) {
#if 0
case WM_WM_MOVE:
- ErrorF("\tWM_WM_MOVE\n");
break;
case WM_WM_SIZE:
- ErrorF("\tWM_WM_SIZE\n");
break;
#endif
case WM_WM_RAISE:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_RAISE\n");
-#endif
/* Raise the window */
- XRaiseWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
+ {
+ const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
+ xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow,
+ XCB_CONFIG_WINDOW_STACK_MODE, values);
+ }
+
#if 0
PreserveWin32Stack(pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
#endif
break;
case WM_WM_LOWER:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_LOWER\n");
-#endif
-
/* Lower the window */
- XLowerWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
+ {
+ const static uint32_t values[] = { XCB_STACK_MODE_BELOW };
+ xcb_configure_window(pWMInfo->conn, pNode->msg.iWindow,
+ XCB_CONFIG_WINDOW_STACK_MODE, values);
+ }
break;
case WM_WM_MAP:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_MAP\n");
-#endif
/* Put a note as to the HWND associated with this Window */
- XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER,
- 32,
- PropModeReplace,
- (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4);
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ pNode->msg.iWindow, pWMInfo->atmPrivMap,
+ XCB_ATOM_INTEGER, 32,
+ sizeof(HWND)/4, &(pNode->msg.hwndWindow));
+
UpdateName(pWMInfo, pNode->msg.iWindow);
UpdateIcon(pWMInfo, pNode->msg.iWindow);
break;
- case WM_WM_MAP2:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_MAP2\n");
-#endif
- XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER,
- 32,
- PropModeReplace,
- (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4);
+ case WM_WM_MAP_UNMANAGED:
+ /* Put a note as to the HWND associated with this Window */
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ pNode->msg.iWindow, pWMInfo->atmPrivMap,
+ XCB_ATOM_INTEGER, 32,
+ sizeof(HWND)/4, &(pNode->msg.hwndWindow));
+
break;
- case WM_WM_MAP3:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_MAP3\n");
-#endif
+ case WM_WM_MAP_MANAGED:
/* Put a note as to the HWND associated with this Window */
- XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER,
- 32,
- PropModeReplace,
- (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4);
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ pNode->msg.iWindow, pWMInfo->atmPrivMap,
+ XCB_ATOM_INTEGER, 32,
+ sizeof(HWND)/4, &(pNode->msg.hwndWindow));
+
UpdateName(pWMInfo, pNode->msg.iWindow);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, TRUE);
UpdateIcon(pWMInfo, pNode->msg.iWindow);
- UpdateStyle(pWMInfo, pNode->msg.iWindow);
/* Reshape */
@@ -858,35 +1078,26 @@ winMultiWindowWMProc(void *pArg)
break;
case WM_WM_UNMAP:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_UNMAP\n");
-#endif
/* Unmap the window */
- XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow);
+ xcb_unmap_window(pWMInfo->conn, pNode->msg.iWindow);
break;
case WM_WM_KILL:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_KILL\n");
-#endif
{
/* --- */
- if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+ if (IsWmProtocolAvailable(pWMInfo,
pNode->msg.iWindow,
pWMInfo->atmWmDelete))
- SendXMessage(pWMInfo->pDisplay,
+ SendXMessage(pWMInfo->conn,
pNode->msg.iWindow,
pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
else
- XKillClient(pWMInfo->pDisplay, pNode->msg.iWindow);
+ xcb_kill_client(pWMInfo->conn, pNode->msg.iWindow);
}
break;
case WM_WM_ACTIVATE:
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("\tWM_WM_ACTIVATE\n");
-#endif
/* Set the input focus */
/*
@@ -899,23 +1110,24 @@ winMultiWindowWMProc(void *pArg)
*/
{
Bool neverFocus = FALSE;
- XWMHints *hints = XGetWMHints(pWMInfo->pDisplay, pNode->msg.iWindow);
-
- if (hints) {
- if (hints->flags & InputHint)
- neverFocus = !hints->input;
- XFree(hints);
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_wm_hints_t hints;
+
+ cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, pNode->msg.iWindow);
+ if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints,
+ NULL)) {
+ if (hints.flags & XCB_ICCCM_WM_HINT_INPUT)
+ neverFocus = !hints.input;
}
if (!neverFocus)
- XSetInputFocus(pWMInfo->pDisplay,
- pNode->msg.iWindow,
- RevertToPointerRoot, CurrentTime);
+ xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_POINTER_ROOT,
+ pNode->msg.iWindow, XCB_CURRENT_TIME);
- if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+ if (IsWmProtocolAvailable(pWMInfo,
pNode->msg.iWindow,
pWMInfo->atmWmTakeFocus))
- SendXMessage(pWMInfo->pDisplay,
+ SendXMessage(pWMInfo->conn,
pNode->msg.iWindow,
pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus);
@@ -932,20 +1144,16 @@ winMultiWindowWMProc(void *pArg)
case WM_WM_HINTS_EVENT:
{
- XWindowAttributes attr;
-
/* Don't do anything if this is an override-redirect window */
- XGetWindowAttributes (pWMInfo->pDisplay, pNode->msg.iWindow, &attr);
- if (attr.override_redirect)
+ if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow))
break;
- UpdateStyle(pWMInfo, pNode->msg.iWindow);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, FALSE);
}
break;
case WM_WM_CHANGE_STATE:
- /* Minimize the window in Windows */
- winMinimizeWindow(pNode->msg.iWindow);
+ UpdateState(pWMInfo, pNode->msg.iWindow, pNode->msg.dwID);
break;
default:
@@ -958,7 +1166,31 @@ winMultiWindowWMProc(void *pArg)
free(pNode);
/* Flush any pending events on our display */
- XFlush(pWMInfo->pDisplay);
+ xcb_flush(pWMInfo->conn);
+
+ /* This is just laziness rather than making sure we used _checked everywhere */
+ {
+ xcb_generic_event_t *event = xcb_poll_for_event(pWMInfo->conn);
+ if (event) {
+ if ((event->response_type & ~0x80) == 0) {
+ xcb_generic_error_t *err = (xcb_generic_error_t *)event;
+ winDebug("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, "
+ "Major opcode: %i, Minor opcode: %i\n",
+ err->error_code, err->resource_id,
+ err->major_code, err->minor_code);
+ }
+ }
+ }
+
+ /* I/O errors etc. */
+ {
+ int e = xcb_connection_has_error(pWMInfo->conn);
+ if (e) {
+ ErrorF("winMultiWindowWMProc - Fatal error %d on xcb connection\n", e);
+ pthread_exit(NULL);
+ break;
+ }
+ }
}
/* Free the condition variable */
@@ -973,9 +1205,28 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+
+ pthread_cleanup_pop(0);
+
return NULL;
}
+static xcb_atom_t
+intern_atom(xcb_connection_t *conn, const char *atomName)
+{
+ xcb_intern_atom_reply_t *atom_reply;
+ xcb_intern_atom_cookie_t atom_cookie;
+ xcb_atom_t atom = XCB_ATOM_NONE;
+
+ atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
+ atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
+ if (atom_reply) {
+ atom = atom_reply->atom;
+ free(atom_reply);
+ }
+ return atom;
+}
+
/*
* X message procedure
*/
@@ -987,14 +1238,18 @@ winMultiWindowXMsgProc(void *pArg)
XMsgProcArgPtr pProcArg = (XMsgProcArgPtr) pArg;
char pszDisplay[512];
int iRetries;
- XEvent event;
- Atom atmWmName;
- Atom atmWmHints;
- Atom atmWmChange;
- Atom atmNetWmIcon;
- Atom atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints;
+ xcb_atom_t atmWmName;
+ xcb_atom_t atmNetWmName;
+ xcb_atom_t atmWmHints;
+ xcb_atom_t atmWmChange;
+ xcb_atom_t atmNetWmIcon;
+ xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints;
int iReturn;
- XIconSize *xis;
+ xcb_auth_info_t *auth_info;
+ xcb_screen_t *root_screen;
+ xcb_window_t root_window_id;
+
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
winDebug("winMultiWindowXMsgProc - Hello\n");
@@ -1004,7 +1259,7 @@ winMultiWindowXMsgProc(void *pArg)
pthread_exit(NULL);
}
- ErrorF("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
+ winDebug("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n");
/* Grab the server started mutex - pause until we get it */
iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
@@ -1014,44 +1269,12 @@ winMultiWindowXMsgProc(void *pArg)
pthread_exit(NULL);
}
- 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");
- }
+ winDebug("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n");
/* Release the server started mutex */
pthread_mutex_unlock(pProcArg->ppmServerStarted);
- ErrorF("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
-
- /* Install our error handler */
- XSetErrorHandler(winMultiWindowXMsgProcErrorHandler);
- g_winMultiWindowXMsgProcThread = pthread_self();
- g_winMultiWindowXMsgProcOldIOErrorHandler =
- XSetIOErrorHandler(winMultiWindowXMsgProcIOErrorHandler);
-
- /* Set jump point for IO Error exits */
- iReturn = setjmp(g_jmpXMsgProcEntry);
-
- /* Check if we should continue operations */
- if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
- /* setjmp returned an unknown value, exit */
- ErrorF("winInitMultiWindowXMsgProc - setjmp returned: %d. Exiting.\n",
- iReturn);
- pthread_exit(NULL);
- }
- else if (iReturn == WIN_JMP_ERROR_IO) {
- ErrorF("winInitMultiWindowXMsgProc - Caught IO Error. Exiting.\n");
- pthread_exit(NULL);
- }
+ winDebug("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
/* Setup the display connection string x */
winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
@@ -1060,7 +1283,7 @@ winMultiWindowXMsgProc(void *pArg)
ErrorF("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay);
/* Use our generated cookie for authentication */
- winSetAuthorization();
+ auth_info = winGetXcbAuthInfo();
/* Initialize retry count */
iRetries = 0;
@@ -1068,8 +1291,9 @@ winMultiWindowXMsgProc(void *pArg)
/* Open the X display */
do {
/* Try to open the display */
- pProcArg->pDisplay = XOpenDisplay(pszDisplay);
- if (pProcArg->pDisplay == NULL) {
+ pProcArg->conn = xcb_connect_to_display_with_auth_info(pszDisplay,
+ auth_info, NULL);
+ if (xcb_connection_has_error(pProcArg->conn)) {
ErrorF("winMultiWindowXMsgProc - Could not open display, try: %d, "
"sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
++iRetries;
@@ -1079,102 +1303,139 @@ winMultiWindowXMsgProc(void *pArg)
else
break;
}
- while (pProcArg->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
+ while (xcb_connection_has_error(pProcArg->conn) && iRetries < WIN_CONNECT_RETRIES);
/* Make sure that the display opened */
- if (pProcArg->pDisplay == NULL) {
+ if (xcb_connection_has_error(pProcArg->conn)) {
ErrorF("winMultiWindowXMsgProc - Failed opening the display. "
"Exiting.\n");
pthread_exit(NULL);
}
- ErrorF("winMultiWindowXMsgProc - XOpenDisplay () returned and "
+ ErrorF("winMultiWindowXMsgProc - xcb_connect() returned and "
"successfully opened the display.\n");
/* Check if another window manager is already running */
- g_fAnotherWMRunning =
- CheckAnotherWindowManager(pProcArg->pDisplay, pProcArg->dwScreen,
- pProcArg->pWMInfo->fAllowOtherWM);
-
- if (g_fAnotherWMRunning && !pProcArg->pWMInfo->fAllowOtherWM) {
+ if (CheckAnotherWindowManager(pProcArg->conn, pProcArg->dwScreen)) {
ErrorF("winMultiWindowXMsgProc - "
"another window manager is running. Exiting.\n");
pthread_exit(NULL);
}
- /* Set up the supported icon sizes */
- xis = XAllocIconSize();
- if (xis) {
- xis->min_width = xis->min_height = 16;
- xis->max_width = xis->max_height = 48;
- xis->width_inc = xis->height_inc = 16;
- XSetIconSizes(pProcArg->pDisplay,
- RootWindow(pProcArg->pDisplay, pProcArg->dwScreen),
- xis, 1);
- XFree(xis);
+ /* Get root window id */
+ root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
+ root_window_id = root_screen->root;
+
+ {
+ /* Set WM_ICON_SIZE property indicating desired icon sizes */
+ typedef struct {
+ uint32_t min_width, min_height;
+ uint32_t max_width, max_height;
+ int32_t width_inc, height_inc;
+ } xcb_wm_icon_size_hints_hints_t;
+
+ xcb_wm_icon_size_hints_hints_t xis;
+ xis.min_width = xis.min_height = 16;
+ xis.max_width = xis.max_height = 48;
+ xis.width_inc = xis.height_inc = 16;
+
+ xcb_change_property(pProcArg->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ XCB_ATOM_WM_ICON_SIZE, XCB_ATOM_WM_ICON_SIZE, 32,
+ sizeof(xis)/4, &xis);
}
- atmWmName = XInternAtom(pProcArg->pDisplay, "WM_NAME", False);
- atmWmHints = XInternAtom(pProcArg->pDisplay, "WM_HINTS", False);
- atmWmChange = XInternAtom(pProcArg->pDisplay, "WM_CHANGE_STATE", False);
- atmNetWmIcon = XInternAtom(pProcArg->pDisplay, "_NET_WM_ICON", False);
- atmWindowState = XInternAtom(pProcArg->pDisplay, "_NET_WM_STATE", False);
- atmMotifWmHints = XInternAtom(pProcArg->pDisplay, "_MOTIF_WM_HINTS", False);
- atmWindowType = XInternAtom(pProcArg->pDisplay, "_NET_WM_WINDOW_TYPE", False);
- atmNormalHints = XInternAtom(pProcArg->pDisplay, "WM_NORMAL_HINTS", False);
+ atmWmName = intern_atom(pProcArg->conn, "WM_NAME");
+ atmNetWmName = intern_atom(pProcArg->conn, "_NET_WM_NAME");
+ atmWmHints = intern_atom(pProcArg->conn, "WM_HINTS");
+ atmWmChange = intern_atom(pProcArg->conn, "WM_CHANGE_STATE");
+ atmNetWmIcon = intern_atom(pProcArg->conn, "_NET_WM_ICON");
+ atmWindowState = intern_atom(pProcArg->conn, "_NET_WM_STATE");
+ atmMotifWmHints = intern_atom(pProcArg->conn, "_MOTIF_WM_HINTS");
+ atmWindowType = intern_atom(pProcArg->conn, "_NET_WM_WINDOW_TYPE");
+ atmNormalHints = intern_atom(pProcArg->conn, "WM_NORMAL_HINTS");
/*
- iiimxcf had a bug until 2009-04-27, assuming that the
- WM_STATE atom exists, causing clients to fail with
- a BadAtom X error if it doesn't.
-
- Since this is on in the default Solaris 10 install,
- workaround this by making sure it does exist...
+ Enable Composite extension and redirect subwindows of the root window
*/
- XInternAtom(pProcArg->pDisplay, "WM_STATE", 0);
+ if (pProcArg->pWMInfo->fCompositeWM) {
+ const char *extension_name = "Composite";
+ xcb_query_extension_cookie_t cookie;
+ xcb_query_extension_reply_t *reply;
+
+ cookie = xcb_query_extension(pProcArg->conn, strlen(extension_name), extension_name);
+ reply = xcb_query_extension_reply(pProcArg->conn, cookie, NULL);
+
+ if (reply && (reply->present)) {
+ xcb_composite_redirect_subwindows(pProcArg->conn,
+ root_window_id,
+ XCB_COMPOSITE_REDIRECT_AUTOMATIC);
+
+ /*
+ We use automatic updating of the root window for two
+ reasons:
+
+ 1) redirected window contents are mirrored to the root
+ window so that the root window draws correctly when shown.
+
+ 2) updating the root window causes damage against the
+ shadow framebuffer, which ultimately causes WM_PAINT to be
+ sent to the affected window(s) to cause the damage regions
+ to be redrawn.
+ */
+
+ ErrorF("Using Composite redirection\n");
+
+ free(reply);
+ }
+ }
/* Loop until we explicitly break out */
while (1) {
+ xcb_generic_event_t *event;
+ uint8_t type;
+ Bool send_event;
+
if (g_shutdown)
break;
- if (pProcArg->pWMInfo->fAllowOtherWM && !XPending(pProcArg->pDisplay)) {
- if (CheckAnotherWindowManager
- (pProcArg->pDisplay, pProcArg->dwScreen, TRUE)) {
- if (!g_fAnotherWMRunning) {
- g_fAnotherWMRunning = TRUE;
- SendMessage(pProcArg->hwndScreen, WM_UNMANAGE, 0, 0);
- }
- }
- else {
- if (g_fAnotherWMRunning) {
- g_fAnotherWMRunning = FALSE;
- SendMessage(pProcArg->hwndScreen, WM_MANAGE, 0, 0);
- }
- }
- Sleep(500);
- continue;
- }
-
/* Fetch next event */
- XNextEvent(pProcArg->pDisplay, &event);
-
- /* Branch on event type */
- if (event.type == CreateNotify) {
- XWindowAttributes attr;
+ event = xcb_wait_for_event(pProcArg->conn);
+ if (!event) { // returns NULL on I/O error
+ int e = xcb_connection_has_error(pProcArg->conn);
+ ErrorF("winMultiWindowXMsgProc - Fatal error %d on xcb connection\n", e);
+ pthread_exit(NULL);
+ break;
+ }
- XSelectInput(pProcArg->pDisplay,
- event.xcreatewindow.window, PropertyChangeMask);
+ type = event->response_type & ~0x80;
+ send_event = event->response_type & 0x80;
- /* Get the window attributes */
- XGetWindowAttributes(pProcArg->pDisplay,
- event.xcreatewindow.window, &attr);
+ winDebug("winMultiWindowXMsgProc - event %d\n", type);
- if (!attr.override_redirect)
- XSetWindowBorderWidth(pProcArg->pDisplay,
- event.xcreatewindow.window, 0);
+ /* Branch on event type */
+ if (type == 0) {
+ xcb_generic_error_t *err = (xcb_generic_error_t *)event;
+ winDebug("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, "
+ "Major opcode: %i, Minor opcode: %i\n",
+ err->error_code, err->resource_id,
+ err->major_code, err->minor_code);
+ }
+ else if (type == XCB_CREATE_NOTIFY) {
+ xcb_create_notify_event_t *notify = (xcb_create_notify_event_t *)event;
+
+ /* Request property change events */
+ const static uint32_t mask_value[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
+ xcb_change_window_attributes (pProcArg->conn, notify->window,
+ XCB_CW_EVENT_MASK, mask_value);
+
+ /* If it's not override-redirect, set the border-width to 0 */
+ if (!IsOverrideRedirect(pProcArg->conn, notify->window)) {
+ const static uint32_t width_value[] = { 0 };
+ xcb_configure_window(pProcArg->conn, notify->window,
+ XCB_CONFIG_WINDOW_BORDER_WIDTH, width_value);
+ }
}
- else if (event.type == MapNotify) {
+ else if (type == XCB_MAP_NOTIFY) {
/* Fake a reparentNotify event as SWT/Motif expects a
Window Manager to reparent a top-level window when
it is mapped and waits until they do.
@@ -1190,43 +1451,54 @@ winMultiWindowXMsgProc(void *pArg)
See sourceware bugzilla #9848
*/
- XWindowAttributes attr;
- Window root;
- Window parent;
- Window *children;
- unsigned int nchildren;
-
- if (XGetWindowAttributes(event.xmap.display,
- event.xmap.window,
- &attr) &&
- XQueryTree(event.xmap.display,
- event.xmap.window,
- &root, &parent, &children, &nchildren)) {
- if (children)
- XFree(children);
+ xcb_map_notify_event_t *notify = (xcb_map_notify_event_t *)event;
+ xcb_get_geometry_cookie_t cookie;
+ xcb_get_geometry_reply_t *reply;
+ xcb_query_tree_cookie_t cookie_qt;
+ xcb_query_tree_reply_t *reply_qt;
+
+ cookie = xcb_get_geometry(pProcArg->conn, notify->window);
+ cookie_qt = xcb_query_tree(pProcArg->conn, notify->window);
+ reply = xcb_get_geometry_reply(pProcArg->conn, cookie, NULL);
+ reply_qt = xcb_query_tree_reply(pProcArg->conn, cookie_qt, NULL);
+
+ if (reply && reply_qt) {
/*
It's a top-level window if the parent window is a root window
Only non-override_redirect windows can get reparented
*/
- if ((attr.root == parent) && !event.xmap.override_redirect) {
- XEvent event_send;
-
- event_send.type = ReparentNotify;
- event_send.xreparent.event = event.xmap.window;
- event_send.xreparent.window = event.xmap.window;
- event_send.xreparent.parent = parent;
- event_send.xreparent.x = attr.x;
- event_send.xreparent.y = attr.y;
-
- XSendEvent(event.xmap.display,
- event.xmap.window,
- True, StructureNotifyMask, &event_send);
+ if ((reply->root == reply_qt->parent) && !notify->override_redirect) {
+ xcb_reparent_notify_event_t event_send;
+
+ event_send.response_type = ReparentNotify;
+ event_send.event = notify->window;
+ event_send.window = notify->window;
+ event_send.parent = reply_qt->parent;
+ event_send.x = reply->x;
+ event_send.y = reply->y;
+
+ xcb_send_event (pProcArg->conn, TRUE, notify->window,
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+ (const char *)&event_send);
+
+ free(reply_qt);
+ free(reply);
}
}
}
- else if (event.type == ConfigureNotify) {
- if (!event.xconfigure.send_event) {
+ else if (type == XCB_UNMAP_NOTIFY) {
+ xcb_unmap_notify_event_t *notify = (xcb_unmap_notify_event_t *)event;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg = WM_WM_CHANGE_STATE;
+ msg.iWindow = notify->window;
+ msg.dwID = XCB_ICCCM_WM_STATE_WITHDRAWN;
+
+ winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ }
+ else if (type == XCB_CONFIGURE_NOTIFY) {
+ if (!send_event) {
/*
Java applications using AWT on JRE 1.6.0 break with non-reparenting WMs AWT
doesn't explicitly know about (See sun bug #6434227)
@@ -1238,21 +1510,34 @@ winMultiWindowXMsgProc(void *pArg)
Rather than tell all sorts of lies to get XWM to recognize us as one of
those, simply send a synthetic ConfigureNotify for every non-synthetic one
*/
- XEvent event_send = event;
+ xcb_configure_notify_event_t *notify = (xcb_configure_notify_event_t *)event;
+ xcb_configure_notify_event_t event_send = *notify;
+
+ event_send.event = notify->window;
- event_send.xconfigure.send_event = TRUE;
- event_send.xconfigure.event = event.xconfigure.window;
- XSendEvent(event.xconfigure.display,
- event.xconfigure.window,
- True, StructureNotifyMask, &event_send);
+ xcb_send_event(pProcArg->conn, TRUE, notify->window,
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+ (const char *)&event_send);
}
}
- else if (event.type == PropertyNotify) {
- if (event.xproperty.atom == atmWmName) {
+ else if (type == XCB_PROPERTY_NOTIFY) {
+ xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)event;
+
+ xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(pProcArg->conn, notify->atom);
+ xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(pProcArg->conn, cookie, NULL);
+ if (reply) {
+ winDebug("winMultiWindowXMsgProc: PropertyNotify %.*s\n",
+ xcb_get_atom_name_name_length(reply),
+ xcb_get_atom_name_name(reply));
+ free(reply);
+ }
+
+ if ((notify->atom == atmWmName) ||
+ (notify->atom == atmNetWmName)) {
memset(&msg, 0, sizeof(msg));
msg.msg = WM_WM_NAME_EVENT;
- msg.iWindow = event.xproperty.window;
+ msg.iWindow = notify->window;
/* Other fields ignored */
winSendMessageToWM(pProcArg->pWMInfo, &msg);
@@ -1262,47 +1547,95 @@ winMultiWindowXMsgProc(void *pArg)
Several properties are considered for WM hints, check if this property change affects any of them...
(this list needs to be kept in sync with winApplyHints())
*/
- if ((event.xproperty.atom == atmWmHints) ||
- (event.xproperty.atom == atmWindowState) ||
- (event.xproperty.atom == atmMotifWmHints) ||
- (event.xproperty.atom == atmWindowType) ||
- (event.xproperty.atom == atmNormalHints)) {
+ if ((notify->atom == atmWmHints) ||
+ (notify->atom == atmWindowState) ||
+ (notify->atom == atmMotifWmHints) ||
+ (notify->atom == atmWindowType) ||
+ (notify->atom == atmNormalHints)) {
memset(&msg, 0, sizeof(msg));
msg.msg = WM_WM_HINTS_EVENT;
- msg.iWindow = event.xproperty.window;
+ msg.iWindow = notify->window;
/* Other fields ignored */
winSendMessageToWM(pProcArg->pWMInfo, &msg);
}
/* Not an else as WM_HINTS affects both style and icon */
- if ((event.xproperty.atom == atmWmHints) ||
- (event.xproperty.atom == atmNetWmIcon)) {
+ if ((notify->atom == atmWmHints) ||
+ (notify->atom == atmNetWmIcon)) {
memset(&msg, 0, sizeof(msg));
msg.msg = WM_WM_ICON_EVENT;
- msg.iWindow = event.xproperty.window;
+ msg.iWindow = notify->window;
/* Other fields ignored */
winSendMessageToWM(pProcArg->pWMInfo, &msg);
}
}
}
- else if (event.type == ClientMessage
- && event.xclient.message_type == atmWmChange
- && event.xclient.data.l[0] == IconicState) {
- ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
+ else if (type == XCB_CLIENT_MESSAGE) {
+ xcb_client_message_event_t *client_msg = (xcb_client_message_event_t *)event;
+ winDebug("winMultiWindowXMsgProc: ClientMessage: type %d window 0x%08x data[0] %d\n", client_msg->type, client_msg->window, client_msg->data.data32[0]);
- memset(&msg, 0, sizeof(msg));
+ if (client_msg->type == atmWmChange
+ && client_msg->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) {
+ ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
- msg.msg = WM_WM_CHANGE_STATE;
- msg.iWindow = event.xclient.window;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg = WM_WM_CHANGE_STATE;
+ msg.iWindow = client_msg->window;
+ msg.dwID = client_msg->data.data32[0];
- winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ }
+ else if (client_msg->type == pProcArg->pWMInfo->ewmh._NET_WM_STATE) {
+ int action = client_msg->data.data32[0];
+ int state = -1;
+
+ if (action == XCB_EWMH_WM_STATE_ADD) {
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ state = XCB_ICCCM_WM_STATE_ZOOM;
+
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT))
+ state = XCB_ICCCM_WM_STATE_ZOOM;
+
+ if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN)
+ state = XCB_ICCCM_WM_STATE_ICONIC;
+ }
+ else if (action == XCB_EWMH_WM_STATE_REMOVE) {
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT))
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN)
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+ }
+ else {
+ ErrorF("winMultiWindowXMsgProc: ClientMEssage _NET_WM_STATE unsupported action %d\n", action);
+ }
+
+ if (state != -1) {
+ memset(&msg, 0, sizeof(msg));
+ msg.msg = WM_WM_CHANGE_STATE;
+ msg.iWindow = client_msg->window;
+ msg.dwID = state;
+
+ winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ }
+ }
}
+
+ /* Free the event */
+ free(event);
}
- XCloseDisplay(pProcArg->pDisplay);
- pthread_exit(NULL);
+ xcb_disconnect(pProcArg->conn);
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -1317,7 +1650,7 @@ winInitWM(void **ppWMInfo,
pthread_t * ptWMProc,
pthread_t * ptXMsgProc,
pthread_mutex_t * ppmServerStarted,
- int dwScreen, HWND hwndScreen, BOOL allowOtherWM)
+ int dwScreen, HWND hwndScreen, Bool compositeWM)
{
WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec));
WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec));
@@ -1339,7 +1672,7 @@ winInitWM(void **ppWMInfo,
/* Set a return pointer to the Window Manager info structure */
*ppWMInfo = pWMInfo;
- pWMInfo->fAllowOtherWM = allowOtherWM;
+ pWMInfo->fCompositeWM = compositeWM;
/* Setup the argument structure for the thread function */
pArg->dwScreen = dwScreen;
@@ -1387,6 +1720,9 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
int iRetries = 0;
char pszDisplay[512];
int iReturn;
+ xcb_auth_info_t *auth_info;
+ xcb_screen_t *root_screen;
+ xcb_window_t root_window_id;
winDebug("winInitMultiWindowWM - Hello\n");
@@ -1396,7 +1732,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
pthread_exit(NULL);
}
- ErrorF("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
+ winDebug("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n");
/* Grab our garbage mutex to satisfy pthread_cond_wait */
iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted);
@@ -1406,44 +1742,12 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
pthread_exit(NULL);
}
- 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");
- }
+ winDebug("winInitMultiWindowWM - pthread_mutex_lock () returned.\n");
/* Release the server started mutex */
pthread_mutex_unlock(pProcArg->ppmServerStarted);
- ErrorF("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
-
- /* Install our error handler */
- XSetErrorHandler(winMultiWindowWMErrorHandler);
- g_winMultiWindowWMThread = pthread_self();
- g_winMultiWindowWMOldIOErrorHandler =
- XSetIOErrorHandler(winMultiWindowWMIOErrorHandler);
-
- /* Set jump point for IO Error exits */
- iReturn = setjmp(g_jmpWMEntry);
-
- /* Check if we should continue operations */
- if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
- /* setjmp returned an unknown value, exit */
- ErrorF("winInitMultiWindowWM - setjmp returned: %d. Exiting.\n",
- iReturn);
- pthread_exit(NULL);
- }
- else if (iReturn == WIN_JMP_ERROR_IO) {
- ErrorF("winInitMultiWindowWM - Caught IO Error. Exiting.\n");
- pthread_exit(NULL);
- }
+ winDebug("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
/* Setup the display connection string x */
winGetDisplayName(pszDisplay, (int) pProcArg->dwScreen);
@@ -1452,13 +1756,14 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
ErrorF("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay);
/* Use our generated cookie for authentication */
- winSetAuthorization();
+ auth_info = winGetXcbAuthInfo();
/* Open the X display */
do {
/* Try to open the display */
- pWMInfo->pDisplay = XOpenDisplay(pszDisplay);
- if (pWMInfo->pDisplay == NULL) {
+ pWMInfo->conn = xcb_connect_to_display_with_auth_info(pszDisplay,
+ auth_info, NULL);
+ if (xcb_connection_has_error(pWMInfo->conn)) {
ErrorF("winInitMultiWindowWM - Could not open display, try: %d, "
"sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
++iRetries;
@@ -1468,151 +1773,149 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
else
break;
}
- while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
+ while (xcb_connection_has_error(pWMInfo->conn) && iRetries < WIN_CONNECT_RETRIES);
/* Make sure that the display opened */
- if (pWMInfo->pDisplay == NULL) {
+ if (xcb_connection_has_error(pWMInfo->conn)) {
ErrorF("winInitMultiWindowWM - Failed opening the display. "
"Exiting.\n");
pthread_exit(NULL);
}
- ErrorF("winInitMultiWindowWM - XOpenDisplay () returned and "
+ ErrorF("winInitMultiWindowWM - xcb_connect () returned and "
"successfully opened the display.\n");
/* Create some atoms */
- pWMInfo->atmWmProtos = XInternAtom(pWMInfo->pDisplay,
- "WM_PROTOCOLS", False);
- pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
- "WM_DELETE_WINDOW", False);
- pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay,
- "WM_TAKE_FOCUS", False);
-
- pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
- WINDOWSWM_NATIVE_HWND, False);
-
- if (1) {
- Cursor cursor = XCreateFontCursor(pWMInfo->pDisplay, XC_left_ptr);
-
- if (cursor) {
- XDefineCursor(pWMInfo->pDisplay,
- DefaultRootWindow(pWMInfo->pDisplay), cursor);
- XFreeCursor(pWMInfo->pDisplay, cursor);
+ pWMInfo->atmWmProtos = intern_atom(pWMInfo->conn, "WM_PROTOCOLS");
+ pWMInfo->atmWmDelete = intern_atom(pWMInfo->conn, "WM_DELETE_WINDOW");
+ pWMInfo->atmWmTakeFocus = intern_atom(pWMInfo->conn, "WM_TAKE_FOCUS");
+ pWMInfo->atmPrivMap = intern_atom(pWMInfo->conn, WINDOWSWM_NATIVE_HWND);
+ pWMInfo->atmUtf8String = intern_atom(pWMInfo->conn, "UTF8_STRING");
+ pWMInfo->atmNetWmName = intern_atom(pWMInfo->conn, "_NET_WM_NAME");
+ pWMInfo->atmCurrentDesktop = intern_atom(pWMInfo->conn, "_NET_CURRENT_DESKTOP");
+ pWMInfo->atmNumberDesktops = intern_atom(pWMInfo->conn, "_NET_NUMBER_OF_DESKTOPS");
+ pWMInfo->atmDesktopNames = intern_atom(pWMInfo->conn, "__NET_DESKTOP_NAMES");
+ pWMInfo->atmWmState = intern_atom(pWMInfo->conn, "WM_STATE");
+
+ /* Initialization for the xcb_ewmh and EWMH atoms */
+ {
+ xcb_intern_atom_cookie_t *atoms_cookie;
+ atoms_cookie = xcb_ewmh_init_atoms(pWMInfo->conn, &pWMInfo->ewmh);
+ if (xcb_ewmh_init_atoms_replies(&pWMInfo->ewmh, atoms_cookie, NULL)) {
+ /* Set the _NET_SUPPORTED atom for this context.
+
+ TODO: Audit to ensure we implement everything defined as MUSTs
+ for window managers in the EWMH standard.*/
+ xcb_atom_t supported[] =
+ {
+ pWMInfo->ewmh.WM_PROTOCOLS,
+ pWMInfo->ewmh._NET_SUPPORTED,
+ pWMInfo->ewmh._NET_SUPPORTING_WM_CHECK,
+ pWMInfo->ewmh._NET_CLOSE_WINDOW,
+ pWMInfo->ewmh._NET_WM_WINDOW_TYPE,
+ pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK,
+ pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH,
+ pWMInfo->ewmh._NET_WM_STATE,
+ pWMInfo->ewmh._NET_WM_STATE_HIDDEN,
+ pWMInfo->ewmh._NET_WM_STATE_ABOVE,
+ pWMInfo->ewmh._NET_WM_STATE_BELOW,
+ pWMInfo->ewmh._NET_WM_STATE_SKIP_TASKBAR,
+ pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT,
+ pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ,
+ };
+
+ xcb_ewmh_set_supported(&pWMInfo->ewmh, pProcArg->dwScreen,
+ sizeof(supported)/sizeof(xcb_atom_t), supported);
+ }
+ else {
+ ErrorF("winInitMultiWindowWM - xcb_ewmh_init_atoms() failed\n");
}
}
-}
-/*
- * winSendMessageToWM - Send a message from the X thread to the WM thread
- */
-
-void
-winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
-{
- WMMsgNodePtr pNode;
+ /* Get root window id */
+ root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen);
+ root_window_id = root_screen->root;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF("winSendMessageToWM ()\n");
-#endif
-
- pNode = malloc(sizeof(WMMsgNodeRec));
- if (pNode != NULL) {
- memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec));
- PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode);
- }
-}
-
-/*
- * Window manager error handler
- */
-
-static int
-winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr)
-{
- char pszErrorMsg[100];
-
- if (pErr->request_code == X_ChangeWindowAttributes
- && pErr->error_code == BadAccess) {
- ErrorF("winMultiWindowWMErrorHandler - ChangeWindowAttributes "
- "BadAccess.\n");
- return 0;
+ /*
+ Set root window properties for describing multiple desktops to describe
+ the one desktop we have
+ */
+ {
+ int data;
+ const char buf[] = "Desktop";
+
+ data = 0;
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmCurrentDesktop, XCB_ATOM_CARDINAL, 32,
+ 1, &data);
+ data = 1;
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmNumberDesktops, XCB_ATOM_CARDINAL, 32,
+ 1, &data);
+
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmDesktopNames, pWMInfo->atmUtf8String, 8,
+ strlen(buf), (unsigned char *) buf);
}
- XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
- ErrorF("winMultiWindowWMErrorHandler - ERROR: %s\n", pszErrorMsg);
+ /*
+ Set the root window cursor to left_ptr (this controls the cursor an
+ application gets over it's windows when it doesn't set one)
+ */
+ {
+#define XC_left_ptr 68
+ xcb_cursor_t cursor = xcb_generate_id(pWMInfo->conn);
+ xcb_font_t font = xcb_generate_id(pWMInfo->conn);
+ xcb_font_t *mask_font = &font; /* An alias to clarify */
+ int shape = XC_left_ptr;
+ uint32_t mask = XCB_CW_CURSOR;
+ uint32_t value_list = cursor;
- return 0;
-}
+ static const uint16_t fgred = 0, fggreen = 0, fgblue = 0;
+ static const uint16_t bgred = 0xFFFF, bggreen = 0xFFFF, bgblue = 0xFFFF;
-/*
- * Window manager IO error handler
- */
+ xcb_open_font(pWMInfo->conn, font, sizeof("cursor"), "cursor");
-static int
-winMultiWindowWMIOErrorHandler(Display * pDisplay)
-{
- ErrorF("winMultiWindowWMIOErrorHandler!\n");
+ xcb_create_glyph_cursor(pWMInfo->conn, cursor, font, *mask_font,
+ shape, shape + 1,
+ fgred, fggreen, fgblue, bgred, bggreen, bgblue);
- if (pthread_equal(pthread_self(), g_winMultiWindowWMThread)) {
- if (g_shutdown)
- pthread_exit(NULL);
+ xcb_change_window_attributes(pWMInfo->conn, root_window_id, mask, &value_list);
- /* Restart at the main entry point */
- longjmp(g_jmpWMEntry, WIN_JMP_ERROR_IO);
+ xcb_free_cursor(pWMInfo->conn, cursor);
+ xcb_close_font(pWMInfo->conn, font);
}
-
- if (g_winMultiWindowWMOldIOErrorHandler)
- g_winMultiWindowWMOldIOErrorHandler(pDisplay);
-
- return 0;
}
/*
- * X message procedure error handler
+ * winSendMessageToWM - Send a message from the X thread to the WM thread
*/
-static int
-winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr)
+void
+winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
{
- char pszErrorMsg[100];
+ WMMsgNodePtr pNode;
- XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg);
+ ErrorF("winSendMessageToWM %s\n", MessageName(pMsg));
#endif
- return 0;
-}
-
-/*
- * X message procedure IO error handler
- */
-
-static int
-winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay)
-{
- ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n");
-
- if (pthread_equal(pthread_self(), g_winMultiWindowXMsgProcThread)) {
- /* Restart at the main entry point */
- longjmp(g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
+ pNode = malloc(sizeof(WMMsgNodeRec));
+ if (pNode != NULL) {
+ memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec));
+ PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode);
}
-
- if (g_winMultiWindowXMsgProcOldIOErrorHandler)
- g_winMultiWindowXMsgProcOldIOErrorHandler(pDisplay);
-
- return 0;
}
/*
- * Catch RedirectError to detect other window manager running
+ * winMultiWindowThreadExit - Thread exit handler
*/
-static int
-winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr)
+static void
+winMultiWindowThreadExit(void *arg)
{
- redirectError = TRUE;
- return 0;
+ /* multiwindow client thread has exited, stop server as well */
+ raise(SIGTERM);
}
/*
@@ -1620,31 +1923,46 @@ winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr)
*/
static Bool
-CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen,
- Bool fAllowOtherWM)
+CheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen)
{
+ Bool redirectError = FALSE;
+
+ /* Get root window id */
+ xcb_screen_t *root_screen = xcb_aux_get_screen(conn, dwScreen);
+ xcb_window_t root_window_id = root_screen->root;
+
/*
Try to select the events which only one client at a time is allowed to select.
If this causes an error, another window manager is already running...
*/
- redirectError = FALSE;
- XSetErrorHandler(winRedirectErrorHandler);
- XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
- ResizeRedirectMask | SubstructureRedirectMask |
- ButtonPressMask);
- XSync(pDisplay, 0);
- XSetErrorHandler(winMultiWindowXMsgProcErrorHandler);
+ const static uint32_t test_mask[] = { XCB_EVENT_MASK_RESIZE_REDIRECT |
+ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
+ XCB_EVENT_MASK_BUTTON_PRESS };
+
+ xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(conn,
+ root_window_id,
+ XCB_CW_EVENT_MASK,
+ test_mask);
+ xcb_generic_error_t *error;
+ if ((error = xcb_request_check(conn, cookie)))
+ {
+ redirectError = TRUE;
+ free(error);
+ }
/*
Side effect: select the events we are actually interested in...
- If other WMs are not allowed, also select one of the events which only one client
+ Other WMs are not allowed, also select one of the events which only one client
at a time is allowed to select, so other window managers won't start...
*/
- XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen),
- SubstructureNotifyMask | (!fAllowOtherWM ? ButtonPressMask :
- 0));
- XSync(pDisplay, 0);
+ {
+ const uint32_t mask[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+ XCB_EVENT_MASK_BUTTON_PRESS };
+
+ xcb_change_window_attributes(conn, root_window_id, XCB_CW_EVENT_MASK, mask);
+ }
+
return redirectError;
}
@@ -1659,6 +1977,40 @@ winDeinitMultiWindowWM(void)
g_shutdown = TRUE;
}
+static void
+winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd)
+{
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_wm_hints_t hints;
+
+ cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, iWindow);
+ if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints, NULL)) {
+ FLASHWINFO fwi;
+
+ fwi.cbSize = sizeof(FLASHWINFO);
+ fwi.hwnd = hWnd;
+
+ winDebug("winApplyUrgency: window 0x%08x has urgency hint %s\n", iWindow,
+ (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) ? "on" : "off");
+
+ if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) {
+ 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);
+ }
+}
+
/* Windows window styles */
#define HINT_NOFRAME (1L<<0)
#define HINT_BORDER (1L<<1)
@@ -1673,18 +2025,19 @@ winDeinitMultiWindowWM(void)
#define HINT_MIN (1L<<1)
static void
-winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
+winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, Bool onCreate)
{
- static Atom windowState, motif_wm_hints, windowType;
- static Atom hiddenState, fullscreenState, belowState, aboveState,
+
+ xcb_connection_t *conn = pWMInfo->conn;
+ static xcb_atom_t windowState, motif_wm_hints;
+ static xcb_atom_t hiddenState, fullscreenState, belowState, aboveState,
skiptaskbarState;
- static Atom dockWindow;
+ static xcb_atom_t splashType;
static int generation;
- Atom type, *pAtom = NULL;
- int format;
- unsigned long hint = 0, maxmin = 0, nitems = 0, left = 0;
+
+ unsigned long hint = HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION;
+ unsigned long maxmin = 0;
unsigned long style, exStyle;
- MwmHints *mwm_hint = NULL;
if (!hWnd)
return;
@@ -1693,25 +2046,25 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
if (generation != serverGeneration) {
generation = serverGeneration;
- windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False);
- motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False);
- windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False);
- hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False);
- fullscreenState =
- XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False);
- belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False);
- aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False);
- dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False);
- skiptaskbarState =
- XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False);
+ windowState = intern_atom(conn, "_NET_WM_STATE");
+ motif_wm_hints = intern_atom(conn, "_MOTIF_WM_HINTS");
+ hiddenState = intern_atom(conn, "_NET_WM_STATE_HIDDEN");
+ fullscreenState = intern_atom(conn, "_NET_WM_STATE_FULLSCREEN");
+ belowState = intern_atom(conn, "_NET_WM_STATE_BELOW");
+ aboveState = intern_atom(conn, "_NET_WM_STATE_ABOVE");
+ skiptaskbarState = intern_atom(conn, "_NET_WM_STATE_SKIP_TASKBAR");
+ splashType = intern_atom(conn, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN");
}
- if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
- MAXINT, False, XA_ATOM, &type, &format,
- &nitems, &left,
- (unsigned char **) &pAtom) == Success) {
- if (pAtom ) {
- unsigned long i;
+ {
+ xcb_get_property_cookie_t cookie_wm_state = xcb_get_property(conn, FALSE, iWindow, windowState, XCB_ATOM_ATOM, 0L, INT_MAX);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie_wm_state, NULL);
+ if (reply) {
+ int i;
+ int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
+ xcb_atom_t *pAtom = xcb_get_property_value(reply);
+ Bool verMax = FALSE;
+ Bool horMax = FALSE;
for (i = 0; i < nitems; i++) {
if (pAtom[i] == skiptaskbarState)
@@ -1724,28 +2077,38 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
*zstyle = HWND_BOTTOM;
else if (pAtom[i] == aboveState)
*zstyle = HWND_TOPMOST;
+ if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT)
+ verMax = TRUE;
+ if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ)
+ horMax = TRUE;
}
- XFree(pAtom);
- }
+ if (verMax && horMax)
+ maxmin |= HINT_MAX;
+
+ free(reply);
+ }
}
- nitems = left = 0;
- if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L,
- PropMwmHintsElements, False, motif_wm_hints, &type,
- &format, &nitems, &left,
- (unsigned char **) &mwm_hint) == Success) {
- if (mwm_hint && nitems == PropMwmHintsElements &&
+ {
+ xcb_get_property_cookie_t cookie_mwm_hint = xcb_get_property(conn, FALSE, iWindow, motif_wm_hints, motif_wm_hints, 0L, sizeof(MwmHints));
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie_mwm_hint, NULL);
+ if (reply) {
+ int nitems = xcb_get_property_value_length(reply)/4;
+ MwmHints *mwm_hint = xcb_get_property_value(reply);
+ if (mwm_hint && (nitems >= PropMwmHintsElements) &&
(mwm_hint->flags & MwmHintsDecorations)) {
- if (!mwm_hint->decorations)
- hint |= HINT_NOFRAME;
+ if (!mwm_hint->decorations) {
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION);
+ hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
+ }
else if (!(mwm_hint->decorations & MwmDecorAll)) {
- if (mwm_hint->decorations & MwmDecorBorder)
- hint |= HINT_BORDER;
- if (mwm_hint->decorations & MwmDecorHandle)
- hint |= HINT_SIZEBOX;
- if (mwm_hint->decorations & MwmDecorTitle)
- hint |= HINT_CAPTION;
+ if (!(mwm_hint->decorations & MwmDecorBorder))
+ hint &= ~HINT_BORDER;
+ if (!(mwm_hint->decorations & MwmDecorHandle))
+ hint &= ~HINT_SIZEBOX;
+ if (!(mwm_hint->decorations & MwmDecorTitle))
+ hint &= ~HINT_CAPTION;
if (!(mwm_hint->decorations & MwmDecorMenu))
hint |= HINT_NOSYSMENU;
if (!(mwm_hint->decorations & MwmDecorMinimize))
@@ -1760,49 +2123,64 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
*/
}
}
- if (mwm_hint)
- XFree(mwm_hint);
+ free(reply);
+ }
}
- nitems = left = 0;
- pAtom = NULL;
- if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L,
- 1L, False, XA_ATOM, &type, &format,
- &nitems, &left,
- (unsigned char **) &pAtom) == Success) {
- if (pAtom && nitems == 1) {
- if (*pAtom == dockWindow) {
- hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */
+ {
+ int i;
+ xcb_ewmh_get_atoms_reply_t type;
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type(&pWMInfo->ewmh, iWindow);
+ if (xcb_ewmh_get_wm_window_type_reply(&pWMInfo->ewmh, cookie, &type, NULL)) {
+ for (i = 0; i < type.atoms_len; i++) {
+ if (type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK) {
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION | HINT_NOFRAME);
+ hint |= (HINT_SKIPTASKBAR | HINT_SIZEBOX);
+ *zstyle = HWND_TOPMOST;
+ }
+ else if ((type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH)
+ || (type.atoms[i] == splashType)) {
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION);
+ hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
*zstyle = HWND_TOPMOST;
}
}
- if (pAtom)
- XFree(pAtom);
+ }
}
{
- XSizeHints *normal_hint = XAllocSizeHints();
- long supplied;
-
- if (normal_hint &&
- (XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied) ==
- Success)) {
- if (normal_hint->flags & PMaxSize) {
- /* Not maximizable if a maximum size is specified */
- hint |= HINT_NOMAXIMIZE;
+ xcb_size_hints_t size_hints;
+ xcb_get_property_cookie_t cookie;
+
+ cookie = xcb_icccm_get_wm_normal_hints(conn, iWindow);
+ if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &size_hints, NULL)) {
+ /* Notwithstanding MwmDecorHandle, if we have a border, and
+ WM_NORMAL_HINTS indicates the window should be resizeable, let
+ the window have a resizing border. This is necessary for windows
+ with gtk3+ 3.14 csd. */
+ if (hint & HINT_BORDER)
+ hint |= HINT_SIZEBOX;
+
+ if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) {
+ /* Not maximizable if a maximum size is specified, and that size
+ is smaller (in either dimension) than the screen size */
+ if ((size_hints.max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN))
+ || (size_hints.max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN)))
+ hint |= HINT_NOMAXIMIZE;
- if (normal_hint->flags & PMinSize) {
+ if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
/*
If both minimum size and maximum size are specified and are the same,
don't bother with a resizing frame
*/
- if ((normal_hint->min_width == normal_hint->max_width)
- && (normal_hint->min_height == normal_hint->max_height))
+ if ((size_hints.min_width == size_hints.max_width)
+ && (size_hints.min_height == size_hints.max_height)) {
+ hint |= HINT_NOMAXIMIZE;
hint = (hint & ~HINT_SIZEBOX);
+ }
}
}
}
- XFree(normal_hint);
}
/*
@@ -1810,41 +2188,38 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
application id for grouping.
*/
{
- XClassHint class_hint = { 0, 0 };
- char *window_name = 0;
char *application_id = 0;
+ char *window_name = 0;
+ char *res_name = 0;
+ char *res_class = 0;
- if (XGetClassHint(pDisplay, iWindow, &class_hint)) {
- XFetchName(pDisplay, iWindow, &window_name);
+ GetClassNames(pWMInfo, iWindow, &res_name, &res_class, &window_name);
- style =
- winOverrideStyle(class_hint.res_name, class_hint.res_class,
- window_name);
+ style = STYLE_NONE;
+ style = winOverrideStyle(res_name, res_class, window_name);
+ /*
+ It only makes sense to apply minimize/maximize override when the
+ window is mapped, as otherwise the state can't be changed.
+ */
+ if (!onCreate)
+ style &= ~(STYLE_MAXIMIZE | STYLE_MINIMIZE);
#define APPLICATION_ID_FORMAT "%s.xwin.%s"
#define APPLICATION_ID_UNKNOWN "unknown"
- if (class_hint.res_class) {
- asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
- class_hint.res_class);
- }
- else {
- asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
- APPLICATION_ID_UNKNOWN);
- }
- winSetAppUserModelID(hWnd, application_id);
-
- if (class_hint.res_name)
- XFree(class_hint.res_name);
- if (class_hint.res_class)
- XFree(class_hint.res_class);
- if (application_id)
- free(application_id);
- if (window_name)
- XFree(window_name);
+ if (res_class) {
+ asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
+ res_class);
}
else {
- style = STYLE_NONE;
+ asprintf(&application_id, APPLICATION_ID_FORMAT, XVENDORNAME,
+ APPLICATION_ID_UNKNOWN);
}
+ winSetAppUserModelID(hWnd, application_id);
+
+ free(application_id);
+ free(res_name);
+ free(res_class);
+ free(window_name);
}
if (style & STYLE_TOPMOST)
@@ -1874,6 +2249,9 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
(hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) |
HINT_NOFRAME;
+ if (style & STYLE_SKIPTASKBAR)
+ hint |= HINT_SKIPTASKBAR;
+
/* Now apply styles to window */
style = GetWindowLongPtr(hWnd, GWL_STYLE);
if (!style)
@@ -1881,6 +2259,11 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
+ if (GetParent(hWnd))
+ style |= WS_SYSMENU;
+ else
+ style |= WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
+
if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */
style = style | WS_CAPTION | WS_SIZEBOX;
else if (hint & HINT_NOFRAME) /* No frame, no decorations */
@@ -1915,57 +2298,3 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n",
iWindow, hint, style, exStyle);
}
-
-void
-winUpdateWindowPosition(HWND hWnd, HWND * zstyle)
-{
- int iX, iY, iWidth, iHeight;
- int iDx, iDy;
- RECT rcNew;
- WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
- DrawablePtr pDraw = NULL;
-
- if (!pWin)
- return;
- pDraw = &pWin->drawable;
- if (!pDraw)
- return;
-
- /* Get the X and Y location of the X window */
- iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
-
- /* Get the height and width of the X window */
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* Setup a rectangle with the X window position and size */
- SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
-
- winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
- GetWindowLongPtr(hWnd, GWL_EXSTYLE));
-
- /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
- if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
- iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
- rcNew.left += iDx;
- rcNew.right += iDx;
- }
-
- if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
- iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
- rcNew.top += iDy;
- rcNew.bottom += iDy;
- }
-
- winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- /* Position the Windows window */
- SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
-
-}
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 656f6c2da..6f3291175 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -41,6 +41,7 @@
#include "winprefs.h"
#include "winmsg.h"
#include "inputstr.h"
+#include "wmutil/keyboard.h"
extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
@@ -294,6 +295,31 @@ winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
MOUSE_POLLING_INTERVAL, NULL);
}
+static
+void
+winAdjustXWindowState(winPrivScreenPtr s_pScreenPriv, winWMMessageRec *wmMsg)
+{
+ wmMsg->msg = WM_WM_CHANGE_STATE;
+ if (IsIconic(wmMsg->hwndWindow)) {
+ wmMsg->dwID = 3; // IconicState
+ winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg);
+ }
+ else if (IsZoomed(wmMsg->hwndWindow)) {
+ wmMsg->dwID = 2; // ZoomState
+ winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg);
+ }
+ else if (IsWindowVisible(wmMsg->hwndWindow)) {
+ wmMsg->dwID = 1; // NormalState
+ winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg);
+ }
+ else {
+ /* Only the client, not the user can Withdraw windows, so it doesn't make
+ much sense to handle that state here, and anything else is an
+ unanticapted state. */
+ ErrorF("winAdjustXWindowState - Unknown state for %p\n", wmMsg->hwndWindow);
+ }
+}
+
/*
* winTopLevelWindowProc - Window procedure for all top-level Windows windows.
*/
@@ -302,7 +328,6 @@ LRESULT CALLBACK
winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
POINT ptMouse;
- HDC hdcUpdate;
PAINTSTRUCT ps;
WindowPtr pWin = NULL;
winPrivWinPtr pWinPriv = NULL;
@@ -457,18 +482,9 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_PAINT:
/* Only paint if our window handle is valid */
- if (hwndScreen == NULL)
+ if (hwnd == NULL)
break;
- /* BeginPaint gives us an hdc that clips to the invalidated region */
- hdcUpdate = BeginPaint(hwnd, &ps);
- /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
- if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
- ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
- EndPaint(hwnd, &ps);
- return 0;
- }
-
#ifdef XWIN_GLX_WINDOWS
if (pWinPriv->fWglUsed) {
/*
@@ -478,36 +494,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
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...
*/
+ BeginPaint(hwnd, &ps);
ValidateRect(hwnd, &(ps.rcPaint));
+ EndPaint(hwnd, &ps);
}
else
#endif
- /* Try to copy from the shadow buffer */
- if (!BitBlt(hdcUpdate,
- ps.rcPaint.left, ps.rcPaint.top,
- ps.rcPaint.right - ps.rcPaint.left,
- ps.rcPaint.bottom - ps.rcPaint.top,
- s_pScreenPriv->hdcShadow,
- ps.rcPaint.left + pWin->drawable.x,
- ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
- 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("winTopLevelWindowProc - BitBlt failed: %s\n",
- (LPSTR) lpMsgBuf);
- LocalFree(lpMsgBuf);
- }
+ /* Call the engine dependent repainter */
+ if (*s_pScreenPriv->pwinBltExposedWindowRegion)
+ (*s_pScreenPriv->pwinBltExposedWindowRegion) (s_pScreen, pWin);
- /* EndPaint frees the DC */
- EndPaint(hwnd, &ps);
return 0;
case WM_MOUSEMOVE:
@@ -868,6 +864,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
RemoveProp(hwnd, WIN_WINDOW_PROP);
RemoveProp(hwnd, WIN_WID_PROP);
RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
+ RemoveProp(hwnd, WIN_STATE_PROP);
break;
@@ -878,77 +875,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* else: Wait for WM_EXITSIZEMOVE */
return 0;
- case WM_SHOWWINDOW:
- /* Bail out if the window is being hidden */
- if (!wParam)
- return 0;
-
- /* */
- if (!pWin->overrideRedirect) {
- HWND zstyle = HWND_NOTOPMOST;
-
- /* Flag that this window needs to be made active when clicked */
- SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
-
- /* Set the transient style flags */
- if (GetParent(hwnd))
- SetWindowLongPtr(hwnd, GWL_STYLE,
- WS_POPUP | WS_OVERLAPPED | WS_SYSMENU |
- WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- /* Set the window standard style flags */
- else
- SetWindowLongPtr(hwnd, GWL_STYLE,
- (WS_POPUP | WS_OVERLAPPEDWINDOW |
- WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
- & ~WS_CAPTION & ~WS_SIZEBOX);
-
- winUpdateWindowPosition(hwnd, &zstyle);
-
- {
- WinXWMHints hints;
-
- if (winMultiWindowGetWMHints(pWin, &hints)) {
- /*
- Give the window focus, unless it has an InputHint
- which is FALSE (this is used by e.g. glean to
- avoid every test window grabbing the focus)
- */
- if (!((hints.flags & InputHint) && (!hints.input))) {
- SetForegroundWindow(hwnd);
- }
- }
- }
- wmMsg.msg = WM_WM_MAP3;
- }
- else { /* It is an overridden window so make it top of Z stack */
-
- HWND forHwnd = GetForegroundWindow();
-
-#if CYGWINDOWING_DEBUG
- ErrorF("overridden window is shown\n");
-#endif
- if (forHwnd != NULL) {
- if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
- XMING_SIGNATURE) {
- if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
- SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- else
- SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- }
- }
- wmMsg.msg = WM_WM_MAP2;
- }
-
- /* Tell our Window Manager thread to map the window */
- if (fWMMsgInitialized)
- winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
-
- winStartMousePolling(s_pScreenPriv);
-
- return 0;
-
case WM_SIZING:
/* Need to legalize the size according to WM_NORMAL_HINTS */
/* for applications like xterm */
@@ -1001,12 +927,75 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
}
}
+
+ /* Window is being shown */
+ if (pWinPos->flags & SWP_SHOWWINDOW) {
+ if (!pWin->overrideRedirect) {
+ HWND zstyle = HWND_NOTOPMOST;
+
+ /* Flag that this window needs to be made active when clicked */
+ SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
+
+ winUpdateWindowPosition(hwnd, &zstyle);
+
+ {
+ WinXWMHints hints;
+
+ if (winMultiWindowGetWMHints(pWin, &hints)) {
+ /*
+ Give the window focus, unless it has an InputHint
+ which is FALSE (this is used by e.g. glean to
+ avoid every test window grabbing the focus)
+ */
+ if (!((hints.flags & InputHint) && (!hints.input))) {
+ SetForegroundWindow(hwnd);
+ }
+ }
+ }
+ wmMsg.msg = WM_WM_MAP_MANAGED;
+ }
+ else { /* It is an overridden window so make it top of Z stack */
+ HWND forHwnd = GetForegroundWindow();
+
+ if (forHwnd != NULL) {
+ if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
+ XMING_SIGNATURE) {
+ if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ else
+ SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ }
+ wmMsg.msg = WM_WM_MAP_UNMANAGED;
+ }
+
+ /* Tell our Window Manager thread to map the window */
+ if (fWMMsgInitialized)
+ winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
+
+ winStartMousePolling(s_pScreenPriv);
+ }
+
+ /*
+ We don't react to SWP_HIDEWINDOW indicating window is being hidden in
+ a symmetrical way (i.e. by sending WM_WM_UNMAP)
+
+ If the cause of the window being hidden is the X windows being unmapped,
+ (WM_STATE has changed to WithdrawnState), then the window has already
+ been unmapped.
+
+ Virtual desktop software (like VirtuaWin or Dexpot) uses SWP_HIDEWINDOW
+ to hide windows on other desktops. We mustn't unmap the X window in
+ that situation, as it becomes inaccessible.
+ */
}
- /*
- * Pass the message to DefWindowProc to let the function
- * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
- */
- break;
+ /*
+ * Pass the message to DefWindowProc to let the function
+ * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
+ */
+ break;
case WM_ENTERSIZEMOVE:
hasEnteredSizeMove = TRUE;
@@ -1016,6 +1005,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Adjust the X Window to the moved Windows window */
hasEnteredSizeMove = FALSE;
winAdjustXWindow(pWin, hwnd);
+ if (fWMMsgInitialized)
+ winAdjustXWindowState(s_pScreenPriv, &wmMsg);
return 0;
case WM_SIZE:
@@ -1044,6 +1035,10 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!hasEnteredSizeMove) {
/* Adjust the X Window to the moved Windows window */
winAdjustXWindow(pWin, hwnd);
+ if (fWMMsgInitialized)
+ winAdjustXWindowState(s_pScreenPriv, &wmMsg);
+ if (wParam == SIZE_MINIMIZED)
+ winReorderWindowsMultiWindow();
}
/* else: wait for WM_EXITSIZEMOVE */
return 0; /* end of WM_SIZE handler */
@@ -1155,3 +1150,93 @@ 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;
+ BeginPaint(hwnd, &ps);
+ ValidateRect(hwnd, &(ps.rcPaint));
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+ /* XXX: this is exactly what DefWindowProc does? */
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+void
+winUpdateWindowPosition(HWND hWnd, HWND * zstyle)
+{
+ int iX, iY, iWidth, iHeight;
+ int iDx, iDy;
+ RECT rcNew;
+ WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
+ DrawablePtr pDraw = NULL;
+
+ if (!pWin)
+ return;
+ pDraw = &pWin->drawable;
+ if (!pDraw)
+ return;
+
+ /* Get the X and Y location of the X window */
+ iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ /* Get the height and width of the X window */
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Setup a rectangle with the X window position and size */
+ SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
+
+ winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
+ rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
+
+ AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
+ GetWindowLongPtr(hWnd, GWL_EXSTYLE));
+
+ /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
+ if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
+ iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
+ rcNew.left += iDx;
+ rcNew.right += iDx;
+ }
+
+ if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
+ iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
+ rcNew.top += iDy;
+ rcNew.bottom += iDy;
+ }
+
+ winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
+ rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
+
+ /* Position the Windows window */
+ SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
+ rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
+
+}
diff --git a/hw/xwin/winos.c b/hw/xwin/winos.c
index 0d825bb83..4e72daa7f 100644
--- a/hw/xwin/winos.c
+++ b/hw/xwin/winos.c
@@ -37,19 +37,27 @@ static const char*
IsWow64(void)
{
#ifdef __x86_64__
- return " (64-bit)";
+ return " (Win64)";
#else
- WINBOOL bIsWow64;
+ /* Check if we are running under WoW64 */
LPFN_ISWOW64PROCESS fnIsWow64Process =
(LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")),
"IsWow64Process");
if (NULL != fnIsWow64Process) {
- if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
- return bIsWow64 ? " (WoW64)" : " (32-bit)";
- }
+ WINBOOL bIsWow64 = FALSE;
- /* OS doesn't support IsWow64Process() */
- return "";
+ if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) {
+ return bIsWow64 ? " (WoW64)" : " (Win32)";
+ }
+ else {
+ /* IsWow64Process() failed */
+ return " (Unknown)";
+ }
+ }
+ else {
+ /* OS doesn't support IsWow64Process() */
+ return "";
+ }
#endif
}
@@ -61,12 +69,89 @@ void
winOS(void)
{
OSVERSIONINFOEX osvi = {0};
+ const char *windowstype = "Unknown";
+ const char *prodName = "Unknown";
+ const char *isWow = "Unknown";
/* Get operating system version information */
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx((LPOSVERSIONINFO)&osvi);
- ErrorF("OS: Windows NT %d.%d build %d%s\n",
- (int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion,
- (int)osvi.dwBuildNumber, IsWow64());
+ /* 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 == 10) {
+ if (osvi.dwMinorVersion == 0) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 10";
+ else
+ prodName = "Windows Server 2016";
+ }
+ }
+ else if (osvi.dwMajorVersion == 6) {
+ if (osvi.dwMinorVersion == 4) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 10";
+ else
+ prodName = "Windows Server 2016";
+ }
+ if (osvi.dwMinorVersion == 3) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 8.1";
+ else
+ prodName = "Windows Server 2012 R2";
+ }
+ if (osvi.dwMinorVersion == 2) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 8";
+ else
+ prodName = "Windows Server 2012";
+ }
+ else if (osvi.dwMinorVersion == 1) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows 7";
+ else
+ prodName = "Windows Server 2008 R2";
+ }
+ else if (osvi.dwMinorVersion == 0) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows Vista";
+ else
+ prodName = "Windows Server 2008";
+ }
+ }
+ else if (osvi.dwMajorVersion == 5) {
+ if (osvi.dwMinorVersion == 2) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ prodName = "Windows XP x64 Edition";
+ else if (GetSystemMetrics(SM_SERVERR2))
+ prodName = "Windows Server 2003 R2";
+ else
+ prodName = "Windows Server 2003";
+ }
+ else if (osvi.dwMinorVersion == 1)
+ prodName = "Windows XP";
+ else if (osvi.dwMinorVersion == 0) {
+ prodName = "Windows 2000";
+ break;
+ }
+ }
+
+ break;
+
+ case VER_PLATFORM_WIN32_WINDOWS:
+ windowstype = "Windows";
+ break;
+ }
+
+ isWow = IsWow64();
+
+ ErrorF("OS: %s %s [%s %d.%d build %d]%s\n",
+ prodName, osvi.szCSDVersion,
+ windowstype, (int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion,
+ (int)osvi.dwBuildNumber, isWow);
}
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c
index 505292714..4d53f8a79 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"
@@ -46,6 +48,7 @@
#include "winprefs.h"
#include "windisplay.h"
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
/* Where will the custom menu commands start counting from? */
#define STARTMENUID WM_USER
@@ -297,6 +300,110 @@ HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu)
}
+#ifdef __CYGWIN__
+static void
+LogLineFromFd(int fd, const char *fdname, int pid)
+{
+#define BUFSIZE 512 /* must be less than internal buffer size used in LogVWrite */
+ char buf[BUFSIZE];
+ char *bufptr = buf;
+
+ /* read from fd until eof, newline or our buffer is full */
+ while ((read(fd, bufptr, 1) > 0) && (bufptr < &(buf[BUFSIZE - 1]))) {
+ if (*bufptr == '\n')
+ break;
+ bufptr++;
+ }
+
+ /* null terminate and log */
+ *bufptr = 0;
+ if (strlen(buf))
+ ErrorF("(pid %d %s) %s\n", pid, fdname, buf);
+}
+
+static void *
+ExecAndLogThread(void *cmd)
+{
+ int pid;
+ int stdout_filedes[2];
+ int stderr_filedes[2];
+ int status;
+
+ /* Create a pair of pipes */
+ pipe(stdout_filedes);
+ pipe(stderr_filedes);
+
+ switch (pid = fork()) {
+ case 0: /* child */
+ {
+ struct rlimit rl;
+ unsigned int fd;
+
+ /* dup write end of pipes onto stderr and stdout */
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ dup2(stdout_filedes[1], STDOUT_FILENO);
+ dup2(stderr_filedes[1], STDERR_FILENO);
+
+ /* Close any open descriptors except for STD* */
+ getrlimit(RLIMIT_NOFILE, &rl);
+ for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
+ close(fd);
+
+ /* Disassociate any TTYs */
+ setsid();
+
+ execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
+ perror("execl failed");
+ exit(127);
+ }
+ break;
+
+ default: /* parent */
+ {
+ close(stdout_filedes[1]);
+ close(stderr_filedes[1]);
+
+ ErrorF("executing '%s', pid %d\n", (char *) cmd, pid);
+
+ /* read from pipes, write to log, until both are closed */
+ while (TRUE) {
+ fd_set readfds, errorfds;
+ int nfds = max(stdout_filedes[0], stderr_filedes[0]) + 1;
+
+ FD_ZERO(&readfds);
+ FD_SET(stdout_filedes[0], &readfds);
+ FD_SET(stderr_filedes[0], &readfds);
+ errorfds = readfds;
+
+ if (select(nfds, &readfds, NULL, &errorfds, NULL) > 0) {
+ if (FD_ISSET(stdout_filedes[0], &readfds))
+ LogLineFromFd(stdout_filedes[0], "stdout", pid);
+ if (FD_ISSET(stderr_filedes[0], &readfds))
+ LogLineFromFd(stderr_filedes[0], "stderr", pid);
+
+ if (FD_ISSET(stdout_filedes[0], &errorfds) &&
+ FD_ISSET(stderr_filedes[0], &errorfds))
+ break;
+ }
+ else {
+ break;
+ }
+ }
+
+ waitpid(pid, &status, 0);
+ }
+ break;
+
+ case -1: /* error */
+ ErrorF("fork() to run command failed\n");
+ }
+
+ return (void *) (intptr_t) status;
+}
+#endif
+
/*
* Searches for the custom WM_COMMAND command ID and performs action.
* Return TRUE if command is proccessed, FALSE otherwise.
@@ -319,24 +426,17 @@ HandleCustomWM_COMMAND(HWND hwnd, int command)
switch (m->menuItem[j].cmd) {
#ifdef __CYGWIN__
case CMD_EXEC:
- if (fork() == 0) {
- struct rlimit rl;
- int fd;
-
- /* Close any open descriptors except for STD* */
- getrlimit(RLIMIT_NOFILE, &rl);
- for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
- close(fd);
-
- /* Disassociate any TTYs */
- setsid();
+ {
+ pthread_t t;
- execl("/bin/sh",
- "/bin/sh", "-c", m->menuItem[j].param, NULL);
- exit(0);
- }
+ if (!pthread_create
+ (&t, NULL, ExecAndLogThread, m->menuItem[j].param))
+ pthread_detach(t);
else
- return TRUE;
+ ErrorF
+ ("Creating command output logging thread failed\n");
+ }
+ return TRUE;
break;
#else
case CMD_EXEC:
@@ -637,11 +737,17 @@ winPrefsLoadPreferences(const 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
@@ -672,7 +778,7 @@ LoadPreferences(void)
char *home;
char fname[PATH_MAX + NAME_MAX + 2];
char szDisplay[512];
- char *szEnvDisplay;
+ char *szEnvDisplay, *szEnvLogFile;
int i, j;
char param[PARAM_MAX + 1];
char *srcParam, *dstParam;
@@ -720,6 +826,11 @@ LoadPreferences(void)
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 */
for (i = 0; i < pref.menuItems; i++) {
for (j = 0; j < pref.menu[i].menuItems; j++) {
diff --git a/hw/xwin/winprefs.h b/hw/xwin/winprefs.h
index 8f4eb0807..c41710419 100644
--- a/hw/xwin/winprefs.h
+++ b/hw/xwin/winprefs.h
@@ -34,9 +34,6 @@
/* Need Bool */
#include <X11/Xdefs.h>
-/* Need TRUE */
-#include "misc.h"
-
/* Need to know how long paths can be... */
#include <limits.h>
/* Xwindows redefines PATH_MAX to at least 1024 */
@@ -65,6 +62,7 @@ typedef enum MENUCOMMANDTYPE {
#define STYLE_MAXIMIZE (1L<<4) /* Open a window maximized */
#define STYLE_MINIMIZE (1L<<5) /* Open a window minimized */
#define STYLE_BOTTOM (1L<<6) /* Open a window at the bottom of the Z order */
+#define STYLE_SKIPTASKBAR (1L<<7) /* Omit from taskbar */
/* Where to place a system menu */
typedef enum MENUPOSITION {
diff --git a/hw/xwin/winprefslex.l b/hw/xwin/winprefslex.l
index 9e6f0d6d4..e7547729c 100644
--- a/hw/xwin/winprefslex.l
+++ b/hw/xwin/winprefslex.l
@@ -77,6 +77,7 @@ BOTTOM { return BOTTOM; }
NOTITLE { return NOTITLE; }
OUTLINE { return OUTLINE; }
NOFRAME { return NOFRAME; }
+SKIPTASKBAR { return SKIPTASKBAR; }
ROOTMENU { return ROOTMENU; }
DEFAULTSYSMENU { return DEFAULTSYSMENU; }
SYSMENU { return SYSMENU; }
@@ -90,6 +91,12 @@ RELOAD { return RELOAD; }
TRAYICON { return TRAYICON; }
FORCEEXIT { return FORCEEXIT; }
SILENTEXIT { return SILENTEXIT; }
+DPI { return DPI; }
+XKBLAYOUT { return XKBLAYOUT; }
+XKBMODEL { return XKBMODEL; }
+XKBOPTIONS { return XKBOPTIONS; }
+XKBRULES { return XKBRULES; }
+XKBVARIANT { return XKBVARIANT; }
"{" { return LB; }
"}" { return RB; }
"\""[^\"\r\n]+"\"" { yylval.sVal = makestr(yytext+1); \
diff --git a/hw/xwin/winprefsyacc.y b/hw/xwin/winprefsyacc.y
index 9bb28ae92..e4e305a0f 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);
@@ -108,6 +117,7 @@ extern int yylex(void);
%token NOTITLE
%token OUTLINE
%token NOFRAME
+%token SKIPTASKBAR
%token DEFAULTSYSMENU
%token SYSMENU
%token ROOTMENU
@@ -121,10 +131,17 @@ 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
%type <uVal> group2
+%type <uVal> group3
%type <uVal> stylecombo
%type <iVal> atspot
@@ -155,6 +172,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); }
@@ -207,10 +248,24 @@ group2: NOTITLE { $$=STYLE_NOTITLE; }
| NOFRAME { $$=STYLE_NOFRAME; }
;
+group3: SKIPTASKBAR { $$=STYLE_SKIPTASKBAR; }
+ ;
+
stylecombo: group1 { $$=$1; }
| group2 { $$=$1; }
+ | group3 { $$=$1; }
| group1 group2 { $$=$1|$2; }
+ | group1 group3 { $$=$1|$2; }
| group2 group1 { $$=$1|$2; }
+ | group2 group3 { $$=$1|$2; }
+ | group3 group1 { $$=$1|$2; }
+ | group3 group2 { $$=$1|$2; }
+ | group1 group2 group3 { $$=$1|$2|$3; }
+ | group1 group3 group2 { $$=$1|$2|$3; }
+ | group2 group1 group3 { $$=$1|$2|$3; }
+ | group2 group3 group1 { $$=$1|$2|$3; }
+ | group3 group1 group2 { $$=$1|$2|$3; }
+ | group3 group2 group1 { $$=$1|$2|$3; }
;
styleline: STRING stylecombo NEWLINE newline_or_nada { AddStyleLine($1, $2); free($1); }
@@ -259,6 +314,58 @@ yyerror (const 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 73aa027d8..4f6275be1 100644
--- a/hw/xwin/winprocarg.c
+++ b/hw/xwin/winprocarg.c
@@ -130,18 +130,18 @@ winInitializeScreenDefaults(void)
defaultScreenInfo.fDecoration = TRUE;
#ifdef XWIN_MULTIWINDOWEXTWM
defaultScreenInfo.fMWExtWM = FALSE;
- defaultScreenInfo.fInternalWM = FALSE;
#endif
defaultScreenInfo.fRootless = FALSE;
#ifdef XWIN_MULTIWINDOW
defaultScreenInfo.fMultiWindow = FALSE;
+ defaultScreenInfo.fCompositeWM = FALSE;
#endif
#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
defaultScreenInfo.fMultiMonitorOverride = FALSE;
#endif
defaultScreenInfo.fMultipleMonitors = FALSE;
defaultScreenInfo.fLessPointer = FALSE;
- defaultScreenInfo.iResizeMode = resizeWithRandr;
+ defaultScreenInfo.iResizeMode = resizeDefault;
defaultScreenInfo.fNoTrayIcon = FALSE;
defaultScreenInfo.iE3BTimeout = WIN_E3B_DEFAULT;
defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL;
@@ -247,7 +247,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
* OsVendorInit () gets called, otherwise we will overwrite
* settings changed by parameters such as -fullscreen, etc.
*/
- winErrorFVerb(2, "ddxProcessArgument - Initializing default "
+ winErrorFVerb(3, "ddxProcessArgument - Initializing default "
"screens\n");
winInitializeScreenDefaults();
}
@@ -292,6 +292,9 @@ ddxProcessArgument(int argc, char *argv[], int i)
/* Display the usage message if the argument is malformed */
if (i + 1 >= argc) {
+ ErrorF("ddxProcessArgument - screen - Missing screen number\n");
+ UseMsg();
+ FatalError("-screen missing screen number\n");
return 0;
}
@@ -577,11 +580,8 @@ ddxProcessArgument(int argc, char *argv[], int i)
* Look for the '-internalwm' argument
*/
if (IS_OPTION("-internalwm")) {
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = TRUE;
- screenInfoPtr->fMWExtWM = TRUE;
- screenInfoPtr->fInternalWM = TRUE;
-
+ ErrorF("Ignoring obsolete -internalwm option\n");
+ /* Ignored, but we still accept the arg for backwards compatibility */
/* Indicate that we have processed this argument */
return 1;
}
@@ -615,6 +615,16 @@ ddxProcessArgument(int argc, char *argv[], int i)
/* Indicate that we have processed this argument */
return 1;
}
+
+ /*
+ * Look for the '-compositewm' argument
+ */
+ if (IS_OPTION("-compositewm")) {
+ screenInfoPtr->fCompositeWM = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
#endif
/*
@@ -666,7 +676,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
if (IS_OPTION("-resize"))
mode = resizeWithRandr;
else if (IS_OPTION("-noresize"))
- mode = notAllowed;
+ mode = resizeNotAllowed;
else if (strncmp(argv[i], "-resize=", strlen("-resize=")) == 0) {
char *option = argv[i] + strlen("-resize=");
@@ -675,7 +685,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
else if (strcmp(option, "scrollbars") == 0)
mode = resizeWithScrollbars;
else if (strcmp(option, "none") == 0)
- mode = notAllowed;
+ mode = resizeNotAllowed;
else {
ErrorF("ddxProcessArgument - resize - Invalid resize mode %s\n",
option);
@@ -957,6 +967,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")
@@ -1011,9 +1029,6 @@ ddxProcessArgument(int argc, char *argv[], int i)
if (IS_OPTION("-logfile")) {
CHECK_ARGS(1);
g_pszLogFile = argv[++i];
-#ifdef RELOCATE_PROJECTROOT
- g_fLogFileChanged = TRUE;
-#endif
return 2;
}
@@ -1203,6 +1218,5 @@ winLogVersionInfo(void)
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 f4ba054bc..1b28e5223 100644
--- a/hw/xwin/winrandr.c
+++ b/hw/xwin/winrandr.c
@@ -34,11 +34,6 @@
#include <xwin-config.h>
#endif
#include "win.h"
-#include "mivalidate.h" // for union _Validate used by windowstr.h
-
-#ifndef RANDR_12_INTERFACE
-#error X server must have RandR 1.2 interface
-#endif
/*
* Answer queries about the RandR features supported.
@@ -47,17 +42,47 @@
static Bool
winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations)
{
+ rrScrPrivPtr pRRScrPriv;
+ RROutputPtr output;
+
+ pRRScrPriv = rrGetScrPriv(pScreen);
+ output = pRRScrPriv->outputs[0];
+
winDebug("winRandRGetInfo ()\n");
/* Don't support rotations */
*pRotations = RR_Rotate_0;
- /*
- The screen doesn't have to be limited to the actual
- monitor size (we can have scrollbars :-), so what is
- the upper limit?
- */
- RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096);
+ /* Delete previous mode */
+ if (output->modes[0])
+ {
+ RRModeDestroy(output->modes[0]);
+ RRModeDestroy(output->crtc->mode);
+ }
+
+ /* Register current mode */
+ {
+ xRRModeInfo modeInfo;
+ RRModePtr mode;
+ char name[100];
+
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ snprintf(name, sizeof(name), "%dx%d", pScreen->width, pScreen->height);
+
+ modeInfo.width = pScreen->width;
+ modeInfo.height = pScreen->height;
+ modeInfo.hTotal = pScreen->width;
+ modeInfo.vTotal = pScreen->height;
+ modeInfo.dotClock = 0;
+ modeInfo.nameLength = strlen(name);
+ mode = RRModeGet(&modeInfo, name);
+
+ output->modes[0] = mode;
+ output->numModes = 1;
+
+ mode = RRModeGet(&modeInfo, name);
+ output->crtc->mode = mode;
+ }
return TRUE;
}
@@ -74,6 +99,11 @@ winDoRandRScreenSetSize(ScreenPtr pScreen,
winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
WindowPtr pRoot = pScreen->root;
+ /* Ignore changes which do nothing */
+ if ((pScreen->width == width) && (pScreen->height == height) &&
+ (pScreen->mmWidth == mmWidth) && (pScreen->mmHeight == mmHeight))
+ return;
+
// Prevent screen updates while we change things around
SetRootClip(pScreen, FALSE);
@@ -214,5 +244,45 @@ winRandRInit(ScreenPtr pScreen)
pRRScrPriv->rrCrtcSet = NULL;
pRRScrPriv->rrCrtcSetGamma = NULL;
+ /* Create a CRTC and an output for the screen, and hook them together */
+ {
+ RRCrtcPtr crtc;
+ RROutputPtr output;
+
+ crtc = RRCrtcCreate(pScreen, NULL);
+ if (!crtc)
+ return FALSE;
+
+ crtc->rotations = RR_Rotate_0;
+
+ output = RROutputCreate(pScreen, "default", 7, NULL);
+ if (!output)
+ return FALSE;
+
+ RROutputSetCrtcs(output, &crtc, 1);
+ RROutputSetConnection(output, RR_Connected);
+ RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen));
+
+ output->crtc = crtc;
+
+ /* Set crtc outputs (should use RRCrtcNotify?) */
+ crtc->outputs = malloc(sizeof(RROutputPtr));
+ crtc->outputs[0] = output;
+ crtc->numOutputs = 1;
+
+ pRRScrPriv->primaryOutput = output;
+
+ /* Ensure we have space for exactly one mode */
+ output->modes = malloc(sizeof(RRModePtr));
+ output->modes[0] = NULL;
+ }
+
+ /*
+ The screen doesn't have to be limited to the actual
+ monitor size (we can have scrollbars :-), so what is
+ the upper limit?
+ */
+ RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096);
+
return TRUE;
}
diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c
index 735ce9325..b839eaf1c 100644
--- a/hw/xwin/winscrinit.c
+++ b/hw/xwin/winscrinit.c
@@ -534,10 +534,12 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
#ifdef XWIN_MULTIWINDOW
|| pScreenInfo->fMultiWindow
#endif
-#ifdef XWIN_MULTIWINDOWEXTWM
- || pScreenInfo->fInternalWM
-#endif
) {
+ if ((pScreenInfo->dwBPP == 8) && (pScreenInfo->fCompositeWM)) {
+ ErrorF("-compositewm disabled due to 8bpp depth\n");
+ pScreenInfo->fCompositeWM = FALSE;
+ }
+
#if CYGDEBUG || YES
winDebug("winFinishScreenInitFB - Calling winInitWM.\n");
#endif
@@ -547,11 +549,9 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
&pScreenPriv->ptWMProc,
&pScreenPriv->ptXMsgProc,
&pScreenPriv->pmServerStarted,
- pScreenInfo->dwScreen, (HWND) &pScreenPriv->hwndScreen,
-#ifdef XWIN_MULTIWINDOWEXTWM
- pScreenInfo->fInternalWM ||
-#endif
- FALSE)) {
+ pScreenInfo->dwScreen,
+ (HWND) &pScreenPriv->hwndScreen,
+ pScreenInfo->fCompositeWM)) {
ErrorF("winFinishScreenInitFB - winInitWM () failed.\n");
return FALSE;
}
diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c
index d4f940ec1..9481ecb42 100644
--- a/hw/xwin/winshadddnl.c
+++ b/hw/xwin/winshadddnl.c
@@ -1203,6 +1203,7 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen)
pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
+ pScreenPriv->pwinBltExposedWindowRegion = NULL;
pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
pScreenPriv->pwinRealizeInstalledPalette
@@ -1211,14 +1212,8 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen)
pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
- pScreenPriv->pwinHotKeyAltTab =
- (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA;
pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow
- = (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA;
-#endif
return TRUE;
}
diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c
index bf655174d..797152f13 100644
--- a/hw/xwin/winshadgdi.c
+++ b/hw/xwin/winshadgdi.c
@@ -62,6 +62,9 @@ static Bool
winBltExposedRegionsShadowGDI(ScreenPtr pScreen);
static Bool
+ winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin);
+
+static Bool
winActivateAppShadowGDI(ScreenPtr pScreen);
static Bool
@@ -760,6 +763,12 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
/* BeginPaint gives us an hdc that clips to the invalidated region */
hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &ps);
+ /* Avoid the BitBlt if the PAINTSTRUCT region is bogus */
+ if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
+ ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
+ EndPaint(pScreenPriv->hwndScreen, &ps);
+ return 0;
+ }
/* Realize the palette, if we have one */
if (pScreenPriv->pcmapInstalled != NULL) {
@@ -769,11 +778,30 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
RealizePalette(hdcUpdate);
}
- /* Our BitBlt will be clipped to the invalidated region */
- BitBlt(hdcUpdate,
- 0, 0,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- pScreenPriv->hdcShadow, 0, 0, SRCCOPY);
+ /* Try to copy from the shadow buffer to the invalidated region */
+ if (!BitBlt(hdcUpdate,
+ ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left,
+ ps.rcPaint.bottom - ps.rcPaint.top,
+ pScreenPriv->hdcShadow,
+ ps.rcPaint.left,
+ ps.rcPaint.top,
+ SRCCOPY)) {
+ LPVOID lpMsgBuf;
+
+ /* Display an 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("winBltExposedRegionsShadowGDI - BitBlt failed: %s\n",
+ (LPSTR) lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
/* EndPaint frees the DC */
EndPaint(pScreenPriv->hwndScreen, &ps);
@@ -789,6 +817,149 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
}
/*
+ * Blt exposed region to the given HWND
+ */
+
+static Bool
+winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin)
+{
+ winScreenPriv(pScreen);
+ winPrivWinPtr pWinPriv = winGetWindowPriv(pWin);
+
+ HWND hWnd = pWinPriv->hWnd;
+ HDC hdcUpdate;
+ PAINTSTRUCT ps;
+
+ hdcUpdate = BeginPaint(hWnd, &ps);
+ /* Avoid the BitBlt if the PAINTSTRUCT region is bogus */
+ if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
+ ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
+ EndPaint(hWnd, &ps);
+ return 0;
+ }
+
+#ifdef COMPOSITE
+ if (pWin->redirectDraw != RedirectDrawNone) {
+ HBITMAP hBitmap;
+ HDC hdcPixmap;
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+
+ /*
+ This is kind of clunky, and possibly not very efficient.
+
+ Would it be more efficient to only create the DIB bitmap when the
+ composite bitmap is realloced and store it in a window private?
+
+ But we still end up copying and converting all the bits from the
+ window pixmap into a DDB for every update.
+
+ Perhaps better still would be to wrap the screen CreatePixmap routine
+ so it uses CreateDIBSection()?
+ */
+
+ BITMAPV4HEADER bmih;
+ memset(&bmih, sizeof(bmih), 0);
+ bmih.bV4Size = sizeof(BITMAPV4HEADER);
+ bmih.bV4Width = pPixmap->drawable.width;
+ bmih.bV4Height = -pPixmap->drawable.height; /* top-down bitmap */
+ bmih.bV4Planes = 1;
+ bmih.bV4BitCount = pPixmap->drawable.bitsPerPixel;
+ bmih.bV4SizeImage = 0;
+ /* window pixmap format is the same as the screen pixmap */
+ assert(pPixmap->drawable.bitsPerPixel > 8);
+ bmih.bV4V4Compression = BI_BITFIELDS;
+ bmih.bV4RedMask = pScreenPriv->dwRedMask;
+ bmih.bV4GreenMask = pScreenPriv->dwGreenMask;
+ bmih.bV4BlueMask = pScreenPriv->dwBlueMask;
+ bmih.bV4AlphaMask = 0;
+
+ /* Create the window bitmap from the pixmap */
+ hBitmap = CreateDIBitmap(pScreenPriv->hdcScreen,
+ (BITMAPINFOHEADER *)&bmih, CBM_INIT,
+ pPixmap->devPrivate.ptr, (BITMAPINFO *)&bmih,
+ DIB_RGB_COLORS);
+
+ /* Select the window bitmap into a screen-compatible DC */
+ hdcPixmap = CreateCompatibleDC(pScreenPriv->hdcScreen);
+ SelectObject(hdcPixmap, hBitmap);
+
+ /* Blt from the window bitmap to the invalidated region */
+ if (!BitBlt(hdcUpdate,
+ ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left,
+ ps.rcPaint.bottom - ps.rcPaint.top,
+ hdcPixmap,
+ ps.rcPaint.left + pWin->borderWidth,
+ ps.rcPaint.top + pWin->borderWidth,
+ SRCCOPY))
+ ErrorF("winBltExposedWindowRegionShadowGDI - BitBlt failed: 0x%08x\n",
+ GetLastError());
+
+ /* Release */
+ DeleteDC(hdcPixmap);
+ DeleteObject(hBitmap);
+ }
+ else
+#endif
+ {
+ /* Try to copy from the shadow buffer to the invalidated region */
+ /* XXX: looks like those coordinates should get transformed ??? */
+ if (!BitBlt(hdcUpdate,
+ ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left,
+ ps.rcPaint.bottom - ps.rcPaint.top,
+ pScreenPriv->hdcShadow,
+ ps.rcPaint.left + pWin->drawable.x,
+ ps.rcPaint.top + pWin->drawable.y,
+ SRCCOPY)) {
+ LPVOID lpMsgBuf;
+
+ /* Display an 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("winBltExposedWindowRegionShadowGDI - BitBlt failed: %s\n",
+ (LPSTR) lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+ }
+
+ /* If part of the invalidated region is outside the window (which can happen
+ if the native window is being re-sized), fill that area with black */
+ if (ps.rcPaint.right > ps.rcPaint.left + pWin->drawable.width) {
+ BitBlt(hdcUpdate,
+ ps.rcPaint.left + pWin->drawable.width,
+ ps.rcPaint.top,
+ ps.rcPaint.right - (ps.rcPaint.left + pWin->drawable.width),
+ ps.rcPaint.bottom - ps.rcPaint.top,
+ NULL,
+ 0, 0,
+ BLACKNESS);
+ }
+
+ if (ps.rcPaint.bottom > ps.rcPaint.top + pWin->drawable.height) {
+ BitBlt(hdcUpdate,
+ ps.rcPaint.left,
+ ps.rcPaint.top + pWin->drawable.height,
+ ps.rcPaint.right - ps.rcPaint.left,
+ ps.rcPaint.bottom - (ps.rcPaint.top + pWin->drawable.height),
+ NULL,
+ 0, 0,
+ BLACKNESS);
+ }
+
+ /* EndPaint frees the DC */
+ EndPaint(hWnd, &ps);
+
+ return TRUE;
+}
+
+/*
* Do any engine-specific appliation-activation processing
*/
@@ -1135,6 +1306,7 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen)
pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
+ pScreenPriv->pwinBltExposedWindowRegion = winBltExposedWindowRegionShadowGDI;
pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
pScreenPriv->pwinRealizeInstalledPalette =
@@ -1143,16 +1315,8 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen)
pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
- pScreenPriv->pwinHotKeyAltTab =
- (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA;
- pScreenPriv->pwinCreatePrimarySurface =
- (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
- pScreenPriv->pwinReleasePrimarySurface =
- (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow =
- (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA;
-#endif
+ pScreenPriv->pwinCreatePrimarySurface = NULL;
+ pScreenPriv->pwinReleasePrimarySurface = NULL;
return TRUE;
}
diff --git a/hw/xwin/wintaskbar.c b/hw/xwin/wintaskbar.c
index 7dd4ec30b..401ec175a 100644
--- a/hw/xwin/wintaskbar.c
+++ b/hw/xwin/wintaskbar.c
@@ -66,7 +66,7 @@ DECLARE_INTERFACE_(ITaskbarList, IUnknown)
seem to be the case
*/
-void winShowWindowOnTaskbar(HWND hWnd, BOOL show)
+void winShowWindowOnTaskbar(HWND hWnd, Bool show)
{
ITaskbarList* pTaskbarList = NULL;
diff --git a/hw/xwin/winvalargs.c b/hw/xwin/winvalargs.c
index edfd71f72..f93872419 100644
--- a/hw/xwin/winvalargs.c
+++ b/hw/xwin/winvalargs.c
@@ -127,7 +127,7 @@ winValidateArgs(void)
return FALSE;
}
- /* Check for -multiwindow, -mwextwm, or -rootless and fullscreen */
+ /* Check for -multiwindow, -mwextwm, or -rootless and -fullscreen */
if (g_ScreenInfo[i].fFullScreen && (FALSE
#ifdef XWIN_MULTIWINDOW
|| g_ScreenInfo[i].fMultiWindow
@@ -142,6 +142,21 @@ winValidateArgs(void)
return FALSE;
}
+ /* Check for -multiwindow, -mwextwm, or -rootless and -nodecoration */
+ if (!g_ScreenInfo[i].fDecoration && (FALSE
+#ifdef XWIN_MULTIWINDOW
+ || g_ScreenInfo[i].fMultiWindow
+#endif
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || g_ScreenInfo[i].fMWExtWM
+#endif
+ || g_ScreenInfo[i].fRootless)
+ ) {
+ ErrorF("winValidateArgs - -nodecoration is invalid with "
+ "-multiwindow, -mwextwm, or -rootless.\n");
+ return FALSE;
+ }
+
/* Check for !fullscreen and any fullscreen-only parameters */
if (!g_ScreenInfo[i].fFullScreen
&& (g_ScreenInfo[i].dwRefreshRate != WIN_DEFAULT_REFRESH
@@ -153,7 +168,7 @@ winValidateArgs(void)
/* Check for fullscreen and any non-fullscreen parameters */
if (g_ScreenInfo[i].fFullScreen
- && ((g_ScreenInfo[i].iResizeMode != notAllowed)
+ && ((g_ScreenInfo[i].iResizeMode != resizeNotAllowed)
|| !g_ScreenInfo[i].fDecoration
|| g_ScreenInfo[i].fLessPointer)) {
ErrorF("winValidateArgs - -fullscreen is invalid with "
diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index 660a78f2d..52806887f 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -40,6 +40,7 @@
#define _WINDOWSWM_SERVER_
#include <X11/extensions/windowswmstr.h>
#include "winmultiwindowclass.h"
+#include "winmultiwindowicons.h"
#include <X11/Xatom.h>
/*
@@ -516,12 +517,6 @@ winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
win32RootlessWindowPtr pRLNextWinPriv = (win32RootlessWindowPtr) nextWid;
winScreenPriv(pRLWinPriv->pFrame->win->drawable.pScreen);
- winScreenInfo *pScreenInfo = NULL;
- DWORD dwCurrentProcessID = GetCurrentProcessId();
- DWORD dwWindowProcessID = 0;
- HWND hWnd;
- Bool fFirst = TRUE;
- Bool fNeedRestack = TRUE;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMRestackFrame (%p)\n", pRLWinPriv);
@@ -530,9 +525,6 @@ winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
if (pScreenPriv && pScreenPriv->fRestacking)
return;
- if (pScreenPriv)
- pScreenInfo = pScreenPriv->pScreenInfo;
-
pRLWinPriv->fRestackingNow = TRUE;
/* Show window */
@@ -541,68 +533,12 @@ winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
if (pRLNextWinPriv == NULL) {
#if CYGMULTIWINDOW_DEBUG
- winDebug("Win %08x is top\n", pRLWinPriv);
+ winDebug("Win %p is top\n", pRLWinPriv);
#endif
pScreenPriv->widTop = wid;
SetWindowPos(pRLWinPriv->hWnd, HWND_TOP,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
- else if (winIsInternalWMRunning(pScreenInfo)) {
- /* using mulwinidow wm */
-#if CYGMULTIWINDOW_DEBUG
- winDebug("Win %08x is not top\n", pRLWinPriv);
-#endif
- for (hWnd = GetNextWindow(pRLWinPriv->hWnd, GW_HWNDPREV);
- fNeedRestack && hWnd != NULL;
- hWnd = GetNextWindow(hWnd, GW_HWNDPREV)) {
- GetWindowThreadProcessId(hWnd, &dwWindowProcessID);
-
- if ((dwWindowProcessID == dwCurrentProcessID)
- && GetProp(hWnd, WIN_WINDOW_PROP)) {
- if (hWnd == pRLNextWinPriv->hWnd) {
- /* Enable interleave X window and Windows window */
- if (!fFirst) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("raise: Insert after Win %08x\n",
- pRLNextWinPriv);
-#endif
- SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
- 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- }
- else {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("No change\n");
-#endif
- }
- fNeedRestack = FALSE;
- break;
- }
- if (fFirst)
- fFirst = FALSE;
- }
- }
-
- for (hWnd = GetNextWindow(pRLWinPriv->hWnd, GW_HWNDNEXT);
- fNeedRestack && hWnd != NULL;
- hWnd = GetNextWindow(hWnd, GW_HWNDNEXT)) {
- GetWindowThreadProcessId(hWnd, &dwWindowProcessID);
-
- if ((dwWindowProcessID == dwCurrentProcessID)
- && GetProp(hWnd, WIN_WINDOW_PROP)) {
- if (hWnd == pRLNextWinPriv->hWnd) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("lower: Insert after Win %08x\n", pRLNextWinPriv);
-#endif
- SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
- 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- fNeedRestack = FALSE;
- break;
- }
- }
- }
- }
else {
/* using general wm like twm, wmaker etc.
Interleave X window and Windows window will cause problem. */
diff --git a/hw/xwin/winwin32rootlesswindow.c b/hw/xwin/winwin32rootlesswindow.c
index 1faa531df..817cd093e 100644
--- a/hw/xwin/winwin32rootlesswindow.c
+++ b/hw/xwin/winwin32rootlesswindow.c
@@ -194,10 +194,6 @@ winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv,
/* Get current window placement */
GetWindowPlacement(pRLWinPriv->hWnd, &wndPlace);
- if (winIsInternalWMRunning(pScreenInfo)) {
- if (!pRLWinPriv->pFrame->win->overrideRedirect)
- fDecorate = TRUE;
- }
#if 0
if (wndPlace.showCmd == SW_HIDE)
return; //showCmd = SWP_HIDEWINDOW;
@@ -345,15 +341,6 @@ winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv,
}
/*
- * winIsInternalWMRunning (winScreenInfoPtr pScreenInfo)
- */
-Bool
-winIsInternalWMRunning(winScreenInfoPtr pScreenInfo)
-{
- return pScreenInfo->fInternalWM && !pScreenInfo->fAnotherWMRunning;
-}
-
-/*
* winMWExtWMRestackWindows
*/
@@ -402,7 +389,7 @@ winMWExtWMRestackWindows(ScreenPtr pScreen)
#if CYGMULTIWINDOW_DEBUG
winDebug
- ("winMWExtWMRestackWindows - DeferWindowPos (%08x, %08x)\n",
+ ("winMWExtWMRestackWindows - DeferWindowPos (%p, %p)\n",
pRLWin->hWnd, pRLWinPrev ? pRLWinPrev->hWnd : HWND_TOP);
#endif
hWinPosInfo = DeferWindowPos(hWinPosInfo, pRLWin->hWnd,
diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c
index 79d959161..85c9cbf22 100644
--- a/hw/xwin/winwin32rootlesswndproc.c
+++ b/hw/xwin/winwin32rootlesswndproc.c
@@ -42,6 +42,7 @@
#include "winmultiwindowclass.h"
#include "winmsg.h"
#include "inputstr.h"
+#include "wmutil/keyboard.h"
/*
* Constant defines
@@ -60,9 +61,9 @@ static UINT_PTR g_uipMousePollingTimerID = 0;
* Local function
*/
-DEFINE_ATOM_HELPER(AtmWindowsWmRaiseOnClick, WINDOWSWM_RAISE_ON_CLICK)
- DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE)
+DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE)
/* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */
+
/*
* ConstrainSize - Taken from TWM sources - Respects hints for sizing
*/
@@ -272,55 +273,6 @@ ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
}
/*
- * IsRaiseOnClick
- */
-
-static Bool
-IsRaiseOnClick(WindowPtr pWin)
-{
-
- struct _Window *pwin;
- struct _Property *prop;
-
- /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
- * Which pointer's current window do we want? */
- WindowPtr pRoot = GetCurrentRootWindow(inputInfo.pointer);
-
- if (!pWin) {
- ErrorF("IsRaiseOnClick - no prop use default value:%d\n",
- RAISE_ON_CLICK_DEFAULT);
- return RAISE_ON_CLICK_DEFAULT;
- }
-
- pwin = (struct _Window *) pWin;
-
- if (pwin->optional)
- prop = (struct _Property *) pwin->optional->userProps;
- else
- prop = NULL;
-
- while (prop) {
- if (prop->propertyName == AtmWindowsWmRaiseOnClick()
- && prop->type == XA_INTEGER && prop->format == 32) {
- return *(int *) prop->data;
- }
- else
- prop = prop->next;
- }
-
- if (pWin != pRoot) {
- return IsRaiseOnClick(pRoot);
- }
- else {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("IsRaiseOnClick - no prop use default value:%d\n",
- RAISE_ON_CLICK_DEFAULT);
-#endif
- return RAISE_ON_CLICK_DEFAULT;
- }
-}
-
-/*
* IsMouseActive
*/
@@ -388,8 +340,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
PAINTSTRUCT ps;
LPWINDOWPOS pWinPos = NULL;
RECT rcClient;
- winWMMessageRec wmMsg;
- Bool fWMMsgInitialized = FALSE;
/* Check if the Windows window property for our X window pointer is valid */
if ((pRLWinPriv =
@@ -403,26 +353,16 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (pScreenPriv)
hwndScreen = pScreenPriv->hwndScreen;
- wmMsg.msg = 0;
- wmMsg.hwndWindow = hwnd;
- wmMsg.iWindow = (Window) pWin->drawable.id;
-
- wmMsg.iX = pRLWinPriv->pFrame->x;
- wmMsg.iY = pRLWinPriv->pFrame->y;
- wmMsg.iWidth = pRLWinPriv->pFrame->width;
- wmMsg.iHeight = pRLWinPriv->pFrame->height;
-
- fWMMsgInitialized = TRUE;
#if CYGDEBUG
winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam,
lParam);
- winDebug("\thWnd %08X\n", hwnd);
- winDebug("\tpScreenPriv %08X\n", pScreenPriv);
- winDebug("\tpScreenInfo %08X\n", pScreenInfo);
- winDebug("\thwndScreen %08X\n", hwndScreen);
- winDebug("winMWExtWMWindowProc (%08x) %08x %08x %08x\n",
- pRLWinPriv, message, wParam, lParam);
+ winDebug("\thWnd %p\n", hwnd);
+ winDebug("\tpScreenPriv %p\n", pScreenPriv);
+ winDebug("\tpScreenInfo %p\n", pScreenInfo);
+ winDebug("\thwndScreen %p\n", hwndScreen);
+ winDebug("winMWExtWMWindowProc (%p) %08x %08x %08x\n",
+ pRLWinPriv, message, (int)wParam, (int)lParam);
#endif
}
/* Branch on message type */
@@ -446,12 +386,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
DestroyWindow(hwnd);
}
else {
- if (winIsInternalWMRunning(pScreenInfo)) {
- /* Tell our Window Manager thread to kill the window */
- wmMsg.msg = WM_WM_KILL;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
@@ -680,19 +614,7 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
#endif
-#if 1
- /* Check if this window needs to be made active when clicked */
- if (winIsInternalWMRunning(pScreenInfo) && pWin->overrideRedirect) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE - "
- "MA_NOACTIVATE\n");
-#endif
-
- /* */
- return MA_NOACTIVATE;
- }
-#endif
- if (!winIsInternalWMRunning(pScreenInfo) && !IsMouseActive(pWin))
+ if (!IsMouseActive(pWin))
return MA_NOACTIVATE;
break;
@@ -805,19 +727,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winMWExtWMWindowProc - WM_ACTIVATE\n");
#endif
if (LOWORD(wParam) != WA_INACTIVE) {
- if (winIsInternalWMRunning(pScreenInfo)) {
-#if 0
- /* Raise the window to the top in Z order */
- wmMsg.msg = WM_WM_RAISE;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
-#endif
- /* Tell our Window Manager thread to activate the window */
- wmMsg.msg = WM_WM_ACTIVATE;
- if (fWMMsgInitialized)
- if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
@@ -838,14 +747,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
- if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick(pWin)) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("Win %p has WINDOWSWM_RAISE_ON_CLICK.\n",
- pRLWinPriv);
-#endif
- break;
- }
-
#if CYGMULTIWINDOW_DEBUG
winDebug("Win %p forbid to change z order (%p).\n",
pRLWinPriv,
@@ -889,9 +790,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
(short) HIWORD(lParam));
#endif
if (!pRLWinPriv->fMovingOrSizing) {
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
-
winMWExtWMMoveXWindow(pWin, (LOWORD(lParam) - wBorderWidth(pWin)
- GetSystemMetrics(SM_XVIRTUALSCREEN)),
(HIWORD(lParam) - wBorderWidth(pWin)
@@ -907,31 +805,8 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!wParam)
return 0;
- if (!pScreenInfo->fInternalWM) //XXXX
- return 0;
-
winMWExtWMUpdateWindowDecoration(pRLWinPriv, pScreenInfo);
- if (winIsInternalWMRunning(pScreenInfo)) {
-#if CYGMULTIWINDOW_DEBUG || TRUE
- winDebug("\tMapWindow\n");
-#endif
- /* Tell X to map the window */
- MapWindow(pWin, wClient(pWin));
-
- if (!pRLWinPriv->pFrame->win->overrideRedirect)
- /* Bring the Windows window to the foreground */
- SetForegroundWindow(hwnd);
-
- /* Setup the Window Manager message */
- wmMsg.msg = WM_WM_MAP;
- wmMsg.iWidth = pRLWinPriv->pFrame->width;
- wmMsg.iHeight = pRLWinPriv->pFrame->height;
-
- /* Tell our Window Manager thread to map the window */
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
break;
case WM_SIZING:
@@ -967,72 +842,12 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (pWinPos->flags & SWP_HIDEWINDOW)
break;
- /* Reorder if window z order was changed */
- if ((pScreenPriv != NULL)
- && !(pWinPos->flags & SWP_NOZORDER)
- && !(pWinPos->flags & SWP_SHOWWINDOW)
- && winIsInternalWMRunning(pScreenInfo)) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("\twindow z order was changed\n");
-#endif
- if (pWinPos->hwndInsertAfter == HWND_TOP
- || pWinPos->hwndInsertAfter == HWND_TOPMOST
- || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("\traise to top\n");
-#endif
- /* Raise the window to the top in Z order */
- wmMsg.msg = WM_WM_RAISE;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
-#if 1
- else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
- }
- else {
- /* Check if this window is top of X windows. */
- HWND hWndAbove = NULL;
- DWORD dwCurrentProcessID = GetCurrentProcessId();
- DWORD dwWindowProcessID = 0;
-
- for (hWndAbove = pWinPos->hwndInsertAfter;
- hWndAbove != NULL;
- hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
- /* Ignore other XWin process's window */
- GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
-
- if ((dwWindowProcessID == dwCurrentProcessID)
- && GetProp(hWndAbove, WIN_WINDOW_PROP)
- && !IsWindowVisible(hWndAbove)
- && !IsIconic(hWndAbove)) /* ignore minimized windows */
- break;
- }
- /* If this is top of X windows in Windows stack,
- raise it in X stack. */
- if (hWndAbove == NULL) {
-#if CYGMULTIWINDOW_DEBUG
- winDebug("\traise to top\n");
-#endif
- /* Raise the window to the top in Z order */
- wmMsg.msg = WM_WM_RAISE;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
- }
-#endif
- }
-
if (!(pWinPos->flags & SWP_NOSIZE)) {
if (IsIconic(hwnd)) {
#if CYGMULTIWINDOW_DEBUG
winDebug("\tIconic -> MINIMIZED\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo)) {
- /* Raise the window to the top in Z order */
- wmMsg.msg = WM_WM_LOWER;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
+
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
@@ -1072,8 +887,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("\tmove & resize\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
winMWExtWMMoveResizeXWindow(pWin,
rcClient.left -
@@ -1095,8 +908,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("\tmove\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
winMWExtWMMoveResizeXWindow(pWin,
rcClient.left -
@@ -1118,8 +929,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("\tmove\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
winMWExtWMMoveXWindow(pWin,
rcClient.left - wBorderWidth(pWin)
@@ -1132,8 +941,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("\tresize\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
winMWExtWMResizeXWindow(pWin,
rcClient.right - rcClient.left
@@ -1168,12 +975,7 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGMULTIWINDOW_DEBUG
winDebug("\tSIZE_MINIMIZED\n");
#endif
- if (winIsInternalWMRunning(pScreenInfo)) {
- /* Raise the window to the top in Z order */
- wmMsg.msg = WM_WM_LOWER;
- if (fWMMsgInitialized)
- winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg);
- }
+
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
@@ -1209,9 +1011,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Perform the resize and notify the X client */
if (!pRLWinPriv->fMovingOrSizing) {
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
-
winMWExtWMResizeXWindow(pWin, (short) LOWORD(lParam)
- wBorderWidth(pWin) * 2,
(short) HIWORD(lParam)
@@ -1224,10 +1023,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winMWExtWMWindowProc - WM_ACTIVATEAPP\n");
#endif
if (wParam) {
- if (winIsInternalWMRunning(pScreenInfo)) {
- }
- else {
- }
winWindowsWMSendEvent(WindowsWMActivationNotify,
WindowsWMActivationNotifyMask,
1,
@@ -1268,9 +1063,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2);
- if (winIsInternalWMRunning(pScreenInfo))
- winAdjustXWindow(pWin, hwnd);
-
winMWExtWMMoveResizeXWindow(pWin, rcClient.left - wBorderWidth(pWin)
- GetSystemMetrics(SM_XVIRTUALSCREEN),
rcClient.top - wBorderWidth(pWin)
@@ -1281,14 +1073,6 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- wBorderWidth(pWin) * 2);
break;
- case WM_MANAGE:
- ErrorF("winMWExtWMWindowProc - WM_MANAGE\n");
- break;
-
- case WM_UNMANAGE:
- ErrorF("winMWExtWMWindowProc - WM_UNMANAGE\n");
- break;
-
default:
break;
}
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index 7e6bd565c..83c772c09 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -1,5 +1,3 @@
-#if !defined(_WINWINDOW_H_)
-#define _WINWINDOW_H_
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*Copyright (C) Colin Harrison 2005-2009
@@ -31,6 +29,8 @@
* Authors: Kensuke Matsuzaki
* Colin Harrison
*/
+#if !defined(_WINWINDOW_H_)
+#define _WINWINDOW_H_
#ifndef NO
#define NO 0
@@ -50,6 +50,7 @@
#define WIN_SCR_PROP "cyg_screen_prop rl"
#define WINDOW_CLASS_X "cygwin/x X rl"
#define WINDOW_CLASS_X_MSG "cygwin/x X msg"
+#define WINDOW_CLASS_X_CHILD "cygwin/x X child"
#define WINDOW_TITLE_X PROJECT_NAME " X"
#define WIN_WINDOW_PROP "cyg_window_prop_rl"
#ifdef HAS_DEVWINDOWS
@@ -57,6 +58,7 @@
#endif
#define WIN_WID_PROP "cyg_wid_prop_rl"
#define WIN_NEEDMANAGE_PROP "cyg_override_redirect_prop_rl"
+#define WIN_STATE_PROP "cyg_state_prop_rl"
#ifndef CYGMULTIWINDOW_DEBUG
#define CYGMULTIWINDOW_DEBUG NO
#endif
@@ -109,11 +111,9 @@ typedef struct _winWMMessageRec {
#define WM_WM_NAME_EVENT (WM_USER + 9)
#define WM_WM_ICON_EVENT (WM_USER + 10)
#define WM_WM_CHANGE_STATE (WM_USER + 11)
-#define WM_WM_MAP2 (WM_USER + 12)
-#define WM_WM_MAP3 (WM_USER + 13)
+#define WM_WM_MAP_UNMANAGED (WM_USER + 12)
+#define WM_WM_MAP_MANAGED (WM_USER + 13)
#define WM_WM_HINTS_EVENT (WM_USER + 14)
-#define WM_MANAGE (WM_USER + 100)
-#define WM_UNMANAGE (WM_USER + 102)
#define MwmHintsDecorations (1L << 1)
@@ -125,10 +125,16 @@ typedef struct _winWMMessageRec {
#define MwmDecorMinimize (1L << 5)
#define MwmDecorMaximize (1L << 6)
-/* This structure only contains 3 elements... the Motif 2.0 structure
-contains 5... we only need the first 3... so that is all we will define */
+/*
+ This structure only contains 3 elements. The Motif 2.0 structure contains 5,
+ but we only need the first 3, so that is all we will define
+
+ This structure represents xcb_get_property()'s view of the property as a
+ sequence of ints, rather than XGetWindowProperty()'s view of the property as a
+ sequence of arch-dependent longs.
+*/
typedef struct MwmHints {
- unsigned long flags, functions, decorations;
+ unsigned int flags, functions, decorations;
} MwmHints;
#define PropMwmHintsElements 3
@@ -142,15 +148,12 @@ winInitWM(void **ppWMInfo,
pthread_t * ptWMProc,
pthread_t * ptXMsgProc,
pthread_mutex_t * ppmServerStarted,
- int dwScreen, HWND hwndScreen, BOOL allowOtherWM);
+ int dwScreen, HWND hwndScreen, Bool compositeWM);
void
winDeinitMultiWindowWM(void);
void
- winMinimizeWindow(Window id);
-
-void
winPropertyStoreInit(void);
void
@@ -160,7 +163,7 @@ void
winSetAppUserModelID(HWND hWnd, const char *AppID);
void
- winShowWindowOnTaskbar(HWND hWnd, BOOL show);
+ winShowWindowOnTaskbar(HWND hWnd, Bool show);
#endif /* XWIN_MULTIWINDOW */
#endif
diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c
index db41d6b60..b9399fae3 100644
--- a/hw/xwin/winwindowswm.c
+++ b/hw/xwin/winwindowswm.c
@@ -312,7 +312,7 @@ ProcWindowsWMFrameGetRect(ClientPtr client)
REQUEST(xWindowsWMFrameGetRectReq);
#if CYGMULTIWINDOW_DEBUG
- ErrorF("ProcWindowsWMFrameGetRect %d %d\n",
+ ErrorF("ProcWindowsWMFrameGetRect %zu %d\n",
(sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len);
#endif
diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index 123b84f31..61c185785 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -45,6 +45,8 @@
#ifdef XWIN_CLIPBOARD
#include "winclipboard/winclipboard.h"
#endif
+#include "wmutil/mouse.h"
+#include "wmutil/keyboard.h"
/*
* Global variables
@@ -290,22 +292,16 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
* the display dimensions change.
*/
- /*
- * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface
- * and CreatePrimarySurface function pointers to point
- * to the no operation function, NoopDDA. This allows us
- * to blindly call these functions, even if they are not
- * relevant to the current engine (e.g., Shadow GDI).
- */
-
winDebug
("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
/* Release the old primary surface */
- (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
+ if (*s_pScreenPriv->pwinReleasePrimarySurface)
+ (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
/* Create the new primary surface */
- (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
+ if (*s_pScreenPriv->pwinCreatePrimarySurface)
+ (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
}
}
@@ -322,7 +318,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#endif
/* Break if we do not allow resizing */
- if ((s_pScreenInfo->iResizeMode == notAllowed)
+ if ((s_pScreenInfo->iResizeMode == resizeNotAllowed)
|| !s_pScreenInfo->fDecoration
#ifdef XWIN_MULTIWINDOWEXTWM
|| s_pScreenInfo->fMWExtWM
@@ -909,7 +905,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 */
@@ -1107,14 +1103,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winFixShiftKeys(iScanCode);
return 0;
- case WM_HOTKEY:
- if (s_pScreenPriv == NULL)
- break;
-
- /* Call the engine-specific hot key handler */
- (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen);
- return 0;
-
case WM_ACTIVATE:
if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
break;
@@ -1192,7 +1180,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#ifdef XWIN_MULTIWINDOWEXTWM
if (s_pScreenPriv->fActive) {
/* Restack all window unless using built-in wm. */
- if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning)
+ if (s_pScreenInfo->fMWExtWM)
winMWExtWMRestackWindows(s_pScreen);
}
#endif
@@ -1256,28 +1244,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
-#ifdef XWIN_MULTIWINDOWEXTWM
- case WM_MANAGE:
- ErrorF("winWindowProc - WM_MANAGE\n");
- s_pScreenInfo->fAnotherWMRunning = FALSE;
-
- if (s_pScreenInfo->fInternalWM) {
- EnumThreadWindows(g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
- //RootlessRepositionWindows (s_pScreen);
- }
- break;
-
- case WM_UNMANAGE:
- ErrorF("winWindowProc - WM_UNMANAGE\n");
- s_pScreenInfo->fAnotherWMRunning = TRUE;
-
- if (s_pScreenInfo->fInternalWM) {
- EnumThreadWindows(g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
- winMWExtWMRestackWindows(s_pScreen);
- }
- break;
-#endif
-
default:
if (message == s_uTaskbarRestart) {
winInitNotifyIcon(s_pScreenPriv);
diff --git a/hw/xwin/wmutil/Makefile.am b/hw/xwin/wmutil/Makefile.am
new file mode 100644
index 000000000..d4e213b7f
--- /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 -no-undefined
diff --git a/hw/xwin/wmutil/cursor_convert.c b/hw/xwin/wmutil/cursor_convert.c
new file mode 100644
index 000000000..b91200478
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.c
@@ -0,0 +1,351 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+
+#include "win.h"
+#include "winmsg.h"
+#include <cursorstr.h>
+
+#include "cursor_convert.h"
+
+#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114)
+
+#if 1
+#define WIN_DEBUG_MSG winDebug
+#else
+#define WIN_DEBUG_MSG(...)
+#endif
+
+static unsigned char
+reverse(unsigned char c)
+{
+ int i;
+ unsigned char ret = 0;
+
+ for (i = 0; i < 8; ++i) {
+ ret |= ((c >> i) & 1) << (7 - i);
+ }
+ return ret;
+}
+
+/*
+ * Convert X cursor to Windows cursor
+ * FIXME: Perhaps there are more smart code
+ */
+HCURSOR
+winXCursorToHCURSOR(WMUTIL_CURSOR *pCursor)
+{
+ HCURSOR hCursor = NULL;
+ unsigned char *pAnd;
+ unsigned char *pXor;
+ int nCX, nCY;
+ int nBytes;
+ double dForeY, dBackY;
+ BOOL fReverse;
+ HBITMAP hAnd, hXor;
+ ICONINFO ii;
+ unsigned char *pCur;
+ unsigned char bit;
+ HDC hDC;
+ BITMAPV4HEADER bi;
+ BITMAPINFO *pbmi;
+ uint32_t *lpBits;
+
+ int sm_cx = GetSystemMetrics(SM_CXCURSOR);
+ int sm_cy = GetSystemMetrics(SM_CYCURSOR);
+
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Win32 size: %dx%d X11 size: %dx%d hotspot: %d,%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height,
+ pCursor->xhot, pCursor->yhot);
+
+ /* We can use only White and Black, so calc brightness of color
+ * Also check if the cursor is inverted */
+ dForeY = BRIGHTNESS(pCursor->fore);
+ dBackY = BRIGHTNESS(pCursor->back);
+ fReverse = dForeY < dBackY;
+
+ /* Check whether the X11 cursor is bigger than the win32 cursor */
+ if (sm_cx < pCursor->width ||
+ sm_cy < pCursor->height) {
+ winError("winXCursorToHCURSOR - Windows requires %dx%d cursor but X requires %dx%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height);
+ }
+
+ /* Get the number of bytes required to store the whole cursor image
+ * This is roughly (sm_cx * sm_cy) / 8
+ * round up to 8 pixel boundary so we can convert whole bytes */
+ nBytes =
+ bits_to_bytes(sm_cx) * sm_cy;
+
+ /* Get the effective width and height */
+ nCX = min(sm_cx, pCursor->width);
+ nCY = min(sm_cy, pCursor->height);
+
+ /* Allocate memory for the bitmaps */
+ pAnd = malloc(nBytes);
+ memset(pAnd, 0xFF, nBytes);
+ pXor = calloc(1, nBytes);
+ memset(pXor, 0x00, nBytes);
+
+ /* prepare the pointers */
+ hCursor = NULL;
+ lpBits = NULL;
+
+ /* We have a truecolor alpha-blended cursor and can use it! */
+ if (pCursor->argb) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying truecolor alphablended cursor\n");
+ memset(&bi, 0, sizeof(BITMAPV4HEADER));
+ bi.bV4Size = sizeof(BITMAPV4HEADER);
+ bi.bV4Width = sm_cx;
+ bi.bV4Height = -(sm_cy); /* right-side up */
+ bi.bV4Planes = 1;
+ bi.bV4BitCount = 32;
+ bi.bV4V4Compression = BI_BITFIELDS;
+ bi.bV4RedMask = 0x00FF0000;
+ bi.bV4GreenMask = 0x0000FF00;
+ bi.bV4BlueMask = 0x000000FF;
+ bi.bV4AlphaMask = 0xFF000000;
+
+ lpBits = calloc(sm_cx * sm_cy, sizeof(uint32_t));
+
+ if (lpBits) {
+ int y;
+ for (y = 0; y < nCY; y++) {
+ void *src, *dst;
+ src = &(pCursor->argb[y * pCursor->width]);
+ dst = &(lpBits[y * sm_cx]);
+ memcpy(dst, src, 4 * nCX);
+ }
+ }
+ } /* End if-truecolor-icon */
+ else
+ {
+ /* Convert the X11 bitmap to a win32 bitmap
+ * The first is for an empty mask */
+ if (pCursor->emptyMask) {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ pAnd[nWinPix] = 0;
+ if (fReverse)
+ pXor[nWinPix] = reverse(~pCursor->source[nXPix]);
+ else
+ pXor[nWinPix] = reverse(pCursor->source[nXPix]);
+ }
+ }
+ else {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ unsigned char mask = pCursor->mask[nXPix];
+
+ pAnd[nWinPix] = reverse(~mask);
+ if (fReverse)
+ pXor[nWinPix] =
+ reverse(~pCursor->source[nXPix] & mask);
+ else
+ pXor[nWinPix] =
+ reverse(pCursor->source[nXPix] & mask);
+ }
+ }
+ }
+
+ if (!lpBits) {
+ RGBQUAD *pbmiColors;
+ /* Bicolor, use a palettized DIB */
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying two color cursor\n");
+ pbmi = (BITMAPINFO *) &bi;
+ pbmiColors = &(pbmi->bmiColors[0]);
+
+ memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = sm_cx;
+ pbmi->bmiHeader.biHeight = -abs(sm_cy); /* right-side up */
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biClrUsed = 3;
+ pbmi->bmiHeader.biClrImportant = 3;
+
+ pbmiColors[0].rgbRed = 0; /* Empty */
+ pbmiColors[0].rgbGreen = 0;
+ pbmiColors[0].rgbBlue = 0;
+ pbmiColors[0].rgbReserved = 0;
+ pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
+ pbmiColors[1].rgbGreen = pCursor->backGreen >> 8;
+ pbmiColors[1].rgbBlue = pCursor->backBlue >> 8;
+ pbmiColors[1].rgbReserved = 0;
+ pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
+ pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
+ pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
+ pbmiColors[2].rgbReserved = 0;
+
+ lpBits = calloc(sm_cx * sm_cy, 1);
+
+ pCur = (unsigned char *) lpBits;
+ if (lpBits) {
+ int x, y;
+ for (y = 0; y < sm_cy; y++) {
+ for (x = 0; x < sm_cx; x++) {
+ if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */
+ (*pCur++) = 0;
+ else { /* Within X11 icon bounds */
+
+ int nWinPix =
+ bits_to_bytes(sm_cx) * y +
+ (x / 8);
+
+ bit = pAnd[nWinPix];
+ bit = bit & (1 << (7 - (x & 7)));
+ if (!bit) { /* Within the cursor mask? */
+ int nXPix =
+ BitmapBytePad(pCursor->width) * y +
+ (x / 8);
+ bit =
+ ~reverse(~pCursor->
+ source[nXPix] & pCursor->
+ mask[nXPix]);
+ bit = bit & (1 << (7 - (x & 7)));
+ if (bit) /* Draw foreground */
+ (*pCur++) = 2;
+ else /* Draw background */
+ (*pCur++) = 1;
+ }
+ else /* Outside the cursor mask */
+ (*pCur++) = 0;
+ }
+ } /* end for (x) */
+ } /* end for (y) */
+ } /* end if (lpbits) */
+ }
+
+ /* If one of the previous two methods gave us the bitmap we need, make a cursor */
+ if (lpBits) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating bitmap cursor\n");
+
+ hAnd = NULL;
+ hXor = NULL;
+
+ hAnd =
+ CreateBitmap(sm_cx, sm_cy,
+ 1, 1, pAnd);
+
+ hDC = GetDC(NULL);
+ if (hDC) {
+ hXor =
+ CreateCompatibleBitmap(hDC, sm_cx,
+ sm_cy);
+ SetDIBits(hDC, hXor, 0, sm_cy, lpBits,
+ (BITMAPINFO *) &bi, DIB_RGB_COLORS);
+ ReleaseDC(NULL, hDC);
+ }
+ free(lpBits);
+
+ if (hAnd && hXor) {
+ ii.fIcon = FALSE;
+ ii.xHotspot = pCursor->xhot;
+ ii.yHotspot = pCursor->yhot;
+ ii.hbmMask = hAnd;
+ ii.hbmColor = hXor;
+ hCursor = (HCURSOR) CreateIconIndirect(&ii);
+
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError());
+ else {
+ /*
+ Apparently, CreateIconIndirect() sometimes creates an Icon instead of a Cursor.
+ This breaks the hotspot and makes the cursor unusable. Discard the broken cursor
+ and revert to simple b&w cursor. (Seen on W2K in 2004...)
+ */
+ if (GetIconInfo(hCursor, &ii)) {
+ if (ii.fIcon) {
+ winError
+ ("winXCursorToHCURSOR: CreateIconIndirect made an icon, not a cursor. Trying again.\n");
+
+ DestroyCursor(hCursor);
+
+ ii.fIcon = FALSE;
+ ii.xHotspot = pCursor->xhot;
+ ii.yHotspot = pCursor->yhot;
+ hCursor = (HCURSOR) CreateIconIndirect(&ii);
+
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError());
+ }
+ /* GetIconInfo creates new bitmaps. Destroy them again */
+ if (ii.hbmMask)
+ DeleteObject(ii.hbmMask);
+ if (ii.hbmColor)
+ DeleteObject(ii.hbmColor);
+ }
+ }
+ }
+
+ if (hAnd)
+ DeleteObject(hAnd);
+ if (hXor)
+ DeleteObject(hXor);
+ }
+
+ if (!hCursor) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating b&w cursor\n");
+ /* We couldn't make a color cursor for this screen, use
+ black and white instead */
+ hCursor = CreateCursor(GetModuleHandle(NULL),
+ pCursor->xhot, pCursor->yhot,
+ sm_cx,
+ sm_cy, pAnd, pXor);
+ if (hCursor == NULL)
+ winError("winXCursorToHCURSOR - CreateCursor failed: %x", GetLastError());
+ }
+ free(pAnd);
+ free(pXor);
+
+ return hCursor;
+}
diff --git a/hw/xwin/wmutil/cursor_convert.h b/hw/xwin/wmutil/cursor_convert.h
new file mode 100644
index 000000000..a5ddba3c2
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.h
@@ -0,0 +1,54 @@
+/*
+ * File: cursor_convert.h
+ * Purpose: interface for X->Windows cursor conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_CURSOR_H
+#define WMUTILS_CURSOR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct _WMUTIL_CURSOR
+{
+ // this is the data for cursor created with RENDER CreateCusor or read
+ // with XFIXES GetCursorImage
+ int width;
+ int height;
+ int xhot;
+ int yhot;
+ uint32_t *argb;
+
+ // for a core CreateCursor, we might need the following...
+ unsigned char *source;
+ unsigned char *mask;
+ bool emptyMask;
+ unsigned short foreRed, foreGreen, foreBlue;
+ unsigned short backRed, backGreen, backBlue;
+
+} WMUTIL_CURSOR;
+
+HCURSOR
+winXCursorToHCURSOR(WMUTIL_CURSOR *cursordata);
+
+#endif /* WMUTILS_CURSOR_H */
diff --git a/hw/xwin/wmutil/icon_convert.c b/hw/xwin/wmutil/icon_convert.c
new file mode 100644
index 000000000..be9f4e027
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.c
@@ -0,0 +1,572 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Earle F. Philhower, III
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_image.h>
+
+#include <windows.h>
+
+#include <limits.h>
+#include <stdbool.h>
+
+#include "winmsg.h"
+
+#include "icon_convert.h"
+
+extern unsigned long serverGeneration;
+
+/*
+ * Scale an X icon ZPixmap into a Windoze icon bitmap
+ */
+
+static void
+winScaleXImageToWindowsIcon(int iconSize,
+ int effBPP,
+ int stride, xcb_image_t* pixmap, unsigned char *image)
+{
+ int row, column, effXBPP, effXDepth;
+ unsigned char *outPtr;
+ unsigned char *iconData = 0;
+ int xStride;
+ float factX, factY;
+ int posX, posY;
+ unsigned char *ptr;
+ unsigned int zero;
+ unsigned int color;
+
+ effXBPP = pixmap->bpp;
+ if (pixmap->bpp == 15)
+ effXBPP = 16;
+
+ effXDepth = pixmap->depth;
+ if (pixmap->depth == 15)
+ effXDepth = 16;
+
+ xStride = pixmap->stride;
+ if (stride == 0 || xStride == 0) {
+ winError("winScaleXBitmapToWindows - stride or xStride is zero. "
+ "Bailing.\n");
+ return;
+ }
+
+ /* Get icon data */
+ iconData = (unsigned char *) pixmap->data;
+
+ /* Keep aspect ratio */
+ factX = ((float) pixmap->width) / ((float) iconSize);
+ factY = ((float) pixmap->height) / ((float) iconSize);
+ if (factX > factY)
+ factY = factX;
+ else
+ factX = factY;
+
+ /* Out-of-bounds, fill icon with zero */
+ zero = 0;
+
+ for (row = 0; row < iconSize; row++) {
+ outPtr = image + stride * row;
+ for (column = 0; column < iconSize; column++) {
+ posX = factX * column;
+ posY = factY * row;
+
+ ptr = (unsigned char *) iconData + posY * xStride;
+ if (effXBPP == 1) {
+ ptr += posX / 8;
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+
+ if ((*ptr) & (1 << (posX & 7)))
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 0;
+ case 24:
+ *(outPtr++) = 0;
+ case 16:
+ *(outPtr++) = 0;
+ case 8:
+ *(outPtr++) = 0;
+ break;
+ case 1:
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ }
+ else
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 0;
+ break;
+ case 24:
+ *(outPtr++) = 255;
+ case 16:
+ *(outPtr++) = 255;
+ case 8:
+ *(outPtr++) = 255;
+ break;
+ case 1:
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ break;
+ }
+ }
+ else if (effXDepth == 24 || effXDepth == 32) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = (((*ptr) << 16)
+ + ((*(ptr + 1)) << 8)
+ + ((*(ptr + 2)) << 0));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = *(ptr++); /* b */
+ *(outPtr++) = *(ptr++); /* g */
+ *(outPtr++) = *(ptr++); /* r */
+ *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
+ break;
+ case 24:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 16:
+ color = ((((*ptr) >> 2) << 10)
+ + (((*(ptr + 1)) >> 2) << 5)
+ + (((*(ptr + 2)) >> 2)));
+ *(outPtr++) = (color >> 8);
+ *(outPtr++) = (color & 255);
+ break;
+ case 8:
+ color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
+ color /= 3;
+ *(outPtr++) = color;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ }
+ }
+ else if (effXDepth == 16) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = ((*ptr) << 8) + (*(ptr + 1));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ *(outPtr++) = 0; /* resvd */
+ break;
+ case 24:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ break;
+ case 16:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 8:
+ *(outPtr++) = (((color & 31)
+ + ((color >> 5) & 31)
+ + ((color >> 10) & 31)) / 3) << 2;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ } /* end switch(effbpp) */
+ } /* end if effxbpp==16) */
+ } /* end for column */
+ } /* end for row */
+}
+
+static HICON
+NetWMToWinIconAlpha(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ HICON result;
+ HDC hdc = GetDC(NULL);
+ uint32_t *DIB_pixels;
+ ICONINFO ii;
+ BITMAPV4HEADER bmh = { sizeof(bmh) };
+
+ /* Define an ARGB pixel format used for Color+Alpha icons */
+ bmh.bV4Width = width;
+ bmh.bV4Height = -height; /* Invert the image */
+ bmh.bV4Planes = 1;
+ bmh.bV4BitCount = 32;
+ bmh.bV4V4Compression = BI_BITFIELDS;
+ bmh.bV4AlphaMask = 0xFF000000;
+ bmh.bV4RedMask = 0x00FF0000;
+ bmh.bV4GreenMask = 0x0000FF00;
+ bmh.bV4BlueMask = 0x000000FF;
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh,
+ DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
+ 0);
+ ReleaseDC(NULL, hdc);
+
+ if (!ii.hbmColor)
+ return NULL;
+
+ ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
+ memcpy(DIB_pixels, pixels, height * width * 4);
+
+ /* CreateIconIndirect() traditionally required DDBitmaps */
+ /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
+ /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
+ return result;
+}
+
+static HICON
+NetWMToWinIconThreshold(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ int row, col;
+ HICON result;
+ ICONINFO ii;
+
+ HDC hdc = GetDC(NULL);
+ HDC xorDC = CreateCompatibleDC(hdc);
+ HDC andDC = CreateCompatibleDC(hdc);
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
+ ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
+ ReleaseDC(NULL, hdc);
+ SelectObject(xorDC, ii.hbmColor);
+ SelectObject(andDC, ii.hbmMask);
+
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
+ SetPixelV(xorDC, col, row,
+ RGB(((char *) pixels)[2], ((char *) pixels)[1],
+ ((char *) pixels)[0]));
+ SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
+ }
+ else {
+ SetPixelV(xorDC, col, row, RGB(0, 0, 0));
+ SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
+ }
+ pixels++;
+ }
+ }
+ DeleteDC(xorDC);
+ DeleteDC(andDC);
+
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
+ result);
+ return result;
+}
+
+static HICON
+NetWMToWinIcon(int bpp, uint32_t * icon)
+{
+ static bool hasIconAlphaChannel = FALSE;
+ static bool versionChecked = FALSE;
+
+ if (!versionChecked) {
+ OSVERSIONINFOEX osvi = { 0 };
+ ULONGLONG dwlConditionMask = 0;
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ osvi.dwMajorVersion = 5;
+ osvi.dwMinorVersion = 1;
+
+ /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
+ VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
+ VER_GREATER_EQUAL);
+ hasIconAlphaChannel =
+ VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
+ dwlConditionMask);
+ versionChecked = TRUE;
+
+ winError("OS has icon alpha channel support: %s\n",
+ hasIconAlphaChannel ? "yes" : "no");
+ }
+
+ if (hasIconAlphaChannel && (bpp == 32))
+ return NetWMToWinIconAlpha(icon);
+ else
+ return NetWMToWinIconThreshold(icon);
+}
+
+/*
+ * Attempt to create a custom icon from the WM_HINTS bitmaps
+ */
+
+HICON
+winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize)
+{
+ unsigned char *mask, *image = NULL, *imageMask;
+ unsigned char *dst, *src;
+ int planes, bpp, i;
+ unsigned int biggest_size = 0;
+ HDC hDC;
+ ICONINFO ii;
+ xcb_icccm_wm_hints_t hints;
+ HICON hIcon = NULL;
+ uint32_t *biggest_icon = NULL;
+ static xcb_atom_t _XA_NET_WM_ICON;
+ static int generation;
+ uint32_t *icon, *icon_data = NULL;
+ unsigned long int size;
+
+ hDC = GetDC(GetDesktopWindow());
+ planes = GetDeviceCaps(hDC, PLANES);
+ bpp = GetDeviceCaps(hDC, BITSPIXEL);
+ ReleaseDC(GetDesktopWindow(), hDC);
+
+ /* Always prefer _NET_WM_ICON icons */
+ if (generation != serverGeneration) {
+ xcb_intern_atom_reply_t *atom_reply;
+ xcb_intern_atom_cookie_t atom_cookie;
+ const char *atomName = "_NET_WM_ICON";
+
+ generation = serverGeneration;
+
+ _XA_NET_WM_ICON = XCB_NONE;
+
+ atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
+ atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
+ if (atom_reply) {
+ _XA_NET_WM_ICON = atom_reply->atom;
+ free(atom_reply);
+ }
+ }
+
+ {
+ xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
+
+ if (reply &&
+ ((icon_data = xcb_get_property_value(reply)) != NULL)) {
+ size = xcb_get_property_value_length(reply)/sizeof(uint32_t);
+ for (icon = icon_data; icon < &icon_data[size] && *icon;
+ icon = &icon[icon[0] * icon[1] + 2]) {
+ winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
+
+ /* Icon data size will overflow an int and thus is bigger than the
+ property can possibly be */
+ if ((INT_MAX/icon[0]) < icon[1]) {
+ winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
+ break;
+ }
+
+ /* Icon data size is bigger than amount of data remaining */
+ if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
+ winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
+ break;
+ }
+
+ /* Found an exact match to the size we require... */
+ if (icon[0] == iconSize && icon[1] == iconSize) {
+ winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
+ iconSize, iconSize);
+ hIcon = NetWMToWinIcon(bpp, icon);
+ break;
+ }
+ /* Otherwise, find the biggest icon and let Windows scale the size */
+ else if (biggest_size < icon[0]) {
+ biggest_icon = icon;
+ biggest_size = icon[0];
+ }
+ }
+
+ if (!hIcon && biggest_icon) {
+ winDebug
+ ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
+ biggest_icon[0], biggest_icon[1], iconSize, iconSize);
+
+ hIcon = NetWMToWinIcon(bpp, biggest_icon);
+ }
+
+ free(reply);
+ }
+ }
+
+ if (!hIcon) {
+ xcb_get_property_cookie_t wm_hints_cookie;
+
+ winDebug("winXIconToHICON: no suitable NetIcon\n");
+
+ 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 0x%x\n",
+ (unsigned int)id,
+ (unsigned int)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%p\n",
+ (unsigned int)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..78a92a6dc
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.c
@@ -0,0 +1,308 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/Xmd.h> // to provide a BYTE type, since the Windows one is eclipsed
+
+#include "winvkmap.h"
+#include "keyboard.h"
+
+#include "winmsg.h"
+
+static bool g_winKeyState[NUM_KEYCODES];
+
+/*
+ * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
+ * into an ASCII scan code.
+ *
+ * We do this ourselves, rather than letting Windows handle it,
+ * because Windows tends to munge the handling of special keys,
+ * like AltGr on European keyboards.
+ */
+
+int
+winTranslateKey(WPARAM wParam, LPARAM lParam)
+{
+ int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
+ int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
+ int iParam = HIWORD(lParam);
+ int iParamScanCode = LOBYTE(iParam);
+ int iScanCode;
+
+ winDebug("winTranslateKey: wParam %08x lParam %08x\n", (int)wParam, (int)lParam);
+
+/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
+ * scan code.
+ *
+ * Vocola 3 (Rick Mohr's supplement to WSR) uses
+ * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
+ * scan code of 1
+ */
+ if (iParamScanCode <= 1) {
+ if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
+ /* Trigger special case table to translate to extended
+ * keycode, otherwise if num_lock is on, we can get keypad
+ * numbers instead of navigation keys. */
+ iParam |= KF_EXTENDED;
+ else
+ iParamScanCode = MapVirtualKeyEx(wParam,
+ /*MAPVK_VK_TO_VSC */ 0,
+ GetKeyboardLayout(0));
+ }
+
+ /* Branch on special extended, special non-extended, or normal key */
+ if ((iParam & KF_EXTENDED) && iKeyFixupEx)
+ iScanCode = iKeyFixupEx;
+ else if (iKeyFixup)
+ iScanCode = iKeyFixup;
+ else if (wParam == 0 && iParamScanCode == 0x70)
+ iScanCode = KEY_HKTG;
+ else
+ switch (iParamScanCode) {
+ case 0x70:
+ iScanCode = KEY_HKTG;
+ break;
+ case 0x73:
+ iScanCode = KEY_BSlash2;
+ break;
+ default:
+ iScanCode = iParamScanCode;
+ break;
+ }
+
+ return iScanCode;
+}
+
+/*
+ * Look for the lovely fake Control_L press/release generated by Windows
+ * when AltGr is pressed/released on a non-U.S. keyboard.
+ */
+
+bool
+winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ MSG msgNext;
+ LONG lTime;
+ bool fReturn;
+
+ static bool lastWasControlL = FALSE;
+ static LONG lastTime;
+
+ /*
+ * Fake Ctrl_L presses will be followed by an Alt_R press
+ * with the same timestamp as the Ctrl_L press.
+ */
+ if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L press */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next press message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYDOWN &&
+ msgNext.message != WM_SYSKEYDOWN)
+ fReturn = 0;
+
+ if (!fReturn) {
+ lastWasControlL = TRUE;
+ lastTime = lTime;
+ }
+ else {
+ lastWasControlL = FALSE;
+ }
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key press is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L press is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ /*
+ * Sometimes, the Alt_R press message is not yet posted when the
+ * fake Ctrl_L press message arrives (even though it has the
+ * same timestamp), so check for an Alt_R press message that has
+ * arrived since the last Ctrl_L message.
+ */
+ else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
+ /* Got a Alt_R press */
+
+ if (lastWasControlL) {
+ lTime = GetMessageTime();
+
+ if (lastTime == lTime) {
+ /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */
+ winSendKeyEvent(KEY_LCtrl, FALSE);
+ }
+ lastWasControlL = FALSE;
+ }
+ }
+ /*
+ * Fake Ctrl_L releases will be followed by an Alt_R release
+ * with the same timestamp as the Ctrl_L release.
+ */
+ else if ((message == WM_KEYUP || message == WM_SYSKEYUP)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L release */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next release message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYUP &&
+ msgNext.message != WM_SYSKEYUP)
+ fReturn = 0;
+
+ lastWasControlL = FALSE;
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn
+ && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP)
+ && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key release is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L release is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ else {
+ /* On any other press or release message, we don't have a
+ potentially fake Ctrl_L to worry about anymore... */
+ lastWasControlL = FALSE;
+ }
+
+ /* Not a fake control left press/release */
+ return FALSE;
+}
+
+/*
+ * Lift any modifier keys that are pressed
+ */
+
+void
+winKeybdReleaseKeys(void)
+{
+ int i;
+
+ /* Loop through all keys */
+ for (i = 0; i < NUM_KEYCODES; ++i) {
+ /* Pop key if pressed */
+ if (g_winKeyState[i])
+ winSendKeyEvent(i, FALSE);
+
+ /* Reset pressed flag for keys */
+ g_winKeyState[i] = FALSE;
+ }
+}
+
+/*
+ * Take a raw X key code and send an up or down event for it.
+ *
+ * Thanks to VNC for inspiration, though it is a simple function.
+ */
+
+void
+winSendKeyEvent(DWORD dwKey, bool fDown)
+{
+ /*
+ * When alt-tabing between screens we can get phantom key up messages
+ * Here we only pass them through it we think we should!
+ */
+ if (g_winKeyState[dwKey] == FALSE && fDown == FALSE)
+ return;
+
+ /* Update the keyState map */
+ g_winKeyState[dwKey] = fDown;
+
+ winSendKeyEventCallback(dwKey + MIN_KEYCODE, fDown);
+
+ winDebug("winSendKeyEvent: dwKey: %u, fDown: %u\n", (unsigned int)dwKey, fDown);
+}
+
+bool
+winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case VK_CONTROL:
+ if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
+ return TRUE;
+ break;
+ case VK_SHIFT:
+ if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
+ return TRUE;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Only one shift release message is sent even if both are pressed.
+ * Fix this here
+ */
+void
+winFixShiftKeys(int iScanCode)
+{
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ return;
+
+ if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
+ winSendKeyEvent(KEY_ShiftR, FALSE);
+ if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
+ winSendKeyEvent(KEY_ShiftL, FALSE);
+}
diff --git a/hw/xwin/wmutil/keyboard.h b/hw/xwin/wmutil/keyboard.h
new file mode 100644
index 000000000..5b229c25c
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.h
@@ -0,0 +1,39 @@
+/*
+ * File: keyboard.h
+ * Purpose: interface for X->Windows keyboard event conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_KEYBOARD_H
+#define WMUTILS_KEYBOARD_H
+
+#include <stdbool.h>
+
+void winSendKeyEvent(DWORD dwKey, bool fDown);
+void winSendKeyEventCallback(DWORD dwKey, bool fDown);
+void winKeybdReleaseKeys(void);
+bool winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam);
+bool winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
+int winTranslateKey(WPARAM wParam, LPARAM lParam);
+void winFixShiftKeys(int iScanCode);
+
+#endif /* WMUTILS_KEYBOARD_H */
diff --git a/hw/xwin/wmutil/mouse.c b/hw/xwin/wmutil/mouse.c
new file mode 100644
index 000000000..ba58f067a
--- /dev/null
+++ b/hw/xwin/wmutil/mouse.c
@@ -0,0 +1,111 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/X.h>
+
+#include "mouse.h"
+
+/* Handle the mouse wheel */
+void
+winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown)
+{
+ int button;
+
+ /* Do we have any previous delta stored? */
+ if ((*iTotalDeltaZ > 0 && iDeltaZ > 0)
+ || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) {
+ /* Previous delta and of same sign as current delta */
+ iDeltaZ += *iTotalDeltaZ;
+ *iTotalDeltaZ = 0;
+ }
+ else {
+ /*
+ * Previous delta of different sign, or zero.
+ * We will set it to zero for either case,
+ * as blindly setting takes just as much time
+ * as checking, then setting if necessary :)
+ */
+ *iTotalDeltaZ = 0;
+ }
+
+ /*
+ * Only process this message if the wheel has moved further than
+ * WHEEL_DELTA
+ */
+ if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
+ *iTotalDeltaZ = 0;
+
+ /* Figure out how many whole deltas of the wheel we have */
+ iDeltaZ /= WHEEL_DELTA;
+ }
+ else {
+ /*
+ * Wheel has not moved past WHEEL_DELTA threshold;
+ * we will store the wheel delta until the threshold
+ * has been reached.
+ */
+ *iTotalDeltaZ = iDeltaZ;
+ return;
+ }
+
+ /* Set the button to indicate up or down wheel delta */
+ if (iDeltaZ > 0) {
+ button = iButtonUp;
+ }
+ else {
+ button = iButtonDown;
+ }
+
+ /*
+ * Flip iDeltaZ to positive, if negative,
+ * because always need to generate a *positive* number of
+ * button clicks for the Z axis.
+ */
+ if (iDeltaZ < 0) {
+ iDeltaZ *= -1;
+ }
+
+ /* Generate X input messages for each wheel delta we have seen */
+ while (iDeltaZ--) {
+ /* Push the wheel button */
+ winMouseButtonsSendEvent(TRUE, button);
+
+ /* Release the wheel button */
+ winMouseButtonsSendEvent(FALSE, button);
+ }
+}
diff --git a/hw/xwin/wmutil/mouse.h b/hw/xwin/wmutil/mouse.h
new file mode 100644
index 000000000..8bd6fe9eb
--- /dev/null
+++ b/hw/xwin/wmutil/mouse.h
@@ -0,0 +1,36 @@
+/*
+ * File: mouse.h
+ * Purpose: interface for X->Windows mouse event conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_MOUSE_H
+#define WMUTILS_MOUSE_H
+
+#include <stdbool.h>
+
+void winMouseWheel(int *iTotalDeltaz, int iDeltaZ, int iButtonUp, int iButtonDown);
+
+/* Callback for sending mouse button events */
+void winMouseButtonsSendEvent(bool bPress, int iButton);
+
+#endif /* WMUTILS_MOUSE_H */
diff --git a/hw/xwin/winkeynames.h b/hw/xwin/wmutil/scancodes.h
index bfed9d427..3215a4bcb 100644
--- a/hw/xwin/winkeynames.h
+++ b/hw/xwin/wmutil/scancodes.h
@@ -1,5 +1,3 @@
-#ifndef _WINKEYNAMES_H
-#define _WINKEYNAMES_H
/*
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
*
@@ -23,18 +21,8 @@
*
*/
-#define GLYPHS_PER_KEY 4
-#define NUM_KEYCODES 248
-#define MIN_KEYCODE 8
-#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
-
-#define AltMask Mod1Mask
-#define NumLockMask Mod2Mask
-#define AltLangMask Mod3Mask
-#define KanaMask Mod4Mask
-#define ScrollLockMask Mod5Mask
-
-#define ModifierDown(k) ((keyc->state & (k)) == (k))
+#ifndef SCANCODES_H
+#define SCANCODES_H
/*
* NOTE: The AT/MF keyboards can generate (via the 8042) two (MF: three)
@@ -203,4 +191,4 @@
#define KEY_NOTUSED 0
#define KEY_UNKNOWN 255
-#endif /* _WINKEYNAMES_H */
+#endif /* SCANCODES_H */
diff --git a/hw/xwin/winkeybd.h b/hw/xwin/wmutil/winvkmap.h
index 6701f0959..eff61c7f9 100644
--- a/hw/xwin/winkeybd.h
+++ b/hw/xwin/wmutil/winvkmap.h
@@ -1,5 +1,3 @@
-#if !defined(WINKEYBD_H)
-#define WINKEYBD_H
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*
@@ -30,10 +28,17 @@
* Authors: Harold L Hunt II
*/
+#ifndef WINVKMAP_H
+#define WINVKMAP_H
+
/*
* We need symbols for the scan codes of keys.
*/
-#include "winkeynames.h"
+#include "scancodes.h"
+
+#define NUM_KEYCODES 248
+#define MIN_KEYCODE 8
+#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
#define VK_FN 0xFF
@@ -268,8 +273,7 @@ const int
/* 220 */ 0, 0, 0,
/* 221 */ 0, 0, 0,
/* 222 */ 0, 0, 0,
- /* 223 */ VK_OEM_8, 0, KEY_RCtrl,
- /* at least on Canadian Multilingual Standard layout */
+ /* 223 */ VK_OEM_8, 0, KEY_RCtrl, /* at least on Canadian Multilingual Standard layout */
/* 224 */ 0, 0, 0,
/* 225 */ 0, 0, 0,
/* 226 */ 0, 0, 0,
@@ -301,8 +305,7 @@ const int
/* 252 */ 0, 0, 0,
/* 253 */ 0, 0, 0,
/* 254 */ 0, 0, 0,
- /* 255 */ VK_FN, 0, KEY_Fn
- /* Most keyboards don't generate a scancode for Fn, but a few do... */
+ /* 255 */ VK_FN, 0, KEY_Fn /* Most keyboards don't generate a scancode for Fn, but a few do... */
};
-#endif /* WINKEYBD_H */
+#endif /* WINVKMAP_H */