summaryrefslogtreecommitdiff
path: root/hw/xwin
diff options
context:
space:
mode:
authorJon TURNEY <jon.turney@dronecode.org.uk>2012-12-19 13:39:19 +0000
committerJon TURNEY <jon.turney@dronecode.org.uk>2012-12-19 13:39:19 +0000
commit76049abac505761266f42a53e70f910d3a18063b (patch)
tree774179ad9e45022ab820260a08b5126f444b0e42 /hw/xwin
parent300976718089800703c8df49e18dde1e49c23d6a (diff)
parentec9d7ae80e3cb68bbc58339172f9bae795ff345d (diff)
Merge branch 'cygwin-patches-for-1.13' into cygwin-release-1.13xserver-cygwin-1.13.1-1
Conflicts: hw/xwin/Makefile.am
Diffstat (limited to 'hw/xwin')
-rw-r--r--hw/xwin/Makefile.am19
-rwxr-xr-xhw/xwin/glx/gen_gl_wrappers.py10
-rw-r--r--hw/xwin/glx/glwrap.c2
-rw-r--r--hw/xwin/win.h24
-rw-r--r--hw/xwin/winclipboardthread.c2
-rw-r--r--hw/xwin/winconfig.h2
-rw-r--r--hw/xwin/wincursor.c306
-rw-r--r--hw/xwin/winkeybd.c307
-rw-r--r--hw/xwin/winmouse.c98
-rw-r--r--hw/xwin/winmsg.c10
-rw-r--r--hw/xwin/winmultiwindowclass.c6
-rw-r--r--hw/xwin/winmultiwindowicons.c516
-rw-r--r--hw/xwin/winmultiwindowwm.c14
-rw-r--r--hw/xwin/winprefs.c6
-rw-r--r--hw/xwin/wintrayicon.c2
-rw-r--r--hw/xwin/winwndproc.c9
-rw-r--r--hw/xwin/wmutil/Makefile.am24
-rw-r--r--hw/xwin/wmutil/cursor_convert.c352
-rw-r--r--hw/xwin/wmutil/cursor_convert.h54
-rw-r--r--hw/xwin/wmutil/icon_convert.c553
-rw-r--r--hw/xwin/wmutil/icon_convert.h34
-rw-r--r--hw/xwin/wmutil/keyboard.c308
-rw-r--r--hw/xwin/wmutil/keyboard.h39
-rw-r--r--hw/xwin/wmutil/mouse.c114
-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
27 files changed, 1672 insertions, 1212 deletions
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index c1e2cef46..a71435909 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -15,7 +15,7 @@ if XWIN_GLX_WINDOWS
GLX_DIR = glx
DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS
XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la
-XWIN_GLX_LINK_FLAGS = -lopengl32
+XWIN_GLX_SYS_LIBS = -lopengl32
endif
if XWIN_MULTIWINDOW
@@ -25,7 +25,8 @@ SRCS_MULTIWINDOW = \
winmultiwindowwm.c \
winmultiwindowwndproc.c
DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW
-MULTIWINDOW_LIBS = -lshlwapi -lole32
+MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32
+MULTIWINDOW_LIBS = $(top_builddir)/hw/xwin/wmutil/libXWinWMUtil.la
endif
if XWIN_MULTIWINDOWEXTWM
@@ -84,15 +85,19 @@ SRCS = InitInput.c \
winengine.c \
winerror.c \
winglobals.c \
+ winglobals.h \
winkeybd.c \
winkeyhook.c \
winmisc.c \
winmonitors.c \
+ winmonitors.h \
winmouse.c \
winmsg.c \
winmsgwindow.c \
winmultiwindowclass.c \
+ winmultiwindowclass.h \
winmultiwindowicons.c \
+ winmultiwindowicons.h \
winprefs.c \
winprefsyacc.y \
winprefslex.l \
@@ -103,6 +108,7 @@ SRCS = InitInput.c \
winshadddnl.c \
winshadgdi.c \
wintaskbar.c \
+ taskbar.h \
wintrayicon.c \
winvalargs.c \
winwakeup.c \
@@ -113,8 +119,6 @@ SRCS = InitInput.c \
winconfig.h \
win.h \
winglobals.h \
- winkeybd.h \
- winkeynames.h \
winlayouts.h \
winmessages.h \
winmonitors.h \
@@ -155,8 +159,9 @@ INCLUDES = -I$(top_srcdir)/miext/rootless
XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la
XWIN_SYS_LIBS += -ldxguid
-XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS)
-XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
+XWin_DEPENDENCIES = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS)
+XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) \
+ $(XWIN_GLX_SYS_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) $(MULTIWINDOW_SYS_LIBS)
XWin_LDFLAGS = -mwindows -static
.rc.o:
@@ -190,5 +195,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) .
+SUBDIRS = man $(GLX_DIR) wmutil .
DIST_SUBDIRS = man glx .
diff --git a/hw/xwin/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py
index 15f7ef868..2273589c9 100755
--- a/hw/xwin/glx/gen_gl_wrappers.py
+++ b/hw/xwin/glx/gen_gl_wrappers.py
@@ -146,9 +146,8 @@ for line in glspec :
arglist_use = m1.group(2)
wrappers[function] = {}
- # near and far might be reserved words or macros so can't be used as formal parameter names
- arglist_use = arglist_use.replace('near','zNear')
- arglist_use = arglist_use.replace('far','zFar')
+ # ensure formal parameter names don't collide with reserved names or shadow global declarations
+ arglist_use = ',' .join([i.rstrip() + '_' for i in arglist_use.split(",")])
wrappers[function]['arglist_use'] = arglist_use
param_count = 0
@@ -217,9 +216,8 @@ for w in sorted(wrappers.keys()) :
if k.startswith('param') :
l = wrappers[w][k].split()
- # near and far might be reserved words or macros so can't be used as formal parameter names
- l[0] = l[0].replace('near','zNear')
- l[0] = l[0].replace('far','zFar')
+ # ensure formal parameter names don't collide with reserved names or shadow global declarations
+ l[0] = l[0] + '_'
if l[2] == 'in' :
if l[3] == 'array' :
diff --git a/hw/xwin/glx/glwrap.c b/hw/xwin/glx/glwrap.c
index 690b82926..73cff3cc1 100644
--- a/hw/xwin/glx/glwrap.c
+++ b/hw/xwin/glx/glwrap.c
@@ -67,7 +67,7 @@ glWinCallDelta(void)
}
static PROC
-glWinResolveHelper(PROC * cache, char *symbol)
+glWinResolveHelper(PROC * cache, const char *symbol)
{
PROC proc = NULL;
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 35eaf2028..5e665f4c2 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -921,9 +921,6 @@ void
* winkeybd.c
*/
-void
- winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode);
-
int
winKeybdProc(DeviceIntPtr pDeviceInt, int iState);
@@ -933,20 +930,6 @@ void
void
winRestoreModeKeyStates(void);
-Bool
- winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam);
-
-void
- winKeybdReleaseKeys(void);
-
-void
- winSendKeyEvent(DWORD dwKey, Bool fDown);
-
-BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
-
-void
- winFixShiftKeys(int iScanCode);
-
/*
* winkeyhook.c
*/
@@ -986,13 +969,6 @@ int
winMouseProc(DeviceIntPtr pDeviceInt, int iState);
int
- winMouseWheel(ScreenPtr pScreen, int iDeltaZ);
-
-void
- winMouseButtonsSendEvent(int iEventType, int iButton);
-
-int
-
winMouseButtonsHandle(ScreenPtr pScreen,
int iEventType, int iButton, WPARAM wParam);
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 779f3e525..ecf93aa41 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -359,10 +359,12 @@ winClipboardProc(void *pvNotUsed)
}
}
+#ifdef HAS_DEVWINDOWS
if (!(FD_ISSET(iConnectionNumber, &fdsRead)) &&
!(FD_ISSET(fdMessageQueue, &fdsRead))) {
winDebug("winClipboardProc - Spurious wake\n");
}
+#endif
}
winClipboardProc_Exit:
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index 4f41a62ad..4cf7ab1d6 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -201,7 +201,7 @@ typedef union {
unsigned long num;
char *str;
double realnum;
- Bool bool;
+ Bool bool_;
OptFrequency freq;
} ValueUnion;
diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c
index b56104fde..62be7cefe 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;
- int x, y;
- unsigned char bit;
- HDC hDC;
- BITMAPV4HEADER bi;
- BITMAPINFO *pbmi;
- unsigned long *lpBits;
-
- WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height,
- pCursor->bits->xhot, pCursor->bits->yhot);
-
- /* We can use only White and Black, so calc brightness of color
- * Also check if the cursor is inverted */
- dForeY = BRIGHTNESS(pCursor->fore);
- dBackY = BRIGHTNESS(pCursor->back);
- fReverse = dForeY < dBackY;
-
- /* Check wether the X11 cursor is bigger than the win32 cursor */
- if (pScreenPriv->cursor.sm_cx < pCursor->bits->width ||
- pScreenPriv->cursor.sm_cy < pCursor->bits->height) {
- winErrorFVerb(3,
- "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n",
- pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
- pCursor->bits->width, pCursor->bits->height);
- }
-
- /* Get the number of bytes required to store the whole cursor image
- * This is roughly (sm_cx * sm_cy) / 8
- * round up to 8 pixel boundary so we can convert whole bytes */
- nBytes =
- bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy;
-
- /* Get the effective width and height */
- nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width);
- nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height);
-
- /* Allocate memory for the bitmaps */
- pAnd = malloc(nBytes);
- memset(pAnd, 0xFF, nBytes);
- pXor = calloc(1, nBytes);
-
- /* Convert the X11 bitmap to a win32 bitmap
- * The first is for an empty mask */
- if (pCursor->bits->emptyMask) {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- pAnd[nWinPix] = 0;
- if (fReverse)
- pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]);
- else
- pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]);
- }
- }
- else {
- int x, y, xmax = bits_to_bytes(nCX);
-
- for (y = 0; y < nCY; ++y)
- for (x = 0; x < xmax; ++x) {
- int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
- int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
-
- unsigned char mask = pCursor->bits->mask[nXPix];
-
- pAnd[nWinPix] = reverse(~mask);
- if (fReverse)
- pXor[nWinPix] =
- reverse(~pCursor->bits->source[nXPix] & mask);
- else
- pXor[nWinPix] =
- reverse(pCursor->bits->source[nXPix] & mask);
- }
- }
-
- /* prepare the pointers */
- hCursor = NULL;
- lpBits = NULL;
-
- /* We have a truecolor alpha-blended cursor and can use it! */
- if (pCursor->bits->argb) {
- WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n");
- memset(&bi, 0, sizeof(BITMAPV4HEADER));
- bi.bV4Size = sizeof(BITMAPV4HEADER);
- bi.bV4Width = pScreenPriv->cursor.sm_cx;
- bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */
- bi.bV4Planes = 1;
- bi.bV4BitCount = 32;
- bi.bV4V4Compression = BI_BITFIELDS;
- bi.bV4RedMask = 0x00FF0000;
- bi.bV4GreenMask = 0x0000FF00;
- bi.bV4BlueMask = 0x000000FF;
- bi.bV4AlphaMask = 0xFF000000;
-
- lpBits =
- (unsigned long *) calloc(pScreenPriv->cursor.sm_cx *
- pScreenPriv->cursor.sm_cy,
- sizeof(unsigned long));
-
- if (lpBits) {
- for (y = 0; y < nCY; y++) {
- unsigned long *src, *dst;
-
- src = &(pCursor->bits->argb[y * pCursor->bits->width]);
- dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]);
- memcpy(dst, src, 4 * nCX);
- }
- }
- } /* End if-truecolor-icon */
-
- if (!lpBits) {
- /* Bicolor, use a palettized DIB */
- WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n");
- pbmi = (BITMAPINFO *) & bi;
- memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx;
- pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */
- pbmi->bmiHeader.biPlanes = 1;
- pbmi->bmiHeader.biBitCount = 8;
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biClrUsed = 3;
- pbmi->bmiHeader.biClrImportant = 3;
- pbmi->bmiColors[0].rgbRed = 0; /* Empty */
- pbmi->bmiColors[0].rgbGreen = 0;
- pbmi->bmiColors[0].rgbBlue = 0;
- pbmi->bmiColors[0].rgbReserved = 0;
- pbmi->bmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
- pbmi->bmiColors[1].rgbGreen = pCursor->backGreen >> 8;
- pbmi->bmiColors[1].rgbBlue = pCursor->backBlue >> 8;
- pbmi->bmiColors[1].rgbReserved = 0;
- pbmi->bmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
- pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
- pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
- pbmi->bmiColors[2].rgbReserved = 0;
-
- lpBits =
- (unsigned long *) calloc(pScreenPriv->cursor.sm_cx *
- pScreenPriv->cursor.sm_cy, sizeof(char));
-
- pCur = (unsigned char *) lpBits;
- if (lpBits) {
- 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/winkeybd.c b/hw/xwin/winkeybd.c
index bfb1407b4..464ddc452 100644
--- a/hw/xwin/winkeybd.c
+++ b/hw/xwin/winkeybd.c
@@ -34,15 +34,21 @@
#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"
-static Bool g_winKeyState[NUM_KEYCODES];
+#define AltMask Mod1Mask
+#define NumLockMask Mod2Mask
+#define AltLangMask Mod3Mask
+#define KanaMask Mod4Mask
+#define ScrollLockMask Mod5Mask
/*
* Local prototypes
@@ -54,65 +60,6 @@ static void
static void
winKeybdCtrl(DeviceIntPtr pDevice, KeybdCtrl * pCtrl);
-/*
- * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
- * into an ASCII scan code.
- *
- * We do this ourselves, rather than letting Windows handle it,
- * because Windows tends to munge the handling of special keys,
- * like AltGr on European keyboards.
- */
-
-void
-winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode)
-{
- int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
- int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
- int iParam = HIWORD(lParam);
- int iParamScanCode = LOBYTE(iParam);
-
- winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
-
-/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
- * scan code.
- *
- * Vocola 3 (Rick Mohr's supplement to WSR) uses
- * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
- * scan code of 1
- */
- if (iParamScanCode <= 1) {
- if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
- /* Trigger special case table to translate to extended
- * keycode, otherwise if num_lock is on, we can get keypad
- * numbers instead of navigation keys. */
- iParam |= KF_EXTENDED;
- else
- iParamScanCode = MapVirtualKeyEx(wParam,
- /*MAPVK_VK_TO_VSC */ 0,
- GetKeyboardLayout(0));
- }
-
- /* Branch on special extended, special non-extended, or normal key */
- if ((iParam & KF_EXTENDED) && iKeyFixupEx)
- *piScanCode = iKeyFixupEx;
- else if (iKeyFixup)
- *piScanCode = iKeyFixup;
- else if (wParam == 0 && iParamScanCode == 0x70)
- *piScanCode = KEY_HKTG;
- else
- switch (iParamScanCode) {
- case 0x70:
- *piScanCode = KEY_HKTG;
- break;
- case 0x73:
- *piScanCode = KEY_BSlash2;
- break;
- default:
- *piScanCode = iParamScanCode;
- break;
- }
-}
-
/* Ring the keyboard bell (system speaker on PCs) */
static void
winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, pointer pCtrl, int iClass)
@@ -266,28 +213,40 @@ winRestoreModeKeyStates(void)
* have a logical XOR operator, so we use a macro instead.
*/
+ /* Check if modifier keys are pressed, and if so, fake a press */
{
- /* consider modifer keys */
- BOOL ctrl = (GetAsyncKeyState(VK_CONTROL) < 0);
- BOOL shift = (GetAsyncKeyState(VK_SHIFT) < 0);
+ BOOL lctrl = (GetAsyncKeyState(VK_LCONTROL) < 0);
+ BOOL rctrl = (GetAsyncKeyState(VK_RCONTROL) < 0);
+ BOOL lshift = (GetAsyncKeyState(VK_LSHIFT) < 0);
+ BOOL rshift = (GetAsyncKeyState(VK_RSHIFT) < 0);
BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0);
BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0);
- if (ctrl && altgr)
- ctrl = FALSE;
+ /*
+ If AltGr and CtrlL appear to be pressed, assume the
+ CtrL is a fake one
+ */
+ if (lctrl && altgr)
+ lctrl = FALSE;
+
+ if (lctrl)
+ winSendKeyEvent(KEY_LCtrl, TRUE);
+
+ if (rctrl)
+ winSendKeyEvent(KEY_RCtrl, TRUE);
- if (WIN_XOR(internalKeyStates & ControlMask, ctrl))
- winSendKeyEvent(KEY_LCtrl, ctrl);
+ if (lshift)
+ winSendKeyEvent(KEY_ShiftL, TRUE);
- if (WIN_XOR(internalKeyStates & ShiftMask, shift))
- winSendKeyEvent(KEY_ShiftL, shift);
+ if (rshift)
+ winSendKeyEvent(KEY_ShiftL, TRUE);
- if (WIN_XOR(internalKeyStates & Mod1Mask, alt))
- winSendKeyEvent(KEY_Alt, alt);
+ if (alt)
+ winSendKeyEvent(KEY_Alt, TRUE);
- if (WIN_XOR(internalKeyStates & Mod5Mask, altgr))
- winSendKeyEvent(KEY_AltLang, altgr);
+ if (altgr)
+ winSendKeyEvent(KEY_AltLang, TRUE);
}
/* Has the key state changed? */
@@ -317,215 +276,25 @@ winRestoreModeKeyStates(void)
winSendKeyEvent(KEY_HKTG, TRUE);
winSendKeyEvent(KEY_HKTG, FALSE);
}
-}
-/*
- * Look for the lovely fake Control_L press/release generated by Windows
- * when AltGr is pressed/released on a non-U.S. keyboard.
- */
-
-Bool
-winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
-{
- MSG msgNext;
- LONG lTime;
- Bool fReturn;
-
- static Bool lastWasControlL = FALSE;
- static UINT lastMessage;
- static LONG lastTime;
-
- /*
- * Fake Ctrl_L presses will be followed by an Alt_R press
- * with the same timestamp as the Ctrl_L press.
- */
- if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
- /* Got a Ctrl_L press */
-
- /* Get time of current message */
- lTime = GetMessageTime();
-
- /* Look for next press message */
- fReturn = PeekMessage(&msgNext, NULL,
- WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
-
- if (fReturn && msgNext.message != WM_KEYDOWN &&
- msgNext.message != WM_SYSKEYDOWN)
- fReturn = 0;
-
- if (!fReturn) {
- lastWasControlL = TRUE;
- lastMessage = message;
- lastTime = lTime;
- }
- else {
- lastWasControlL = FALSE;
- }
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
- /*
- * Next key press is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L press is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
- /*
- * Sometimes, the Alt_R press message is not yet posted when the
- * fake Ctrl_L press message arrives (even though it has the
- * same timestamp), so check for an Alt_R press message that has
- * arrived since the last Ctrl_L message.
- */
- 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.
+ For strict correctness, we should also press any non-modifier keys
+ which are already down when we gain focus, but nobody has complained
+ yet :-)
*/
- else if ((message == WM_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;
- }
-}
-
-/*
- * Take a raw X key code and send an up or down event for it.
- *
- * Thanks to VNC for inspiration, though it is a simple function.
- */
-
-void
-winSendKeyEvent(DWORD dwKey, Bool fDown)
-{
- /*
- * When alt-tabing between screens we can get phantom key up messages
- * Here we only pass them through it we think we should!
- */
- if (g_winKeyState[dwKey] == FALSE && fDown == FALSE)
- return;
-
- /* Update the keyState map */
- g_winKeyState[dwKey] = fDown;
-
QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease,
- dwKey + MIN_KEYCODE, NULL);
-
- winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown);
-}
-
-BOOL
-winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
-{
- 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 on 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);
+ dwKey, NULL);
}
/*
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index 9d896c90e..ec1e5ce4f 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;
@@ -133,90 +135,20 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState)
return Success;
}
-/* Handle the mouse wheel */
-int
-winMouseWheel(ScreenPtr pScreen, int iDeltaZ)
-{
- winScreenPriv(pScreen);
- int button; /* Button4 or Button5 */
-
- /* Button4 = WheelUp */
- /* Button5 = WheelDown */
-
- /* Do we have any previous delta stored? */
- if ((pScreenPriv->iDeltaZ > 0 && iDeltaZ > 0)
- || (pScreenPriv->iDeltaZ < 0 && iDeltaZ < 0)) {
- /* Previous delta and of same sign as current delta */
- iDeltaZ += pScreenPriv->iDeltaZ;
- pScreenPriv->iDeltaZ = 0;
- }
- else {
- /*
- * Previous delta of different sign, or zero.
- * We will set it to zero for either case,
- * as blindly setting takes just as much time
- * as checking, then setting if necessary :)
- */
- pScreenPriv->iDeltaZ = 0;
- }
-
- /*
- * Only process this message if the wheel has moved further than
- * WHEEL_DELTA
- */
- if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) {
- pScreenPriv->iDeltaZ = 0;
-
- /* Figure out how many whole deltas of the wheel we have */
- iDeltaZ /= WHEEL_DELTA;
- }
- else {
- /*
- * Wheel has not moved past WHEEL_DELTA threshold;
- * we will store the wheel delta until the threshold
- * has been reached.
- */
- pScreenPriv->iDeltaZ = iDeltaZ;
- return 0;
- }
-
- /* Set the button to indicate up or down wheel delta */
- if (iDeltaZ > 0) {
- button = Button4;
- }
- else {
- button = Button5;
- }
-
- /*
- * Flip iDeltaZ to positive, if negative,
- * because always need to generate a *positive* number of
- * button clicks for the Z axis.
- */
- if (iDeltaZ < 0) {
- iDeltaZ *= -1;
- }
-
- /* Generate X input messages for each wheel delta we have seen */
- while (iDeltaZ--) {
- /* Push the wheel button */
- winMouseButtonsSendEvent(ButtonPress, button);
-
- /* Release the wheel button */
- winMouseButtonsSendEvent(ButtonRelease, button);
- }
-
- return 0;
-}
-
/*
* Enqueue a mouse button event
*/
void
-winMouseButtonsSendEvent(int iEventType, int iButton)
+winMouseButtonsSendEvent(bool bPress, int iButton)
{
ValuatorMask mask;
+ int iEventType;
+
+ if (bPress)
+ iEventType = ButtonPress;
+ else
+ iEventType = ButtonRelease;
if (g_winMouseButtonMap)
iButton = g_winMouseButtonMap[iButton];
@@ -245,7 +177,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
/* Send button events right away if emulate 3 buttons is off */
if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF) {
/* Emulate 3 buttons is off, send the button event */
- winMouseButtonsSendEvent(iEventType, iButton);
+ winMouseButtonsSendEvent((iEventType == ButtonPress), iButton);
return 0;
}
@@ -282,7 +214,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send fake middle button */
- winMouseButtonsSendEvent(ButtonPress, Button2);
+ winMouseButtonsSendEvent(TRUE, Button2);
/* Indicate that a fake middle button event was sent */
pScreenPriv->fE3BFakeButton2Sent = TRUE;
@@ -297,8 +229,8 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->iE3BCachedPress = 0;
/* Send cached press, then send release */
- winMouseButtonsSendEvent(ButtonPress, iButton);
- winMouseButtonsSendEvent(ButtonRelease, iButton);
+ winMouseButtonsSendEvent(TRUE, iButton);
+ winMouseButtonsSendEvent(FALSE, iButton);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->fE3BFakeButton2Sent && !(wParam & MK_LBUTTON)
@@ -309,7 +241,7 @@ winMouseButtonsHandle(ScreenPtr pScreen,
pScreenPriv->fE3BFakeButton2Sent = FALSE;
/* Send middle mouse button release */
- winMouseButtonsSendEvent(ButtonRelease, Button2);
+ winMouseButtonsSendEvent(TRUE, Button2);
}
else if (iEventType == ButtonRelease
&& pScreenPriv->iE3BCachedPress == 0
@@ -318,7 +250,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 07c2f30eb..b2c87ca17 100644
--- a/hw/xwin/winmsg.c
+++ b/hw/xwin/winmsg.c
@@ -99,6 +99,16 @@ winErrorFVerb(int verb, const char *format, ...)
}
void
+winError(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ LogVMessageVerb(X_NONE, -1, format, ap);
+ va_end(ap);
+}
+
+void
winDebug(const char *format, ...)
{
va_list ap;
diff --git a/hw/xwin/winmultiwindowclass.c b/hw/xwin/winmultiwindowclass.c
index 9fc1be2a4..93166fe3b 100644
--- a/hw/xwin/winmultiwindowclass.c
+++ b/hw/xwin/winmultiwindowclass.c
@@ -37,6 +37,12 @@
#include "winmultiwindowclass.h"
#include "win.h"
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+#define strnlen(str, len) \
+ (__extension__ ({ int _len = strlen(str); \
+ _len > len ? len : _len; }))
+#endif
+
/*
* Local function
*/
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index b8357e72d..9684512da 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -32,510 +32,22 @@
#include <xwin-config.h>
#endif
-#ifndef WINVER
-#define WINVER 0x0500
-#endif
-
#include <X11/Xwindows.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#include <X11/Xlib-xcb.h>
#include "winresource.h"
#include "winprefs.h"
-#include "winmsg.h"
#include "winmultiwindowicons.h"
#include "winglobals.h"
+#include "wmutil/icon_convert.h"
+
/*
* global variables
*/
extern HINSTANCE g_hInstance;
/*
- * Scale an X icon ZPixmap into a Windoze icon bitmap
- */
-
-static void
-winScaleXImageToWindowsIcon(int iconSize,
- int effBPP,
- int stride, XImage * pixmap, unsigned char *image)
-{
- int row, column, effXBPP, effXDepth;
- unsigned char *outPtr;
- unsigned char *iconData = 0;
- int xStride;
- float factX, factY;
- int posX, posY;
- unsigned char *ptr;
- unsigned int zero;
- unsigned int color;
-
- effXBPP = pixmap->bits_per_pixel;
- if (pixmap->bits_per_pixel == 15)
- effXBPP = 16;
-
- effXDepth = pixmap->depth;
- if (pixmap->depth == 15)
- effXDepth = 16;
-
- xStride = pixmap->bytes_per_line;
- if (stride == 0 || xStride == 0) {
- ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. "
- "Bailing.\n");
- return;
- }
-
- /* Get icon data */
- iconData = (unsigned char *) pixmap->data;
-
- /* Keep aspect ratio */
- factX = ((float) pixmap->width) / ((float) iconSize);
- factY = ((float) pixmap->height) / ((float) iconSize);
- if (factX > factY)
- factY = factX;
- else
- factX = factY;
-
- /* Out-of-bounds, fill icon with zero */
- zero = 0;
-
- for (row = 0; row < iconSize; row++) {
- outPtr = image + stride * row;
- for (column = 0; column < iconSize; column++) {
- posX = factX * column;
- posY = factY * row;
-
- ptr = (unsigned char *) iconData + posY * xStride;
- if (effXBPP == 1) {
- ptr += posX / 8;
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
-
- if ((*ptr) & (1 << (posX & 7)))
- switch (effBPP) {
- case 32:
- *(outPtr++) = 0;
- case 24:
- *(outPtr++) = 0;
- case 16:
- *(outPtr++) = 0;
- case 8:
- *(outPtr++) = 0;
- break;
- case 1:
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- }
- else
- switch (effBPP) {
- case 32:
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 255;
- *(outPtr++) = 0;
- break;
- case 24:
- *(outPtr++) = 255;
- case 16:
- *(outPtr++) = 255;
- case 8:
- *(outPtr++) = 255;
- break;
- case 1:
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- break;
- }
- }
- else if (effXDepth == 24 || effXDepth == 32) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = (((*ptr) << 16)
- + ((*(ptr + 1)) << 8)
- + ((*(ptr + 2)) << 0));
- switch (effBPP) {
- case 32:
- *(outPtr++) = *(ptr++); /* b */
- *(outPtr++) = *(ptr++); /* g */
- *(outPtr++) = *(ptr++); /* r */
- *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
- break;
- case 24:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 16:
- color = ((((*ptr) >> 2) << 10)
- + (((*(ptr + 1)) >> 2) << 5)
- + (((*(ptr + 2)) >> 2)));
- *(outPtr++) = (color >> 8);
- *(outPtr++) = (color & 255);
- break;
- case 8:
- color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
- color /= 3;
- *(outPtr++) = color;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- }
- }
- else if (effXDepth == 16) {
- ptr += posX * (effXBPP / 8);
-
- /* Out of X icon bounds, leave space blank */
- if (posX >= pixmap->width || posY >= pixmap->height)
- ptr = (unsigned char *) &zero;
- color = ((*ptr) << 8) + (*(ptr + 1));
- switch (effBPP) {
- case 32:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- *(outPtr++) = 0; /* resvd */
- break;
- case 24:
- *(outPtr++) = (color & 31) << 2;
- *(outPtr++) = ((color >> 5) & 31) << 2;
- *(outPtr++) = ((color >> 10) & 31) << 2;
- break;
- case 16:
- *(outPtr++) = *(ptr++);
- *(outPtr++) = *(ptr++);
- break;
- case 8:
- *(outPtr++) = (((color & 31)
- + ((color >> 5) & 31)
- + ((color >> 10) & 31)) / 3) << 2;
- break;
- case 1:
- if (color)
- outPtr[column / 8] |= (1 << (7 - (column & 7)));
- else
- outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
- break;
- } /* end switch(effbpp) */
- } /* end if effxbpp==16) */
- } /* end for column */
- } /* end for row */
-}
-
-static HICON
-NetWMToWinIconAlpha(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- HICON result;
- HDC hdc = GetDC(NULL);
- uint32_t *DIB_pixels;
- ICONINFO ii;
- BITMAPV4HEADER bmh = { sizeof(bmh) };
-
- /* Define an ARGB pixel format used for Color+Alpha icons */
- bmh.bV4Width = width;
- bmh.bV4Height = -height; /* Invert the image */
- bmh.bV4Planes = 1;
- bmh.bV4BitCount = 32;
- bmh.bV4V4Compression = BI_BITFIELDS;
- bmh.bV4AlphaMask = 0xFF000000;
- bmh.bV4RedMask = 0x00FF0000;
- bmh.bV4GreenMask = 0x0000FF00;
- bmh.bV4BlueMask = 0x000000FF;
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) & bmh,
- DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
- 0);
- ReleaseDC(NULL, hdc);
- ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
- memcpy(DIB_pixels, pixels, height * width * 4);
-
- /* CreateIconIndirect() traditionally required DDBitmaps */
- /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
- /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
- return result;
-}
-
-static HICON
-NetWMToWinIconThreshold(uint32_t * icon)
-{
- int width = icon[0];
- int height = icon[1];
- uint32_t *pixels = &icon[2];
- int row, col;
- HICON result;
- ICONINFO ii;
-
- HDC hdc = GetDC(NULL);
- HDC xorDC = CreateCompatibleDC(hdc);
- HDC andDC = CreateCompatibleDC(hdc);
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
- ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
- ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
- ReleaseDC(NULL, hdc);
- SelectObject(xorDC, ii.hbmColor);
- SelectObject(andDC, ii.hbmMask);
-
- for (row = 0; row < height; row++) {
- for (col = 0; col < width; col++) {
- if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
- SetPixelV(xorDC, col, row,
- RGB(((char *) pixels)[2], ((char *) pixels)[1],
- ((char *) pixels)[0]));
- SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
- }
- else {
- SetPixelV(xorDC, col, row, RGB(0, 0, 0));
- SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
- }
- pixels++;
- }
- }
- DeleteDC(xorDC);
- DeleteDC(andDC);
-
- result = CreateIconIndirect(&ii);
-
- DeleteObject(ii.hbmColor);
- DeleteObject(ii.hbmMask);
-
- winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
- result);
- return result;
-}
-
-static HICON
-NetWMToWinIcon(int bpp, uint32_t * icon)
-{
- static Bool hasIconAlphaChannel = FALSE;
- static BOOL versionChecked = FALSE;
-
- if (!versionChecked) {
- OSVERSIONINFOEX osvi = { 0 };
- ULONGLONG dwlConditionMask = 0;
-
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- osvi.dwMajorVersion = 5;
- osvi.dwMinorVersion = 1;
-
- /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
- VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
- VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
- VER_GREATER_EQUAL);
- hasIconAlphaChannel =
- VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
- dwlConditionMask);
- versionChecked = TRUE;
-
- ErrorF("OS has icon alpha channel support: %s\n",
- hasIconAlphaChannel ? "yes" : "no");
- }
-
- if (hasIconAlphaChannel && (bpp == 32))
- return NetWMToWinIconAlpha(icon);
- else
- return NetWMToWinIconThreshold(icon);
-}
-
-/*
- * Attempt to create a custom icon from the WM_HINTS bitmaps
- */
-
-static
- HICON
-winXIconToHICON(Display * pDisplay, Window id, int iconSize)
-{
- unsigned char *mask, *image = NULL, *imageMask;
- unsigned char *dst, *src;
- int planes, bpp, i;
- int biggest_size = 0;
- HDC hDC;
- ICONINFO ii;
- XWMHints *hints;
- HICON hIcon = NULL;
- uint32_t *biggest_icon = NULL;
-
- static Atom _XA_NET_WM_ICON;
- static int generation;
- uint32_t *icon, *icon_data = NULL;
- unsigned long int size;
- unsigned long int type;
- int format;
- unsigned long int left;
-
- hDC = GetDC(GetDesktopWindow());
- planes = GetDeviceCaps(hDC, PLANES);
- bpp = GetDeviceCaps(hDC, BITSPIXEL);
- ReleaseDC(GetDesktopWindow(), hDC);
-
- /* Always prefer _NET_WM_ICON icons */
- if (generation != serverGeneration) {
- generation = serverGeneration;
- _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE);
- }
-
- if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON,
- 0, MAXINT, FALSE,
- AnyPropertyType, &type, &format, &size, &left,
- (unsigned char **) &icon_data) == Success) &&
- (icon_data != NULL)) {
- for (icon = icon_data; icon < &icon_data[size] && *icon;
- icon = &icon[icon[0] * icon[1] + 2]) {
- /* Find an exact match to the size we require... */
- if (icon[0] == iconSize && icon[1] == iconSize) {
- winDebug("winXIconToHICON: found %lu x %lu NetIcon\n", icon[0],
- icon[1]);
- hIcon = NetWMToWinIcon(bpp, icon);
- break;
- }
- /* Otherwise, find the biggest icon and let Windows scale the size */
- else if (biggest_size < icon[0]) {
- biggest_icon = icon;
- biggest_size = icon[0];
- }
- }
-
- if (!hIcon && biggest_icon) {
- winDebug
- ("winXIconToHICON: selected %lu x %lu NetIcon for scaling to %u x %u\n",
- biggest_icon[0], biggest_icon[1], iconSize, iconSize);
-
- hIcon = NetWMToWinIcon(bpp, biggest_icon);
- }
-
- XFree(icon_data);
- }
-
- if (!hIcon) {
- winDebug("winXIconToHICON: no suitable NetIcon\n");
-
- hints = XGetWMHints(pDisplay, id);
- if (hints) {
- winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
- hints->icon_pixmap);
-
- if (hints->icon_pixmap) {
- Window root;
- int x, y;
- unsigned int width, height, border_width, depth;
- XImage *xImageIcon;
- XImage *xImageMask = NULL;
-
- XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y,
- &width, &height, &border_width, &depth);
-
- xImageIcon =
- XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height,
- 0xFFFFFFFF, ZPixmap);
- winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
- xImageIcon);
-
- if (hints->icon_mask)
- xImageMask =
- XGetImage(pDisplay, hints->icon_mask, 0, 0, width,
- height, 0xFFFFFFFF, ZPixmap);
-
- if (xImageIcon) {
- int effBPP, stride, maskStride;
-
- /* 15 BPP is really 16BPP as far as we care */
- if (bpp == 15)
- effBPP = 16;
- else
- effBPP = bpp;
-
- /* Need 16-bit aligned rows for DDBitmaps */
- stride = ((iconSize * effBPP + 15) & (~15)) / 8;
-
- /* Mask is 1-bit deep */
- maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
-
- image = malloc(stride * iconSize);
- imageMask = malloc(stride * iconSize);
- mask = malloc(maskStride * iconSize);
-
- /* Default to a completely black mask */
- memset(imageMask, 0, stride * iconSize);
- memset(mask, 0, maskStride * iconSize);
-
- winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
- xImageIcon, image);
-
- if (xImageMask) {
- winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
- xImageMask, mask);
- winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
- xImageMask, imageMask);
- }
-
- /* Now we need to set all bits of the icon which are not masked */
- /* on to 0 because Color is really an XOR, not an OR function */
- dst = image;
- src = imageMask;
-
- for (i = 0; i < (stride * iconSize); i++)
- if ((*(src++)))
- *(dst++) = 0;
- else
- dst++;
-
- ii.fIcon = TRUE;
- ii.xHotspot = 0; /* ignored */
- ii.yHotspot = 0; /* ignored */
-
- /* Create Win32 mask from pixmap shape */
- ii.hbmMask =
- CreateBitmap(iconSize, iconSize, planes, 1, mask);
-
- /* Create Win32 bitmap from pixmap */
- ii.hbmColor =
- CreateBitmap(iconSize, iconSize, planes, bpp, image);
-
- /* Merge Win32 mask and bitmap into icon */
- hIcon = CreateIconIndirect(&ii);
-
- /* Release Win32 mask and bitmap */
- DeleteObject(ii.hbmMask);
- DeleteObject(ii.hbmColor);
-
- /* Free X mask and bitmap */
- free(mask);
- free(image);
- free(imageMask);
-
- if (xImageMask)
- XDestroyImage(xImageMask);
-
- XDestroyImage(xImageIcon);
- }
- }
- XFree(hints);
- }
- }
- return hIcon;
-}
-
-/*
* Change the Windows window icon
*/
@@ -545,16 +57,20 @@ winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew)
{
HICON hIcon, hIconSmall = NULL, hIconOld;
- /* Start with the icon from preferences, if any */
- hIcon = hIconNew;
- hIconSmall = hIconNew;
+ if (hIconNew)
+ {
+ /* Start with the icon from preferences, if any */
+ hIcon = hIconNew;
+ hIconSmall = hIconNew;
+ }
+ else
+ {
+ /* If we still need an icon, try and get the icon from WM_HINTS */
+ xcb_connection_t *conn = XGetXCBConnection(pDisplay);
- /* If we still need an icon, try and get the icon from WM_HINTS */
- if (!hIcon)
- hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON));
- if (!hIconSmall)
- hIconSmall =
- winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON));
+ hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON));
+ hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON));
+ }
/* If we got the small, but not the large one swap them */
if (!hIcon && hIconSmall) {
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index b4bd71f62..c948f3080 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -82,6 +82,10 @@
#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
#endif
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
extern void winDebug(const char *format, ...);
extern void winReshapeMultiWindow(WindowPtr pWin);
extern void winUpdateRgnMultiWindow(WindowPtr pWin);
@@ -1733,15 +1737,15 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle)
unsigned long i;
for (i = 0; i < nitems; i++) {
- if (*pAtom == skiptaskbarState)
+ if (pAtom[i] == skiptaskbarState)
hint |= HINT_SKIPTASKBAR;
- if (*pAtom == hiddenState)
+ if (pAtom[i] == hiddenState)
maxmin |= HINT_MIN;
- else if (*pAtom == fullscreenState)
+ else if (pAtom[i] == fullscreenState)
maxmin |= HINT_MAX;
- if (*pAtom == belowState)
+ if (pAtom[i] == belowState)
*zstyle = HWND_BOTTOM;
- else if (*pAtom == aboveState)
+ else if (pAtom[i] == aboveState)
*zstyle = HWND_TOPMOST;
}
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c
index d6ec63099..c443c493b 100644
--- a/hw/xwin/winprefs.c
+++ b/hw/xwin/winprefs.c
@@ -789,7 +789,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;
@@ -838,7 +838,9 @@ LoadPreferences(void)
}
/* Setup XWINLOGFILE environment variable */
- setenv("XWINLOGFILE", g_pszLogFile, TRUE);
+ 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++) {
diff --git a/hw/xwin/wintrayicon.c b/hw/xwin/wintrayicon.c
index dbc47257b..f168b884a 100644
--- a/hw/xwin/wintrayicon.c
+++ b/hw/xwin/wintrayicon.c
@@ -114,7 +114,7 @@ winHandleIconMessage(HWND hwnd, UINT message,
switch (lParam) {
case WM_LBUTTONUP:
/* Restack and bring all windows to top */
- SetForegroundWindow(hwnd);
+ SetForegroundWindow (pScreenPriv->hwndScreen);
#ifdef XWIN_MULTIWINDOWEXTWM
if (pScreenInfo->fMWExtWM)
diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index 9aba46b98..790e1a09c 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -42,6 +42,7 @@
#include "winmsg.h"
#include "winmonitors.h"
#include "inputstr.h"
+#include "wmutil/mouse.h"
/*
* Global variables
@@ -918,7 +919,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (wParam) {
case WIN_E3B_TIMER_ID:
/* Send delayed button press */
- winMouseButtonsSendEvent(ButtonPress,
+ winMouseButtonsSendEvent(TRUE,
s_pScreenPriv->iE3BCachedPress);
/* Kill this timer */
@@ -978,7 +979,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
#if CYGDEBUG
winDebug("winWindowProc - WM_MOUSEWHEEL\n");
#endif
- winMouseWheel(s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam));
+ winMouseWheel(&(s_pScreenPriv->iDeltaZ), GET_WHEEL_DELTA_WPARAM(wParam));
break;
case WM_SETFOCUS:
@@ -1066,7 +1067,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
/* Translate Windows key code to X scan code */
- winTranslateKey(wParam, lParam, &iScanCode);
+ iScanCode = winTranslateKey(wParam, lParam);
/* Ignore repeats for CapsLock */
if (wParam == VK_CAPITAL)
@@ -1095,7 +1096,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
/* Enqueue a keyup event */
- winTranslateKey(wParam, lParam, &iScanCode);
+ iScanCode = winTranslateKey(wParam, lParam);
winSendKeyEvent(iScanCode, FALSE);
/* Release all pressed shift keys */
diff --git a/hw/xwin/wmutil/Makefile.am b/hw/xwin/wmutil/Makefile.am
new file mode 100644
index 000000000..5ccee32a6
--- /dev/null
+++ b/hw/xwin/wmutil/Makefile.am
@@ -0,0 +1,24 @@
+lib_LTLIBRARIES = libXWinWMUtil.la
+
+library_includedir=$(includedir)/XWinWMUtil
+
+library_include_HEADERS = \
+ icon_convert.h \
+ cursor_convert.h \
+ mouse.h \
+ keyboard.h
+
+libXWinWMUtil_la_SOURCES = \
+ icon_convert.c \
+ cursor_convert.c \
+ mouse.c \
+ keyboard.c \
+ winvkmap.h \
+ scancodes.h
+
+AM_CFLAGS = -DHAVE_XWIN_CONFIG_H \
+ $(DIX_CFLAGS) \
+ $(XWINMODULES_CFLAGS) \
+ -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/..
+
+libXWinWMUtil_la_LDFLAGS = -static
diff --git a/hw/xwin/wmutil/cursor_convert.c b/hw/xwin/wmutil/cursor_convert.c
new file mode 100644
index 000000000..9f4e8f1ab
--- /dev/null
+++ b/hw/xwin/wmutil/cursor_convert.c
@@ -0,0 +1,352 @@
+/*
+ *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;
+ int x, y;
+ unsigned char bit;
+ HDC hDC;
+ BITMAPV4HEADER bi;
+ BITMAPINFO *pbmi;
+ unsigned long *lpBits;
+
+ int sm_cx = GetSystemMetrics(SM_CXCURSOR);
+ int sm_cy = GetSystemMetrics(SM_CYCURSOR);
+
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Win32 size: %dx%d X11 size: %dx%d hotspot: %d,%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height,
+ pCursor->xhot, pCursor->yhot);
+
+ /* We can use only White and Black, so calc brightness of color
+ * Also check if the cursor is inverted */
+ dForeY = BRIGHTNESS(pCursor->fore);
+ dBackY = BRIGHTNESS(pCursor->back);
+ fReverse = dForeY < dBackY;
+
+ /* Check whether the X11 cursor is bigger than the win32 cursor */
+ if (sm_cx < pCursor->width ||
+ sm_cy < pCursor->height) {
+ winError("winXCursorToHCURSOR - Windows requires %dx%d cursor but X requires %dx%d\n",
+ sm_cx, sm_cy,
+ pCursor->width, pCursor->height);
+ }
+
+ /* Get the number of bytes required to store the whole cursor image
+ * This is roughly (sm_cx * sm_cy) / 8
+ * round up to 8 pixel boundary so we can convert whole bytes */
+ nBytes =
+ bits_to_bytes(sm_cx) * sm_cy;
+
+ /* Get the effective width and height */
+ nCX = min(sm_cx, pCursor->width);
+ nCY = min(sm_cy, pCursor->height);
+
+ /* Allocate memory for the bitmaps */
+ pAnd = malloc(nBytes);
+ memset(pAnd, 0xFF, nBytes);
+ pXor = calloc(1, nBytes);
+ memset(pXor, 0x00, nBytes);
+
+ /* prepare the pointers */
+ hCursor = NULL;
+ lpBits = NULL;
+
+ /* We have a truecolor alpha-blended cursor and can use it! */
+ if (pCursor->argb) {
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying truecolor alphablended cursor\n");
+ memset(&bi, 0, sizeof(BITMAPV4HEADER));
+ bi.bV4Size = sizeof(BITMAPV4HEADER);
+ bi.bV4Width = sm_cx;
+ bi.bV4Height = -(sm_cy); /* right-side up */
+ bi.bV4Planes = 1;
+ bi.bV4BitCount = 32;
+ bi.bV4V4Compression = BI_BITFIELDS;
+ bi.bV4RedMask = 0x00FF0000;
+ bi.bV4GreenMask = 0x0000FF00;
+ bi.bV4BlueMask = 0x000000FF;
+ bi.bV4AlphaMask = 0xFF000000;
+
+ lpBits =
+ (unsigned long *) calloc(sm_cx *
+ sm_cy,
+ sizeof(unsigned long));
+
+ if (lpBits) {
+ for (y = 0; y < nCY; y++) {
+ unsigned long *src, *dst;
+
+ src = &(pCursor->argb[y * pCursor->width]);
+ dst = &(lpBits[y * sm_cx]);
+ memcpy(dst, src, 4 * nCX);
+ }
+ }
+ } /* End if-truecolor-icon */
+ else
+ {
+ /* Convert the X11 bitmap to a win32 bitmap
+ * The first is for an empty mask */
+ if (pCursor->emptyMask) {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ pAnd[nWinPix] = 0;
+ if (fReverse)
+ pXor[nWinPix] = reverse(~pCursor->source[nXPix]);
+ else
+ pXor[nWinPix] = reverse(pCursor->source[nXPix]);
+ }
+ }
+ else {
+ int x, y, xmax = bits_to_bytes(nCX);
+
+ for (y = 0; y < nCY; ++y)
+ for (x = 0; x < xmax; ++x) {
+ int nWinPix = bits_to_bytes(sm_cx) * y + x;
+ int nXPix = BitmapBytePad(pCursor->width) * y + x;
+
+ unsigned char mask = pCursor->mask[nXPix];
+
+ pAnd[nWinPix] = reverse(~mask);
+ if (fReverse)
+ pXor[nWinPix] =
+ reverse(~pCursor->source[nXPix] & mask);
+ else
+ pXor[nWinPix] =
+ reverse(pCursor->source[nXPix] & mask);
+ }
+ }
+ }
+
+ if (!lpBits) {
+ /* Bicolor, use a palettized DIB */
+ WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying two color cursor\n");
+ pbmi = (BITMAPINFO *) & bi;
+ memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = sm_cx;
+ pbmi->bmiHeader.biHeight = -abs(sm_cy); /* right-side up */
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biClrUsed = 3;
+ pbmi->bmiHeader.biClrImportant = 3;
+ pbmi->bmiColors[0].rgbRed = 0; /* Empty */
+ pbmi->bmiColors[0].rgbGreen = 0;
+ pbmi->bmiColors[0].rgbBlue = 0;
+ pbmi->bmiColors[0].rgbReserved = 0;
+ pbmi->bmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */
+ pbmi->bmiColors[1].rgbGreen = pCursor->backGreen >> 8;
+ pbmi->bmiColors[1].rgbBlue = pCursor->backBlue >> 8;
+ pbmi->bmiColors[1].rgbReserved = 0;
+ pbmi->bmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */
+ pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
+ pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
+ pbmi->bmiColors[2].rgbReserved = 0;
+
+ lpBits =
+ (unsigned long *) calloc(sm_cx *
+ sm_cy, sizeof(char));
+
+ pCur = (unsigned char *) lpBits;
+ if (lpBits) {
+ 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..50d9e809c
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.c
@@ -0,0 +1,553 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Earle F. Philhower, III
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_image.h>
+
+#include <windows.h>
+
+#include <limits.h>
+#include <stdbool.h>
+
+#include "icon_convert.h"
+
+/*
+ * global variables
+ */
+extern int serverGeneration;
+
+/*
+ * Scale an X icon ZPixmap into a Windoze icon bitmap
+ */
+
+static void
+winScaleXImageToWindowsIcon(int iconSize,
+ int effBPP,
+ int stride, xcb_image_t* pixmap, unsigned char *image)
+{
+ int row, column, effXBPP, effXDepth;
+ unsigned char *outPtr;
+ unsigned char *iconData = 0;
+ int xStride;
+ float factX, factY;
+ int posX, posY;
+ unsigned char *ptr;
+ unsigned int zero;
+ unsigned int color;
+
+ effXBPP = pixmap->bpp;
+ if (pixmap->bpp == 15)
+ effXBPP = 16;
+
+ effXDepth = pixmap->depth;
+ if (pixmap->depth == 15)
+ effXDepth = 16;
+
+ xStride = pixmap->stride;
+ if (stride == 0 || xStride == 0) {
+ winError("winScaleXBitmapToWindows - stride or xStride is zero. "
+ "Bailing.\n");
+ return;
+ }
+
+ /* Get icon data */
+ iconData = (unsigned char *) pixmap->data;
+
+ /* Keep aspect ratio */
+ factX = ((float) pixmap->width) / ((float) iconSize);
+ factY = ((float) pixmap->height) / ((float) iconSize);
+ if (factX > factY)
+ factY = factX;
+ else
+ factX = factY;
+
+ /* Out-of-bounds, fill icon with zero */
+ zero = 0;
+
+ for (row = 0; row < iconSize; row++) {
+ outPtr = image + stride * row;
+ for (column = 0; column < iconSize; column++) {
+ posX = factX * column;
+ posY = factY * row;
+
+ ptr = (unsigned char *) iconData + posY * xStride;
+ if (effXBPP == 1) {
+ ptr += posX / 8;
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+
+ if ((*ptr) & (1 << (posX & 7)))
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 0;
+ case 24:
+ *(outPtr++) = 0;
+ case 16:
+ *(outPtr++) = 0;
+ case 8:
+ *(outPtr++) = 0;
+ break;
+ case 1:
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ }
+ else
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 255;
+ *(outPtr++) = 0;
+ break;
+ case 24:
+ *(outPtr++) = 255;
+ case 16:
+ *(outPtr++) = 255;
+ case 8:
+ *(outPtr++) = 255;
+ break;
+ case 1:
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ break;
+ }
+ }
+ else if (effXDepth == 24 || effXDepth == 32) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = (((*ptr) << 16)
+ + ((*(ptr + 1)) << 8)
+ + ((*(ptr + 2)) << 0));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = *(ptr++); /* b */
+ *(outPtr++) = *(ptr++); /* g */
+ *(outPtr++) = *(ptr++); /* r */
+ *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
+ break;
+ case 24:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 16:
+ color = ((((*ptr) >> 2) << 10)
+ + (((*(ptr + 1)) >> 2) << 5)
+ + (((*(ptr + 2)) >> 2)));
+ *(outPtr++) = (color >> 8);
+ *(outPtr++) = (color & 255);
+ break;
+ case 8:
+ color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
+ color /= 3;
+ *(outPtr++) = color;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ }
+ }
+ else if (effXDepth == 16) {
+ ptr += posX * (effXBPP / 8);
+
+ /* Out of X icon bounds, leave space blank */
+ if (posX >= pixmap->width || posY >= pixmap->height)
+ ptr = (unsigned char *) &zero;
+ color = ((*ptr) << 8) + (*(ptr + 1));
+ switch (effBPP) {
+ case 32:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ *(outPtr++) = 0; /* resvd */
+ break;
+ case 24:
+ *(outPtr++) = (color & 31) << 2;
+ *(outPtr++) = ((color >> 5) & 31) << 2;
+ *(outPtr++) = ((color >> 10) & 31) << 2;
+ break;
+ case 16:
+ *(outPtr++) = *(ptr++);
+ *(outPtr++) = *(ptr++);
+ break;
+ case 8:
+ *(outPtr++) = (((color & 31)
+ + ((color >> 5) & 31)
+ + ((color >> 10) & 31)) / 3) << 2;
+ break;
+ case 1:
+ if (color)
+ outPtr[column / 8] |= (1 << (7 - (column & 7)));
+ else
+ outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
+ break;
+ } /* end switch(effbpp) */
+ } /* end if effxbpp==16) */
+ } /* end for column */
+ } /* end for row */
+}
+
+static HICON
+NetWMToWinIconAlpha(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ HICON result;
+ HDC hdc = GetDC(NULL);
+ uint32_t *DIB_pixels;
+ ICONINFO ii;
+ BITMAPV4HEADER bmh = { sizeof(bmh) };
+
+ /* Define an ARGB pixel format used for Color+Alpha icons */
+ bmh.bV4Width = width;
+ bmh.bV4Height = -height; /* Invert the image */
+ bmh.bV4Planes = 1;
+ bmh.bV4BitCount = 32;
+ bmh.bV4V4Compression = BI_BITFIELDS;
+ bmh.bV4AlphaMask = 0xFF000000;
+ bmh.bV4RedMask = 0x00FF0000;
+ bmh.bV4GreenMask = 0x0000FF00;
+ bmh.bV4BlueMask = 0x000000FF;
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) & bmh,
+ DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
+ 0);
+ ReleaseDC(NULL, hdc);
+ ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
+ memcpy(DIB_pixels, pixels, height * width * 4);
+
+ /* CreateIconIndirect() traditionally required DDBitmaps */
+ /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
+ /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
+ return result;
+}
+
+static HICON
+NetWMToWinIconThreshold(uint32_t * icon)
+{
+ int width = icon[0];
+ int height = icon[1];
+ uint32_t *pixels = &icon[2];
+ int row, col;
+ HICON result;
+ ICONINFO ii;
+
+ HDC hdc = GetDC(NULL);
+ HDC xorDC = CreateCompatibleDC(hdc);
+ HDC andDC = CreateCompatibleDC(hdc);
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+ ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
+ ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
+ ReleaseDC(NULL, hdc);
+ SelectObject(xorDC, ii.hbmColor);
+ SelectObject(andDC, ii.hbmMask);
+
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
+ SetPixelV(xorDC, col, row,
+ RGB(((char *) pixels)[2], ((char *) pixels)[1],
+ ((char *) pixels)[0]));
+ SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
+ }
+ else {
+ SetPixelV(xorDC, col, row, RGB(0, 0, 0));
+ SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
+ }
+ pixels++;
+ }
+ }
+ DeleteDC(xorDC);
+ DeleteDC(andDC);
+
+ result = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
+ result);
+ return result;
+}
+
+static HICON
+NetWMToWinIcon(int bpp, uint32_t * icon)
+{
+ static bool hasIconAlphaChannel = FALSE;
+ static bool versionChecked = FALSE;
+
+ if (!versionChecked) {
+ OSVERSIONINFOEX osvi = { 0 };
+ ULONGLONG dwlConditionMask = 0;
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ osvi.dwMajorVersion = 5;
+ osvi.dwMinorVersion = 1;
+
+ /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
+ VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
+ VER_GREATER_EQUAL);
+ hasIconAlphaChannel =
+ VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
+ dwlConditionMask);
+ versionChecked = TRUE;
+
+ winError("OS has icon alpha channel support: %s\n",
+ hasIconAlphaChannel ? "yes" : "no");
+ }
+
+ if (hasIconAlphaChannel && (bpp == 32))
+ return NetWMToWinIconAlpha(icon);
+ else
+ return NetWMToWinIconThreshold(icon);
+}
+
+/*
+ * Attempt to create a custom icon from the WM_HINTS bitmaps
+ */
+
+HICON
+winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize)
+{
+ unsigned char *mask, *image = NULL, *imageMask;
+ unsigned char *dst, *src;
+ int planes, bpp, i;
+ int biggest_size = 0;
+ HDC hDC;
+ ICONINFO ii;
+ xcb_icccm_wm_hints_t hints;
+ HICON hIcon = NULL;
+ uint32_t *biggest_icon = NULL;
+
+ static xcb_atom_t _XA_NET_WM_ICON;
+ static int generation;
+ uint32_t *icon, *icon_data = NULL;
+ unsigned long int size;
+ unsigned long int type;
+ int format;
+ unsigned long int left;
+
+ hDC = GetDC(GetDesktopWindow());
+ planes = GetDeviceCaps(hDC, PLANES);
+ bpp = GetDeviceCaps(hDC, BITSPIXEL);
+ ReleaseDC(GetDesktopWindow(), hDC);
+
+ /* Always prefer _NET_WM_ICON icons */
+ if (generation != serverGeneration) {
+ generation = serverGeneration;
+
+ xcb_intern_atom_reply_t *atom_reply;
+ xcb_intern_atom_cookie_t atom_cookie;
+ const char *atomName = "_NET_WM_ICON";
+
+ _XA_NET_WM_ICON = XCB_NONE;
+
+ atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
+ atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
+ if (atom_reply) {
+ _XA_NET_WM_ICON = atom_reply->atom;
+ free(atom_reply);
+ }
+ }
+
+ xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
+
+ if (reply &&
+ ((icon_data = xcb_get_property_value(reply)) != NULL)) {
+ size = xcb_get_property_value_length(reply)/sizeof(uint32_t);
+ for (icon = icon_data; icon < &icon_data[size] && *icon;
+ icon = &icon[icon[0] * icon[1] + 2]) {
+ /* Find an exact match to the size we require... */
+ if (icon[0] == iconSize && icon[1] == iconSize) {
+ winDebug("winXIconToHICON: found %lu x %lu NetIcon\n", icon[0],
+ icon[1]);
+ hIcon = NetWMToWinIcon(bpp, icon);
+ break;
+ }
+ /* Otherwise, find the biggest icon and let Windows scale the size */
+ else if (biggest_size < icon[0]) {
+ biggest_icon = icon;
+ biggest_size = icon[0];
+ }
+ }
+
+ if (!hIcon && biggest_icon) {
+ winDebug
+ ("winXIconToHICON: selected %lu x %lu NetIcon for scaling to %u x %u\n",
+ biggest_icon[0], biggest_icon[1], iconSize, iconSize);
+
+ hIcon = NetWMToWinIcon(bpp, biggest_icon);
+ }
+
+ free(reply);
+ }
+
+ if (!hIcon) {
+ winDebug("winXIconToHICON: no suitable NetIcon\n");
+
+ xcb_get_property_cookie_t wm_hints_cookie = xcb_icccm_get_wm_hints(conn, id);
+ if (xcb_icccm_get_wm_hints_reply(conn, wm_hints_cookie, &hints, NULL)) {
+ winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
+ hints.icon_pixmap);
+
+ if (hints.icon_pixmap) {
+ unsigned int width, height;
+ xcb_image_t *xImageIcon;
+ xcb_image_t *xImageMask = NULL;
+
+ xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, hints.icon_pixmap);
+ xcb_get_geometry_reply_t *geom_reply = xcb_get_geometry_reply(conn, geom_cookie, NULL);
+
+ if (geom_reply) {
+ width = geom_reply->width;
+ height = geom_reply->height;
+
+ xImageIcon = xcb_image_get(conn, hints.icon_pixmap,
+ 0, 0, width, height,
+ 0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
+
+ winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
+ xImageIcon);
+
+ if (hints.icon_mask)
+ xImageMask = xcb_image_get(conn, hints.icon_mask,
+ 0, 0, width, height,
+ 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
+
+ if (xImageIcon) {
+ int effBPP, stride, maskStride;
+
+ /* 15 BPP is really 16BPP as far as we care */
+ if (bpp == 15)
+ effBPP = 16;
+ else
+ effBPP = bpp;
+
+ /* Need 16-bit aligned rows for DDBitmaps */
+ stride = ((iconSize * effBPP + 15) & (~15)) / 8;
+
+ /* Mask is 1-bit deep */
+ maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
+
+ image = malloc(stride * iconSize);
+ imageMask = malloc(stride * iconSize);
+ mask = malloc(maskStride * iconSize);
+
+ /* Default to a completely black mask */
+ memset(imageMask, 0, stride * iconSize);
+ memset(mask, 0, maskStride * iconSize);
+
+ winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+ xImageIcon, image);
+
+ if (xImageMask) {
+ winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
+ xImageMask, mask);
+ winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+ xImageMask, imageMask);
+ }
+
+ /* Now we need to set all bits of the icon which are not masked */
+ /* on to 0 because Color is really an XOR, not an OR function */
+ dst = image;
+ src = imageMask;
+
+ for (i = 0; i < (stride * iconSize); i++)
+ if ((*(src++)))
+ *(dst++) = 0;
+ else
+ dst++;
+
+ ii.fIcon = TRUE;
+ ii.xHotspot = 0; /* ignored */
+ ii.yHotspot = 0; /* ignored */
+
+ /* Create Win32 mask from pixmap shape */
+ ii.hbmMask =
+ CreateBitmap(iconSize, iconSize, planes, 1, mask);
+
+ /* Create Win32 bitmap from pixmap */
+ ii.hbmColor =
+ CreateBitmap(iconSize, iconSize, planes, bpp, image);
+
+ /* Merge Win32 mask and bitmap into icon */
+ hIcon = CreateIconIndirect(&ii);
+
+ /* Release Win32 mask and bitmap */
+ DeleteObject(ii.hbmMask);
+ DeleteObject(ii.hbmColor);
+
+ /* Free X mask and bitmap */
+ free(mask);
+ free(image);
+ free(imageMask);
+
+ if (xImageMask)
+ xcb_image_destroy(xImageMask);
+
+ xcb_image_destroy(xImageIcon);
+ }
+ }
+ }
+ }
+ }
+ return hIcon;
+}
diff --git a/hw/xwin/wmutil/icon_convert.h b/hw/xwin/wmutil/icon_convert.h
new file mode 100644
index 000000000..0065326be
--- /dev/null
+++ b/hw/xwin/wmutil/icon_convert.h
@@ -0,0 +1,34 @@
+/*
+ * File: icons.h
+ * Purpose: interface for X->Windows icon conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_ICONS_H
+#define WMUTILS_ICONS_H
+
+#include <xcb/xcb.h>
+
+HICON
+winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize);
+
+#endif /* WMUTILS_ICONS_H */
diff --git a/hw/xwin/wmutil/keyboard.c b/hw/xwin/wmutil/keyboard.c
new file mode 100644
index 000000000..e4d0bc61b
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.c
@@ -0,0 +1,308 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/Xmd.h> // to provide a BYTE type, since the Windows one is eclipsed
+
+#include "winvkmap.h"
+#include "keyboard.h"
+
+static bool g_winKeyState[NUM_KEYCODES];
+
+/*
+ * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
+ * into an ASCII scan code.
+ *
+ * We do this ourselves, rather than letting Windows handle it,
+ * because Windows tends to munge the handling of special keys,
+ * like AltGr on European keyboards.
+ */
+
+int
+winTranslateKey(WPARAM wParam, LPARAM lParam)
+{
+ int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
+ int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
+ int iParam = HIWORD(lParam);
+ int iParamScanCode = LOBYTE(iParam);
+ int iScanCode;
+
+ winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
+
+/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
+ * scan code.
+ *
+ * Vocola 3 (Rick Mohr's supplement to WSR) uses
+ * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
+ * scan code of 1
+ */
+ if (iParamScanCode <= 1) {
+ if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
+ /* Trigger special case table to translate to extended
+ * keycode, otherwise if num_lock is on, we can get keypad
+ * numbers instead of navigation keys. */
+ iParam |= KF_EXTENDED;
+ else
+ iParamScanCode = MapVirtualKeyEx(wParam,
+ /*MAPVK_VK_TO_VSC */ 0,
+ GetKeyboardLayout(0));
+ }
+
+ /* Branch on special extended, special non-extended, or normal key */
+ if ((iParam & KF_EXTENDED) && iKeyFixupEx)
+ iScanCode = iKeyFixupEx;
+ else if (iKeyFixup)
+ iScanCode = iKeyFixup;
+ else if (wParam == 0 && iParamScanCode == 0x70)
+ iScanCode = KEY_HKTG;
+ else
+ switch (iParamScanCode) {
+ case 0x70:
+ iScanCode = KEY_HKTG;
+ break;
+ case 0x73:
+ iScanCode = KEY_BSlash2;
+ break;
+ default:
+ iScanCode = iParamScanCode;
+ break;
+ }
+
+ return iScanCode;
+}
+
+/*
+ * Look for the lovely fake Control_L press/release generated by Windows
+ * when AltGr is pressed/released on a non-U.S. keyboard.
+ */
+
+bool
+winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ MSG msgNext;
+ LONG lTime;
+ bool fReturn;
+
+ static bool lastWasControlL = FALSE;
+ static UINT lastMessage;
+ static LONG lastTime;
+
+ /*
+ * Fake Ctrl_L presses will be followed by an Alt_R press
+ * with the same timestamp as the Ctrl_L press.
+ */
+ if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L press */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next press message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYDOWN &&
+ msgNext.message != WM_SYSKEYDOWN)
+ fReturn = 0;
+
+ if (!fReturn) {
+ lastWasControlL = TRUE;
+ lastMessage = message;
+ lastTime = lTime;
+ }
+ else {
+ lastWasControlL = FALSE;
+ }
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key press is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L press is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ /*
+ * Sometimes, the Alt_R press message is not yet posted when the
+ * fake Ctrl_L press message arrives (even though it has the
+ * same timestamp), so check for an Alt_R press message that has
+ * arrived since the last Ctrl_L message.
+ */
+ else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
+ /* Got a Alt_R press */
+
+ if (lastWasControlL) {
+ lTime = GetMessageTime();
+
+ if (lastTime == lTime) {
+ /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */
+ winSendKeyEvent(KEY_LCtrl, FALSE);
+ }
+ lastWasControlL = FALSE;
+ }
+ }
+ /*
+ * Fake Ctrl_L releases will be followed by an Alt_R release
+ * with the same timestamp as the Ctrl_L release.
+ */
+ else if ((message == WM_KEYUP || message == WM_SYSKEYUP)
+ && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) {
+ /* Got a Ctrl_L release */
+
+ /* Get time of current message */
+ lTime = GetMessageTime();
+
+ /* Look for next release message */
+ fReturn = PeekMessage(&msgNext, NULL,
+ WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE);
+
+ if (fReturn && msgNext.message != WM_KEYUP &&
+ msgNext.message != WM_SYSKEYUP)
+ fReturn = 0;
+
+ lastWasControlL = FALSE;
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn
+ && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP)
+ && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD(msgNext.lParam) & KF_EXTENDED)) {
+ /*
+ * Next key release is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L release is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+ else {
+ /* On any other press or release message, we don't have a
+ potentially fake Ctrl_L to worry about anymore... */
+ lastWasControlL = FALSE;
+ }
+
+ /* Not a fake control left press/release */
+ return FALSE;
+}
+
+/*
+ * Lift any modifier keys that are pressed
+ */
+
+void
+winKeybdReleaseKeys(void)
+{
+ int i;
+
+ /* Loop through all keys */
+ for (i = 0; i < NUM_KEYCODES; ++i) {
+ /* Pop key if pressed */
+ if (g_winKeyState[i])
+ winSendKeyEvent(i, FALSE);
+
+ /* Reset pressed flag for keys */
+ g_winKeyState[i] = FALSE;
+ }
+}
+
+/*
+ * Take a raw X key code and send an up or down event for it.
+ *
+ * Thanks to VNC for inspiration, though it is a simple function.
+ */
+
+void
+winSendKeyEvent(DWORD dwKey, bool fDown)
+{
+ /*
+ * When alt-tabing between screens we can get phantom key up messages
+ * Here we only pass them through it we think we should!
+ */
+ if (g_winKeyState[dwKey] == FALSE && fDown == FALSE)
+ return;
+
+ /* Update the keyState map */
+ g_winKeyState[dwKey] = fDown;
+
+ winSendKeyEventCallback(dwKey + MIN_KEYCODE, fDown);
+
+ winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown);
+}
+
+bool
+winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case VK_CONTROL:
+ if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
+ return TRUE;
+ break;
+ case VK_SHIFT:
+ if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
+ return TRUE;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Only one shift release message is sent even if both are pressed.
+ * Fix this here
+ */
+void
+winFixShiftKeys(int iScanCode)
+{
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ return;
+
+ if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
+ winSendKeyEvent(KEY_ShiftR, FALSE);
+ if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
+ winSendKeyEvent(KEY_ShiftL, FALSE);
+}
diff --git a/hw/xwin/wmutil/keyboard.h b/hw/xwin/wmutil/keyboard.h
new file mode 100644
index 000000000..5b229c25c
--- /dev/null
+++ b/hw/xwin/wmutil/keyboard.h
@@ -0,0 +1,39 @@
+/*
+ * File: keyboard.h
+ * Purpose: interface for X->Windows keyboard event conversion
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WMUTILS_KEYBOARD_H
+#define WMUTILS_KEYBOARD_H
+
+#include <stdbool.h>
+
+void winSendKeyEvent(DWORD dwKey, bool fDown);
+void winSendKeyEventCallback(DWORD dwKey, bool fDown);
+void winKeybdReleaseKeys(void);
+bool winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam);
+bool winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
+int winTranslateKey(WPARAM wParam, LPARAM lParam);
+void winFixShiftKeys(int iScanCode);
+
+#endif /* WMUTILS_KEYBOARD_H */
diff --git a/hw/xwin/wmutil/mouse.c b/hw/xwin/wmutil/mouse.c
new file mode 100644
index 000000000..4c96d9cdd
--- /dev/null
+++ b/hw/xwin/wmutil/mouse.c
@@ -0,0 +1,114 @@
+/*
+ *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 button; /* Button4 or Button5 */
+
+ /* Button4 = WheelUp */
+ /* Button5 = WheelDown */
+
+ /* 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 = Button4;
+ }
+ else {
+ button = Button5;
+ }
+
+ /*
+ * Flip iDeltaZ to positive, if negative,
+ * because always need to generate a *positive* number of
+ * button clicks for the Z axis.
+ */
+ if (iDeltaZ < 0) {
+ iDeltaZ *= -1;
+ }
+
+ /* Generate X input messages for each wheel delta we have seen */
+ while (iDeltaZ--) {
+ /* Push the wheel button */
+ winMouseButtonsSendEvent(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..ddde7be8b
--- /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);
+
+/* 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 */