Enable Tablet support with both Tilt and Pressure.
diff --git a/configure b/configure
index aeff6d6..eb039b4 100755
--- a/configure
+++ b/configure
@@ -7410,9 +7410,11 @@
+
for ac_header in X11/XKBlib.h \
X11/Xutil.h \
X11/extensions/shape.h \
+ X11/extensions/XInput.h \
X11/extensions/XShm.h \
X11/extensions/Xrandr.h \
X11/extensions/Xrender.h \
@@ -14333,6 +14335,80 @@
_ACEOF
fi
+echo "$as_me:$LINENO: checking for -lXi soname" >&5
+echo $ECHO_N "checking for -lXi soname... $ECHO_C" >&6
+if test "${ac_cv_lib_soname_Xi+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_get_soname_save_LIBS=$LIBS
+LIBS="-lXi $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XOpenDevice ();
+int
+main ()
+{
+XOpenDevice ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_soname_Xi=`$ac_cv_path_LDD conftest$ac_exeext | grep libXi\\.so | sed 's/^.*\(libXi\.so[^ ]*\).*$/\1/'`
+ if test "x$ac_cv_lib_soname_Xi" = "x"
+ then
+ ac_cv_lib_soname_Xi="libXi.so"
+ fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_soname_Xi="libXi.so"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_get_soname_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_soname_Xi" >&5
+echo "${ECHO_T}$ac_cv_lib_soname_Xi" >&6
+if test "x$ac_cv_lib_soname_Xi" != xNONE
+then
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBXI "$ac_cv_lib_soname_Xi"
+_ACEOF
+fi
+
echo "$as_me:$LINENO: checking for -lXrender soname" >&5
echo $ECHO_N "checking for -lXrender soname... $ECHO_C" >&6
if test "${ac_cv_lib_soname_Xrender+set}" = set; then
diff --git a/configure.ac b/configure.ac
index b641220..ed5167f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -181,6 +181,7 @@
AC_CHECK_HEADERS([X11/XKBlib.h \
X11/Xutil.h \
X11/extensions/shape.h \
+ X11/extensions/XInput.h \
X11/extensions/XShm.h \
X11/extensions/Xrandr.h \
X11/extensions/Xrender.h \
@@ -989,6 +990,7 @@
then
WINE_GET_SONAME(X11,XCreateWindow,[$X_LIBS $X_EXTRA_LIBS])
WINE_GET_SONAME(Xext,XextCreateExtension,[$X_LIBS -lX11 $X_EXTRA_LIBS])
+ WINE_GET_SONAME(Xi,XOpenDevice,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
WINE_GET_SONAME(Xrender,XRenderQueryExtension,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
WINE_GET_SONAME(freetype,FT_Init_FreeType,[$X_LIBS])
WINE_GET_SONAME(GL,glXQueryExtension,[$X_LIBS $X_EXTRA_LIBS])
diff --git a/dlls/wintab32/Makefile.in b/dlls/wintab32/Makefile.in
index dc76768..2276728 100644
--- a/dlls/wintab32/Makefile.in
+++ b/dlls/wintab32/Makefile.in
@@ -3,14 +3,15 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = wintab32.dll
-IMPORTS = kernel32
+IMPORTS = user32 kernel32
ALTNAMES = wintab.dll
SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
C_SRCS = \
context.c \
- manager.c
+ manager.c \
+ wintab32.c
C_SRCS16 = \
wintab16.c
diff --git a/dlls/wintab32/context.c b/dlls/wintab32/context.c
index 9071837..7e41396 100644
--- a/dlls/wintab32/context.c
+++ b/dlls/wintab32/context.c
@@ -2,6 +2,7 @@
* Tablet Context
*
* Copyright 2002 Patrik Stridvall
+ * Copyright 2003 CodeWeavers, Aric Stewart
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,29 +20,333 @@
*/
#include "config.h"
-
+#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
#include "windef.h"
-#include "winbase.h"
#include "winerror.h"
+#include "winbase.h"
+#include "winuser.h"
#include "wintab.h"
+#include "wintab_internal.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
+/*
+ * Documentation found at
+ * http://www.csl.sony.co.jp/projects/ar/restricted/wintabl.html
+ */
+
+static BOOL gLoaded;
+static LPOPENCONTEXT gOpenContexts;
+static HCTX gTopContext = (HCTX)0xc00;
+
+static char* DUMPBITS(int x, char* buf)
+{
+ strcpy(buf,"{");
+ if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
+ if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
+ if (x&PK_TIME) strcat(buf, "PK_TIME ");
+ if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
+ if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
+ if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
+ if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
+ if (x&PK_X) strcat(buf, "PK_X ");
+ if (x&PK_Y) strcat(buf, "PK_Y ");
+ if (x&PK_Z) strcat(buf, "PK_Z ");
+ if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
+ if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
+ if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
+ if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
+ strcat(buf, "}");
+ return buf;
+}
+
+static inline void DUMPPACKET(WTPACKET packet)
+{
+ TRACE("pkContext: 0x%x pkStatus: 0x%x pkTime : 0x%x pkChanged: 0x%x pkSerialNumber: 0x%x pkCursor : %i pkButtons: %x pkX: %li pkY: %li pkZ: %li pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n"
+,(UINT)packet.pkContext,
+ (UINT)packet.pkStatus,
+ (UINT)packet.pkTime,
+ (UINT)packet.pkChanged,
+ packet.pkSerialNumber,
+ packet.pkCursor,
+ (UINT)packet.pkButtons,
+ packet.pkX,
+ packet.pkY,
+ packet.pkZ,
+ packet.pkNormalPressure,
+ packet.pkTangentPressure,
+ packet.pkOrientation.orAzimuth,
+ packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
+ packet.pkRotation.roPitch,
+ packet.pkRotation.roRoll, packet.pkRotation.roYaw);
+}
+
+static inline void DUMPCONTEXT(LOGCONTEXTA lc)
+{
+ CHAR mmsg[4000];
+ CHAR bits[100];
+ CHAR bits1[100];
+ CHAR bits2[100];
+
+ sprintf(mmsg,"%s, %x, %x, %x, %x, %x, %x, %x%s, %x%s, %x%s, %x, %x, %i, %i, %i, %li ,%li, %li, %li, %li, %li,%li, %li, %li, %li, %li, %li, %i, %i, %i, %i, %i %li %li\n",
+ debugstr_a(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
+lc.lcDevice, lc.lcPktRate, (UINT)lc.lcPktData, DUMPBITS(lc.lcPktData,bits),
+(UINT)lc.lcPktMode, DUMPBITS(lc.lcPktMode,bits1), (UINT)lc.lcMoveMask,
+DUMPBITS(lc.lcMoveMask,bits2), (INT)lc.lcBtnDnMask, (INT)lc.lcBtnUpMask,
+(INT)lc.lcInOrgX, (INT)lc.lcInOrgY, (INT)lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
+lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
+lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
+lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
+lc.lcSysSensY);
+ TRACE("context: %s",mmsg);
+}
+
+
+/* Find an open context given the handle */
+static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
+{
+ LPOPENCONTEXT ptr = gOpenContexts;
+ while (ptr)
+ {
+ if (ptr->handle == hCtx) return ptr;
+ ptr = ptr->next;
+ }
+ return NULL;
+}
+
+static void LoadTablet()
+{
+ TRACE("Initilizing the tablet to hwnd %p\n",hwndDefault);
+ gLoaded= TRUE;
+ pLoadTabletInfo(hwndDefault);
+}
+
+int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
+ LPARAM lParam, BOOL send_always)
+{
+ if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
+ {
+ TRACE("Posting message %x to %x\n",msg, (UINT)newcontext->hwndOwner);
+ return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+static inline DWORD ScaleForContext(DWORD In, DWORD InOrg, DWORD InExt, DWORD
+ OutOrg, DWORD OutExt)
+{
+ if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
+ return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
+ else
+ return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
+}
+
+LPOPENCONTEXT FindOpenContext(HWND hwnd)
+{
+ LPOPENCONTEXT ptr;
+
+ EnterCriticalSection(&csTablet);
+ ptr = gOpenContexts;
+ while (ptr)
+ {
+ TRACE("Trying Context %p (%p %p)\n",ptr->handle,hwnd,ptr->hwndOwner);
+ if (ptr->hwndOwner == hwnd) break;
+ }
+ LeaveCriticalSection(&csTablet);
+ return ptr;
+}
+
+LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
+{
+ LPOPENCONTEXT ptr=NULL;
+
+ EnterCriticalSection(&csTablet);
+
+ ptr = gOpenContexts;
+ while (ptr)
+ {
+ TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
+
+ if (ptr->hwndOwner == hwnd)
+ {
+ int tgt;
+ if (!ptr->enabled)
+ {
+ ptr = ptr->next;
+ continue;
+ }
+
+ tgt = ptr->PacketsQueued;
+
+ packet->pkContext = ptr->handle;
+
+ /* translate packet data to the context */
+
+ /* Scale as per documentation */
+ packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
+ ptr->context.lcInExtY, ptr->context.lcOutOrgY,
+ ptr->context.lcOutExtY);
+
+ packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
+ ptr->context.lcInExtX, ptr->context.lcOutOrgX,
+ ptr->context.lcOutExtX);
+
+ /* flip the Y axis */
+ if (ptr->context.lcOutExtY > 0)
+ packet->pkY = ptr->context.lcOutExtY - packet->pkY;
+
+ DUMPPACKET(*packet);
+
+ if (tgt + 1 == ptr->QueueSize)
+ {
+ TRACE("Queue Overflow %p\n",ptr->handle);
+ packet->pkStatus = TPS_QUEUE_ERR;
+ }
+ else
+ {
+ TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
+ memcpy(&ptr->PacketQueue[tgt], packet, sizeof
+ (WTPACKET));
+ ptr->PacketsQueued++;
+
+ if (ptr->ActiveCursor != packet->pkCursor)
+ {
+ ptr->ActiveCursor = packet->pkCursor;
+ if (ptr->context.lcOptions & CXO_CSRMESSAGES)
+ TABLET_PostTabletMessage(ptr, WT_CSRCHANGE,
+ (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
+ FALSE);
+ }
+ }
+ break;
+ }
+ ptr = ptr->next;
+ }
+ LeaveCriticalSection(&csTablet);
+ TRACE("Done (%p)\n",ptr);
+ return ptr;
+}
+
+int static inline CopyTabletData(LPVOID target, LPVOID src, INT size)
+{
+ memcpy(target,src,size);
+ return(size);
+}
+
+static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
+ LPWTPACKET *pkt)
+{
+ int loop;
+ int index = -1;
+ for (loop = 0; loop < context->PacketsQueued; loop++)
+ if (context->PacketQueue[loop].pkSerialNumber == wSerial)
+ {
+ index = loop;
+ *pkt = &context->PacketQueue[loop];
+ break;
+ }
+
+ TRACE("%i .. %i\n",context->PacketsQueued,index);
+
+ return index;
+}
+
+
+static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
+ LPWTPACKET wtp)
+{
+ LPBYTE ptr;
+ CHAR bits[100];
+
+ ptr = lpPkt;
+ TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData,bits));
+
+ if (context->context.lcPktData & PK_CONTEXT)
+ ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
+ if (context->context.lcPktData & PK_STATUS)
+ ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
+ if (context->context.lcPktData & PK_TIME)
+ ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
+ if (context->context.lcPktData & PK_CHANGED)
+ ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
+ if (context->context.lcPktData & PK_SERIAL_NUMBER)
+ ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
+ if (context->context.lcPktData & PK_CURSOR)
+ ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
+ if (context->context.lcPktData & PK_BUTTONS)
+ ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
+ if (context->context.lcPktData & PK_X)
+ ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
+ if (context->context.lcPktData & PK_Y)
+ ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
+ if (context->context.lcPktData & PK_Z)
+ ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
+ if (context->context.lcPktData & PK_NORMAL_PRESSURE)
+ ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
+ if (context->context.lcPktData & PK_TANGENT_PRESSURE)
+ ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
+ if (context->context.lcPktData & PK_ORIENTATION)
+ ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
+ if (context->context.lcPktData & PK_ROTATION)
+ ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
+
+ /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
+ return ptr;
+}
+
+static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
+{
+ int rc = 0;
+
+ if (context->context.lcPktData & PK_CONTEXT)
+ rc +=sizeof(HCTX);
+ if (context->context.lcPktData & PK_STATUS)
+ rc +=sizeof(UINT);
+ if (context->context.lcPktData & PK_TIME)
+ rc += sizeof(LONG);
+ if (context->context.lcPktData & PK_CHANGED)
+ rc += sizeof(WTPKT);
+ if (context->context.lcPktData & PK_SERIAL_NUMBER)
+ rc += sizeof(UINT);
+ if (context->context.lcPktData & PK_CURSOR)
+ rc += sizeof(UINT);
+ if (context->context.lcPktData & PK_BUTTONS)
+ rc += sizeof(DWORD);
+ if (context->context.lcPktData & PK_X)
+ rc += sizeof(DWORD);
+ if (context->context.lcPktData & PK_Y)
+ rc += sizeof(DWORD);
+ if (context->context.lcPktData & PK_Z)
+ rc += sizeof(DWORD);
+ if (context->context.lcPktData & PK_NORMAL_PRESSURE)
+ rc += sizeof(UINT);
+ if (context->context.lcPktData & PK_TANGENT_PRESSURE)
+ rc += sizeof(UINT);
+ if (context->context.lcPktData & PK_ORIENTATION)
+ rc += sizeof(ORIENTATION);
+ if (context->context.lcPktData & PK_ROTATION)
+ rc += sizeof(ROTATION);
+
+ rc *= n;
+ memset(lpPkt,0,rc);
+}
+
+
/***********************************************************************
* WTInfoA (WINTAB32.20)
*/
UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
{
- FIXME("(%u, %u, %p): stub\n", wCategory, nIndex, lpOutput);
+ if (gLoaded == FALSE)
+ LoadTablet();
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-
- return 0;
+ return pWTInfoA( wCategory, nIndex, lpOutput );
}
/***********************************************************************
@@ -61,11 +366,38 @@
*/
HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
{
- FIXME("(%p, %p, %u): stub\n", hWnd, lpLogCtx, fEnable);
+ LPOPENCONTEXT newcontext;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
+ DUMPCONTEXT(*lpLogCtx);
- return NULL;
+ newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
+ memcpy(&(newcontext->context),lpLogCtx,sizeof(LOGCONTEXTA));
+ newcontext->hwndOwner = hWnd;
+ newcontext->enabled = fEnable;
+ newcontext->ActiveCursor = -1;
+ newcontext->QueueSize = 10;
+ newcontext->PacketsQueued = 0;
+ newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
+
+ EnterCriticalSection(&csTablet);
+ newcontext->handle = gTopContext++;
+ newcontext->next = gOpenContexts;
+ gOpenContexts = newcontext;
+ LeaveCriticalSection(&csTablet);
+
+ pAttachEventQueueToTablet(hWnd);
+
+ TABLET_PostTabletMessage(newcontext, WT_CTXOPEN, (WPARAM)newcontext->handle,
+ newcontext->context.lcStatus, TRUE);
+
+ newcontext->context.lcStatus = CXS_ONTOP;
+
+ TABLET_PostTabletMessage(newcontext, WT_CTXOVERLAP,
+ (WPARAM)newcontext->handle,
+ newcontext->context.lcStatus, TRUE);
+
+ return newcontext->handle;
}
/***********************************************************************
@@ -85,9 +417,37 @@
*/
BOOL WINAPI WTClose(HCTX hCtx)
{
- FIXME("(%p): stub\n", hCtx);
+ LPOPENCONTEXT context,ptr;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p)\n", hCtx);
+
+ EnterCriticalSection(&csTablet);
+
+ ptr = context = gOpenContexts;
+
+ while (context && (context->handle != hCtx))
+ {
+ ptr = context;
+ context = context->next;
+ }
+ if (!context)
+ {
+ LeaveCriticalSection(&csTablet);
+ return TRUE;
+ }
+
+ if (context == gOpenContexts)
+ gOpenContexts = context->next;
+ else
+ ptr->next = context->next;
+
+ LeaveCriticalSection(&csTablet);
+
+ TABLET_PostTabletMessage(context, WT_CTXCLOSE, (WPARAM)context->handle,
+ context->context.lcStatus,TRUE);
+
+ HeapFree(GetProcessHeap(),0,context->PacketQueue);
+ HeapFree(GetProcessHeap(),0,context);
return TRUE;
}
@@ -97,11 +457,39 @@
*/
int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
{
- FIXME("(%p, %d, %p): stub\n", hCtx, cMaxPkts, lpPkts);
+ int limit;
+ LPOPENCONTEXT context;
+ LPVOID ptr = lpPkts;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
- return 0;
+ if (!hCtx || !lpPkts) return 0;
+
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+ TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
+
+ if (context->PacketsQueued == 0)
+ {
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ for(limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
+ ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
+
+ if (limit < context->PacketsQueued)
+ {
+ memcpy(context->PacketQueue, &context->PacketQueue[limit],
+ (context->QueueSize - (limit))*sizeof(WTPACKET));
+ }
+ context->PacketsQueued -= limit;
+ LeaveCriticalSection(&csTablet);
+
+ TRACE("Copied %i packets\n",limit);
+
+ return limit;
}
/***********************************************************************
@@ -109,11 +497,36 @@
*/
BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
{
- FIXME("(%p, %d, %p): stub\n", hCtx, wSerial, lpPkt);
+ int rc = 0;
+ LPOPENCONTEXT context;
+ LPWTPACKET wtp;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
- return FALSE;
+ if (!hCtx) return 0;
+
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ rc = TABLET_FindPacket(context ,wSerial, &wtp);
+
+ if (rc >= 0)
+ {
+ if (lpPkt)
+ TABLET_CopyPacketData(context ,lpPkt, wtp);
+
+ if ((rc+1) < context->QueueSize)
+ {
+ memcpy(context->PacketQueue, &context->PacketQueue[rc+1],
+ (context->QueueSize - (rc+1))*sizeof(WTPACKET));
+ }
+ context->PacketsQueued -= (rc+1);
+ }
+ LeaveCriticalSection(&csTablet);
+
+ TRACE("Returning %i\n",rc+1);
+ return rc+1;
}
/***********************************************************************
@@ -121,11 +534,18 @@
*/
BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
{
- FIXME("(%p, %u): stub\n", hCtx, fEnable);
+ LPOPENCONTEXT context;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %u)\n", hCtx, fEnable);
- return FALSE;
+ if (!hCtx) return 0;
+
+ EnterCriticalSection(&csTablet);
+ context = TABLET_FindOpenContext(hCtx);
+ context->enabled = fEnable;
+ LeaveCriticalSection(&csTablet);
+
+ return TRUE;
}
/***********************************************************************
@@ -135,9 +555,7 @@
{
FIXME("(%p, %u): stub\n", hCtx, fToTop);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-
- return FALSE;
+ return TRUE;
}
/***********************************************************************
@@ -157,11 +575,18 @@
*/
BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
{
- FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
+ LPOPENCONTEXT context;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %p)\n", hCtx, lpLogCtx);
- return FALSE;
+ if (!hCtx) return 0;
+
+ EnterCriticalSection(&csTablet);
+ context = TABLET_FindOpenContext(hCtx);
+ memcpy(lpLogCtx,&context->context,sizeof(LOGCONTEXTA));
+ LeaveCriticalSection(&csTablet);
+
+ return TRUE;
}
/***********************************************************************
@@ -253,11 +678,30 @@
*/
int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
{
- FIXME("(%p, %d, %p): stub\n", hCtx, cMaxPkts, lpPkts);
+ int limit;
+ LPOPENCONTEXT context;
+ LPVOID ptr = lpPkts;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
- return 0;
+ if (!hCtx || !lpPkts) return 0;
+
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ if (context->PacketsQueued == 0)
+ {
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
+ ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
+
+ LeaveCriticalSection(&csTablet);
+ TRACE("Copied %i packets\n",limit);
+ return limit;
}
/***********************************************************************
@@ -266,12 +710,56 @@
int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
{
- FIXME("(%p, %u, %u, %d, %p, %p): stub\n",
+ LPOPENCONTEXT context;
+ LPVOID ptr = lpPkts;
+ UINT bgn = 0;
+ UINT end = 0;
+ UINT num = 0;
+
+ TRACE("(%p, %u, %u, %d, %p, %p)\n",
hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ if (!hCtx) return 0;
- return 0;
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ if (context->PacketsQueued == 0)
+ {
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ while (bgn < context->PacketsQueued &&
+ context->PacketQueue[bgn].pkSerialNumber != wBegin)
+ bgn++;
+
+ end = bgn;
+ while (end < context->PacketsQueued &&
+ context->PacketQueue[end].pkSerialNumber != wEnd)
+ end++;
+
+ if (bgn == end == context->PacketsQueued)
+ {
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ for (num = bgn; num <= end; num++)
+ ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[end]);
+
+ /* remove read packets */
+ if ((end+1) < context->PacketsQueued)
+ memcpy( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
+ (context->PacketsQueued - ((end-bgn)+1)) * sizeof (WTPACKET));
+
+ context->PacketsQueued -= ((end-bgn)+1);
+ *lpNPkts = ((end-bgn)+1);
+
+ LeaveCriticalSection(&csTablet);
+ TRACE("Copied %i packets\n",*lpNPkts);
+ return (end - bgn)+1;
}
/***********************************************************************
@@ -280,12 +768,51 @@
int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
{
- FIXME("(%p, %u, %u, %d, %p, %p): stub\n",
+ LPOPENCONTEXT context;
+ LPVOID ptr = lpPkts;
+ UINT bgn = 0;
+ UINT end = 0;
+ UINT num = 0;
+
+ TRACE("(%p, %u, %u, %d, %p, %p)\n",
hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ if (!hCtx) return 0;
- return 0;
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ if (context->PacketsQueued == 0)
+ {
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ while (bgn < context->PacketsQueued &&
+ context->PacketQueue[bgn].pkSerialNumber != wBegin)
+ bgn++;
+
+ end = bgn;
+ while (end < context->PacketsQueued &&
+ context->PacketQueue[end].pkSerialNumber != wEnd)
+ end++;
+
+ if (bgn == context->PacketsQueued || end == context->PacketsQueued)
+ {
+ TRACE("%i %i %i \n", bgn, end, context->PacketsQueued);
+ LeaveCriticalSection(&csTablet);
+ return 0;
+ }
+
+ for (num = bgn; num <= end; num++)
+ ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[end]);
+
+ *lpNPkts = ((end-bgn)+1);
+ LeaveCriticalSection(&csTablet);
+
+ TRACE("Copied %i packets\n",*lpNPkts);
+ return (end - bgn)+1;
}
/***********************************************************************
@@ -293,9 +820,28 @@
*/
BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
{
- FIXME("(%p, %p, %p): stub\n", hCtx, lpOld, lpNew);
+ LPOPENCONTEXT context;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
+
+ if (!hCtx) return 0;
+
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ if (context->PacketsQueued)
+ {
+ *lpOld = context->PacketQueue[0].pkSerialNumber;
+ *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
+ }
+ else
+ {
+ TRACE("No packets\n");
+ LeaveCriticalSection(&csTablet);
+ return FALSE;
+ }
+ LeaveCriticalSection(&csTablet);
return TRUE;
}
@@ -305,11 +851,15 @@
*/
int WINAPI WTQueueSizeGet(HCTX hCtx)
{
- FIXME("(%p): stub\n", hCtx);
+ LPOPENCONTEXT context;
+ TRACE("(%p)\n", hCtx);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ if (!hCtx) return 0;
- return 0;
+ EnterCriticalSection(&csTablet);
+ context = TABLET_FindOpenContext(hCtx);
+ LeaveCriticalSection(&csTablet);
+ return context->QueueSize;
}
/***********************************************************************
@@ -317,9 +867,21 @@
*/
BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
{
- FIXME("(%p, %d): stub\n", hCtx, nPkts);
+ LPOPENCONTEXT context;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ TRACE("(%p, %d)\n", hCtx, nPkts);
- return 0;
+ if (!hCtx) return 0;
+
+ EnterCriticalSection(&csTablet);
+
+ context = TABLET_FindOpenContext(hCtx);
+
+ context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
+ context->PacketQueue, sizeof(WTPACKET)*nPkts);
+
+ context->QueueSize = nPkts;
+ LeaveCriticalSection(&csTablet);
+
+ return nPkts;
}
diff --git a/dlls/wintab32/wintab32.c b/dlls/wintab32/wintab32.c
new file mode 100644
index 0000000..7df0b87
--- /dev/null
+++ b/dlls/wintab32/wintab32.c
@@ -0,0 +1,148 @@
+/*
+ * WinTab32 library
+ *
+ * Copyright 2003 CodeWeavers, Aric Stewart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "wintab.h"
+#include "wintab_internal.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
+
+HWND hwndDefault = NULL;
+static const WCHAR
+ WC_TABLETCLASSNAME[] = {'W','i','n','e','T','a','b','l','e','t','C','l','a','s','s',0};
+CRITICAL_SECTION csTablet;
+
+int (*pLoadTabletInfo)(HWND hwnddefault) = NULL;
+int (*pGetCurrentPacket)(LPWTPACKET packet) = NULL;
+int (*pAttachEventQueueToTablet)(HWND hOwner) = NULL;
+UINT (*pWTInfoA)(UINT wCategory, UINT nIndex, LPVOID lpOutput) = NULL;
+
+static LRESULT WINAPI TABLET_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+
+static VOID TABLET_Register()
+{
+ WNDCLASSW wndClass;
+ ZeroMemory(&wndClass, sizeof(WNDCLASSW));
+ wndClass.style = CS_GLOBALCLASS;
+ wndClass.lpfnWndProc = TABLET_WindowProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hCursor = (HCURSOR)NULL;
+ wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
+ wndClass.lpszClassName = WC_TABLETCLASSNAME;
+ RegisterClassW(&wndClass);
+}
+
+static VOID TABLET_Unregister()
+{
+ UnregisterClassW(WC_TABLETCLASSNAME, (HINSTANCE)NULL);
+}
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+ static const WCHAR name[] = {'T','a','b','l','e','t',0};
+ HMODULE hx11drv;
+
+ TRACE("%p, %lx, %p\n",hInstDLL,fdwReason,lpReserved);
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ TRACE("Initialization\n");
+ InitializeCriticalSection(&csTablet);
+ hx11drv = GetModuleHandleA("x11drv.dll");
+ if (hx11drv)
+ {
+ pLoadTabletInfo = (void *)GetProcAddress(hx11drv, "LoadTabletInfo");
+ pAttachEventQueueToTablet = (void *)GetProcAddress(hx11drv, "AttachEventQueueToTablet");
+ pGetCurrentPacket = (void *)GetProcAddress(hx11drv, "GetCurrentPacket");
+ pWTInfoA = (void *)GetProcAddress(hx11drv, "WTInfoA");
+ TABLET_Register();
+ hwndDefault = CreateWindowW(WC_TABLETCLASSNAME, name,
+ WS_POPUPWINDOW,0,0,0,0,0,0,hInstDLL,0);
+ }
+ else
+ return FALSE;
+ break;
+ case DLL_PROCESS_DETACH:
+ TRACE("Detaching\n");
+ if (hwndDefault)
+ {
+ DestroyWindow(hwndDefault);
+ hwndDefault = 0;
+ }
+ TABLET_Unregister();
+ DeleteCriticalSection(&csTablet);
+ break;
+ }
+ return TRUE;
+}
+
+
+/*
+ * The window proc for the default TABLET window
+ */
+static LRESULT WINAPI TABLET_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam)
+{
+ TRACE("Incomming Message 0x%x (0x%08x, 0x%08x)\n", uMsg, (UINT)wParam,
+ (UINT)lParam);
+
+ switch(uMsg)
+ {
+ case WM_NCCREATE:
+ return TRUE;
+
+ case WT_PACKET:
+ {
+ WTPACKET packet;
+ LPOPENCONTEXT handler;
+ pGetCurrentPacket(&packet);
+ handler = AddPacketToContextQueue(&packet,(HWND)lParam);
+ if (handler)
+ TABLET_PostTabletMessage(handler, WT_PACKET,
+ (WPARAM)packet.pkSerialNumber,
+ (LPARAM)handler->handle, FALSE);
+ break;
+ }
+ case WT_PROXIMITY:
+ {
+ LPOPENCONTEXT handler;
+ LPARAM prox;
+ handler = FindOpenContext((HWND)lParam);
+ if (handler)
+ {
+ prox = MAKELPARAM( wParam, 1 );
+ TABLET_PostTabletMessage(handler, WT_PROXIMITY,
+ (WPARAM)handler->handle, (LPARAM)prox,
+ TRUE);
+ }
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/dlls/wintab32/wintab_internal.h b/dlls/wintab32/wintab_internal.h
new file mode 100644
index 0000000..c8511b1
--- /dev/null
+++ b/dlls/wintab32/wintab_internal.h
@@ -0,0 +1,163 @@
+/*
+ * Tablet header
+ *
+ * Copyright 2003 CodeWeavers (Aric Stewart)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __WINE_WINTAB_INTERNAL_H
+#define __WINE_WINTAB_INTERNAL_H
+
+typedef struct tagWTI_INTERFACE_INFO {
+ CHAR WINTABID[1024];
+ /* a copy of the null-terminated tablet hardware identification string
+ * in the user buffer. This string should include make, model, and
+ * revision information in user-readable format.
+ */
+ WORD SPECVERSION;
+ /* the specification version number. The high-order byte contains the
+ * major version number; the low-order byte contains the minor version
+ * number.
+ */
+ WORD IMPLVERSION;
+ /* the implementation version number. The high-order byte contains the
+ * major version number; the low-order byte contains the minor version
+ * number.
+ */
+ UINT NDEVICES;
+ /* the number of devices supported. */
+ UINT NCURSORS;
+ /* the total number of cursor types supported. */
+ UINT NCONTEXTS;
+ /* the number of contexts supported. */
+ UINT CTXOPTIONS;
+ /* flags indicating which context options are supported */
+ UINT CTXSAVESIZE;
+ /* the size of the save information returned from WTSave.*/
+ UINT NEXTENSIONS;
+ /* the number of extension data items supported.*/
+ UINT NMANAGERS;
+ /* the number of manager handles supported.*/
+ }WTI_INTERFACE_INFO, *LPWTI_INTERFACE_INFO;
+
+typedef struct tagWTI_STATUS_INFO{
+ UINT CONTEXTS;
+ /* the number of contexts currently open.*/
+ UINT SYSCTXS;
+ /* the number of system contexts currently open.*/
+ UINT PKTRATE;
+ /* the maximum packet report rate currently being received by any
+ * context, in Hertz.
+ */
+ WTPKT PKTDATA;
+ /* a mask indicating which packet data items are requested by at
+ * least one context.
+ */
+ UINT MANAGERS;
+ /* the number of manager handles currently open.*/
+ BOOL SYSTEM;
+ /* a non-zero value if system pointing is available to the whole
+ * screen; zero otherwise.
+ */
+ DWORD BUTTONUSE;
+ /* a button mask indicating the logical buttons whose events are
+ * requested by at least one context.
+ */
+ DWORD SYSBTNUSE;
+ /* a button mask indicating which logical buttons are assigned a system
+ * button function by the current cursor's system button map.
+ */
+} WTI_STATUS_INFO, *LPWTI_STATUS_INFO;
+
+typedef struct tagWTI_EXTENSIONS_INFO
+{
+ CHAR NAME[256];
+ /* a unique, null-terminated string describing the extension.*/
+ UINT TAG;
+ /* a unique identifier for the extension. */
+ WTPKT MASK;
+ /* a mask that can be bitwise OR'ed with WTPKT-type variables to select
+ * the extension.
+ */
+ UINT SIZE[2];
+ /* an array of two UINTs specifying the extension's size within a packet
+ * (in bytes). The first is for absolute mode; the second is for
+ * relative mode.
+ */
+ AXIS *AXES;
+ /* an array of axis descriptions, as needed for the extension. */
+ BYTE *DEFAULT;
+ /* the current global default data, as needed for the extension. This
+ * data is modified via the WTMgrExt function.
+ */
+ BYTE *DEFCONTEXT;
+ BYTE *DEFSYSCTX;
+ /* the current default context-specific data, as needed for the
+ * extension. The indices identify the digitizing- and system-context
+ * defaults, respectively.
+ */
+ BYTE *CURSORS;
+ /* Is the first of one or more consecutive indices, one per cursor type.
+ * Each returns the current default cursor-specific data, as need for
+ * the extension. This data is modified via the WTMgrCsrExt function.
+ */
+} WTI_EXTENSIONS_INFO, *LPWTI_EXTENSIONS_INFO;
+
+typedef struct tagWTPACKET {
+ HCTX pkContext;
+ UINT pkStatus;
+ LONG pkTime;
+ WTPKT pkChanged;
+ UINT pkSerialNumber;
+ UINT pkCursor;
+ DWORD pkButtons;
+ DWORD pkX;
+ DWORD pkY;
+ DWORD pkZ;
+ UINT pkNormalPressure;
+ UINT pkTangentPressure;
+ ORIENTATION pkOrientation;
+ ROTATION pkRotation; /* 1.1 */
+} WTPACKET, *LPWTPACKET;
+
+typedef struct tagOPENCONTEXT
+{
+ HCTX handle;
+ LOGCONTEXTA context;
+ HWND hwndOwner;
+ BOOL enabled;
+ INT ActiveCursor;
+ INT QueueSize;
+ INT PacketsQueued;
+ LPWTPACKET PacketQueue;
+ struct tagOPENCONTEXT *next;
+} OPENCONTEXT, *LPOPENCONTEXT;
+
+int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
+ LPARAM lParam, BOOL send_always);
+LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd);
+LPOPENCONTEXT FindOpenContext(HWND hwnd);
+
+/* X11drv functions */
+extern int (*pLoadTabletInfo)(HWND hwnddefault);
+extern int (*pGetCurrentPacket)(LPWTPACKET packet);
+extern int (*pAttachEventQueueToTablet)(HWND hOwner);
+extern UINT (*pWTInfoA)(UINT wCategory, UINT nIndex, LPVOID lpOutput);
+
+extern HWND hwndDefault;
+extern CRITICAL_SECTION csTablet;
+
+#endif /* __WINE_WINTAB_INTERNAL_H */
diff --git a/dlls/x11drv/Makefile.in b/dlls/x11drv/Makefile.in
index 240f18f..87fc20e 100644
--- a/dlls/x11drv/Makefile.in
+++ b/dlls/x11drv/Makefile.in
@@ -34,6 +34,7 @@
text.c \
window.c \
winpos.c \
+ wintab.c \
x11ddraw.c \
x11drv_main.c \
xdnd.c \
diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c
index eea433f..c1eef95 100644
--- a/dlls/x11drv/event.c
+++ b/dlls/x11drv/event.c
@@ -274,9 +274,18 @@
if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
WARN( "Got event %s for unknown Window %08lx\n",
event_names[event->type], event->xany.window );
+ else if (event->type <= MappingNotify)
+ TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
+ event_names[event->type], hWnd, event->xany.window, GetFocus() );
else
- TRACE("Got event %s for hwnd %p\n",
- event_names[event->type], hWnd );
+ TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
+ hWnd, event->xany.window, GetFocus() );
+
+ if (X11DRV_ProcessTabletEvent(hWnd, event))
+ {
+ TRACE("Return: filtered by tablet\n");
+ return;
+ }
switch(event->type)
{
diff --git a/dlls/x11drv/wintab.c b/dlls/x11drv/wintab.c
new file mode 100644
index 0000000..71fe01f
--- /dev/null
+++ b/dlls/x11drv/wintab.c
@@ -0,0 +1,1161 @@
+/*
+ * X11 tablet driver
+ *
+ * Copyright 2003 CodeWeavers (Aric Stewart)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+
+#include "windef.h"
+#include "x11drv.h"
+#include "wine/debug.h"
+#include "wintab.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
+WINE_DECLARE_DEBUG_CHANNEL(event);
+
+typedef struct tagWTI_CURSORS_INFO
+{
+ CHAR NAME[256];
+ /* a displayable zero-terminated string containing the name of the
+ * cursor.
+ */
+ BOOL ACTIVE;
+ /* whether the cursor is currently connected. */
+ WTPKT PKTDATA;
+ /* a bit mask indicating the packet data items supported when this
+ * cursor is connected.
+ */
+ BYTE BUTTONS;
+ /* the number of buttons on this cursor. */
+ BYTE BUTTONBITS;
+ /* the number of bits of raw button data returned by the hardware.*/
+ CHAR BTNNAMES[1024]; /* FIXME: make this dynamic */
+ /* a list of zero-terminated strings containing the names of the
+ * cursor's buttons. The number of names in the list is the same as the
+ * number of buttons on the cursor. The names are separated by a single
+ * zero character; the list is terminated by two zero characters.
+ */
+ BYTE BUTTONMAP[32];
+ /* a 32 byte array of logical button numbers, one for each physical
+ * button.
+ */
+ BYTE SYSBTNMAP[32];
+ /* a 32 byte array of button action codes, one for each logical
+ * button.
+ */
+ BYTE NPBUTTON;
+ /* the physical button number of the button that is controlled by normal
+ * pressure.
+ */
+ UINT NPBTNMARKS[2];
+ /* an array of two UINTs, specifying the button marks for the normal
+ * pressure button. The first UINT contains the release mark; the second
+ * contains the press mark.
+ */
+ UINT *NPRESPONSE;
+ /* an array of UINTs describing the pressure response curve for normal
+ * pressure.
+ */
+ BYTE TPBUTTON;
+ /* the physical button number of the button that is controlled by
+ * tangential pressure.
+ */
+ UINT TPBTNMARKS[2];
+ /* an array of two UINTs, specifying the button marks for the tangential
+ * pressure button. The first UINT contains the release mark; the second
+ * contains the press mark.
+ */
+ UINT *TPRESPONSE;
+ /* an array of UINTs describing the pressure response curve for
+ * tangential pressure.
+ */
+ DWORD PHYSID;
+ /* a manufacturer-specific physical identifier for the cursor. This
+ * value will distinguish the physical cursor from others on the same
+ * device. This physical identifier allows applications to bind
+ * functions to specific physical cursors, even if category numbers
+ * change and multiple, otherwise identical, physical cursors are
+ * present.
+ */
+ UINT MODE;
+ /* the cursor mode number of this cursor type, if this cursor type has
+ * the CRC_MULTIMODE capability.
+ */
+ UINT MINPKTDATA;
+ /* the minimum set of data available from a physical cursor in this
+ * cursor type, if this cursor type has the CRC_AGGREGATE capability.
+ */
+ UINT MINBUTTONS;
+ /* the minimum number of buttons of physical cursors in the cursor type,
+ * if this cursor type has the CRC_AGGREGATE capability.
+ */
+ UINT CAPABILITIES;
+ /* flags indicating cursor capabilities, as defined below:
+ CRC_MULTIMODE
+ Indicates this cursor type describes one of several modes of a
+ single physical cursor. Consecutive cursor type categories
+ describe the modes; the CSR_MODE data item gives the mode number
+ of each cursor type.
+ CRC_AGGREGATE
+ Indicates this cursor type describes several physical cursors
+ that cannot be distinguished by software.
+ CRC_INVERT
+ Indicates this cursor type describes the physical cursor in its
+ inverted orientation; the previous consecutive cursor type
+ category describes the normal orientation.
+ */
+ UINT TYPE;
+ /* Manufacturer Unique id for the item type */
+} WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
+
+
+typedef struct tagWTI_DEVICES_INFO
+{
+ CHAR NAME[256];
+ /* a displayable null- terminated string describing the device,
+ * manufacturer, and revision level.
+ */
+ UINT HARDWARE;
+ /* flags indicating hardware and driver capabilities, as defined
+ * below:
+ HWC_INTEGRATED:
+ Indicates that the display and digitizer share the same surface.
+ HWC_TOUCH
+ Indicates that the cursor must be in physical contact with the
+ device to report position.
+ HWC_HARDPROX
+ Indicates that device can generate events when the cursor is
+ entering and leaving the physical detection range.
+ HWC_PHYSID_CURSORS
+ Indicates that device can uniquely identify the active cursor in
+ hardware.
+ */
+ UINT NCSRTYPES;
+ /* the number of supported cursor types.*/
+ UINT FIRSTCSR;
+ /* the first cursor type number for the device. */
+ UINT PKTRATE;
+ /* the maximum packet report rate in Hertz. */
+ WTPKT PKTDATA;
+ /* a bit mask indicating which packet data items are always available.*/
+ WTPKT PKTMODE;
+ /* a bit mask indicating which packet data items are physically
+ * relative, i.e., items for which the hardware can only report change,
+ * not absolute measurement.
+ */
+ WTPKT CSRDATA;
+ /* a bit mask indicating which packet data items are only available when
+ * certain cursors are connected. The individual cursor descriptions
+ * must be consulted to determine which cursors return which data.
+ */
+ INT XMARGIN;
+ INT YMARGIN;
+ INT ZMARGIN;
+ /* the size of tablet context margins in tablet native coordinates, in
+ * the x, y, and z directions, respectively.
+ */
+ AXIS X;
+ AXIS Y;
+ AXIS Z;
+ /* the tablet's range and resolution capabilities, in the x, y, and z
+ * axes, respectively.
+ */
+ AXIS NPRESSURE;
+ AXIS TPRESSURE;
+ /* the tablet's range and resolution capabilities, for the normal and
+ * tangential pressure inputs, respectively.
+ */
+ AXIS ORIENTATION[3];
+ /* a 3-element array describing the tablet's orientation range and
+ * resolution capabilities.
+ */
+ AXIS ROTATION[3];
+ /* a 3-element array describing the tablet's rotation range and
+ * resolution capabilities.
+ */
+ CHAR PNPID[256];
+ /* a null-terminated string containing the devices Plug and Play ID.*/
+} WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
+
+typedef struct tagWTPACKET {
+ HCTX pkContext;
+ UINT pkStatus;
+ LONG pkTime;
+ WTPKT pkChanged;
+ UINT pkSerialNumber;
+ UINT pkCursor;
+ DWORD pkButtons;
+ DWORD pkX;
+ DWORD pkY;
+ DWORD pkZ;
+ UINT pkNormalPressure;
+ UINT pkTangentPressure;
+ ORIENTATION pkOrientation;
+ ROTATION pkRotation; /* 1.1 */
+} WTPACKET, *LPWTPACKET;
+
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+
+static int motion_type = -1;
+static int button_press_type = -1;
+static int button_release_type = -1;
+static int key_press_type = -1;
+static int key_release_type = -1;
+static int proximity_in_type = -1;
+static int proximity_out_type = -1;
+
+static HWND hwndTabletDefault;
+static WTPACKET gMsgPacket;
+static DWORD gSerial;
+static INT button_state[10];
+
+#define CURSORMAX 10
+
+static LOGCONTEXTA gSysContext;
+static WTI_DEVICES_INFO gSysDevice;
+static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
+static INT gNumCursors;
+
+
+#ifndef SONAME_LIBXI
+#define SONAME_LIBXI "libXi.so"
+#endif
+
+/* XInput stuff */
+static void *xinput_handle;
+
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
+MAKE_FUNCPTR(XListInputDevices)
+MAKE_FUNCPTR(XOpenDevice)
+MAKE_FUNCPTR(XQueryDeviceState)
+MAKE_FUNCPTR(XGetDeviceButtonMapping)
+MAKE_FUNCPTR(XCloseDevice)
+MAKE_FUNCPTR(XSelectExtensionEvent)
+MAKE_FUNCPTR(XFreeDeviceState)
+#undef MAKE_FUNCPTR
+
+static INT X11DRV_XInput_Init(void)
+{
+ xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
+ if (xinput_handle)
+ {
+#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
+ LOAD_FUNCPTR(XListInputDevices)
+ LOAD_FUNCPTR(XOpenDevice)
+ LOAD_FUNCPTR(XGetDeviceButtonMapping)
+ LOAD_FUNCPTR(XCloseDevice)
+ LOAD_FUNCPTR(XSelectExtensionEvent)
+ LOAD_FUNCPTR(XQueryDeviceState)
+ LOAD_FUNCPTR(XFreeDeviceState)
+#undef LOAD_FUNCPTR
+ return 1;
+ }
+sym_not_found:
+ return 0;
+}
+
+void X11DRV_LoadTabletInfo(HWND hwnddefault)
+{
+ struct x11drv_thread_data *data = x11drv_thread_data();
+ int num_devices;
+ int loop;
+ int cursor_target;
+ XDeviceInfo *devices;
+ XDeviceInfo *target = NULL;
+ BOOL axis_read_complete= FALSE;
+
+ XAnyClassPtr any;
+ XButtonInfoPtr Button;
+ XValuatorInfoPtr Val;
+ XAxisInfoPtr Axis;
+
+ XDevice *opendevice;
+
+ if (!X11DRV_XInput_Init())
+ {
+ ERR("Unable to initialized the XInput library.\n");
+ return;
+ }
+
+ hwndTabletDefault = hwnddefault;
+
+ /* Do base initializaion */
+ strcpy(gSysContext.lcName, "Wine Tablet Context");
+ strcpy(gSysDevice.NAME,"Wine Tablet Device");
+
+ gSysContext.lcOptions = CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES;
+ gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
+ CXL_SENSITIVITY | CXL_SYSOUT;
+
+ gSysContext.lcMsgBase= WT_DEFBASE;
+ gSysContext.lcDevice = 0;
+ gSysContext.lcPktData =
+ PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
+ PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
+ gSysContext.lcMoveMask=
+ PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
+ gSysContext.lcStatus = CXS_ONTOP;
+ gSysContext.lcPktRate = 100;
+ gSysContext.lcBtnDnMask = 0xffffffff;
+ gSysContext.lcBtnUpMask = 0xffffffff;
+ gSysContext.lcSensX = 65536;
+ gSysContext.lcSensY = 65536;
+ gSysContext.lcSensX = 65536;
+ gSysContext.lcSensZ = 65536;
+ gSysContext.lcSysSensX= 65536;
+ gSysContext.lcSysSensY= 65536;
+
+ /* Device Defaults */
+ gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
+ gSysDevice.FIRSTCSR= 0;
+ gSysDevice.PKTRATE = 100;
+ gSysDevice.PKTDATA =
+ PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
+ PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
+ strcpy(gSysDevice.PNPID,"non-pluginplay");
+
+ wine_tsx11_lock();
+
+ cursor_target = -1;
+ devices = pXListInputDevices(data->display, &num_devices);
+ if (!devices)
+ {
+ WARN("XInput Extenstions reported as not avalable\n");
+ wine_tsx11_unlock();
+ return;
+ }
+ for (loop=0; loop < num_devices; loop++)
+ {
+ int class_loop;
+
+ TRACE("Trying device %i(%s)\n",loop,devices[loop].name);
+ if (devices[loop].use == IsXExtensionDevice)
+ {
+ LPWTI_CURSORS_INFO cursor;
+
+ TRACE("Is Extension Device\n");
+ cursor_target++;
+ target = &devices[loop];
+ cursor = &gSysCursor[cursor_target];
+
+ opendevice = pXOpenDevice(data->display,target->id);
+ if (opendevice)
+ {
+ unsigned char map[32];
+ int i;
+ int shft = 0;
+
+ pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
+
+ for (i=0; i< cursor->BUTTONS; i++,shft++)
+ {
+ cursor->BUTTONMAP[i] = map[i];
+ cursor->SYSBTNMAP[i] = (1<<shft);
+ }
+ pXCloseDevice(data->display, opendevice);
+ }
+ else
+ {
+ WARN("Unable to open device %s\n",target->name);
+ cursor_target --;
+ continue;
+ }
+
+ strcpy(cursor->NAME,target->name);
+
+ cursor->ACTIVE = 1;
+ cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
+ PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
+ PK_ORIENTATION;
+
+ cursor->PHYSID = cursor_target;
+ cursor->NPBUTTON = 1;
+ cursor->NPBTNMARKS[0] = 0 ;
+ cursor->NPBTNMARKS[1] = 1 ;
+ cursor->CAPABILITIES = 1;
+ if (strcasecmp(cursor->NAME,"stylus")==0)
+ cursor->TYPE = 0x4825;
+ if (strcasecmp(cursor->NAME,"eraser")==0)
+ cursor->TYPE = 0xc85a;
+
+
+ any = (XAnyClassPtr) (target->inputclassinfo);
+
+ for (class_loop = 0; class_loop < target->num_classes; class_loop++)
+ {
+ switch (any->class)
+ {
+ case ValuatorClass:
+ if (!axis_read_complete)
+ {
+ Val = (XValuatorInfoPtr) any;
+ Axis = (XAxisInfoPtr) ((char *) Val + sizeof
+ (XValuatorInfo));
+
+ if (Val->num_axes>=1)
+ {
+ /* Axis 1 is X */
+ gSysDevice.X.axMin = Axis->min_value;
+ gSysDevice.X.axMax= Axis->max_value;
+ gSysDevice.X.axUnits = 1;
+ gSysDevice.X.axResolution = Axis->resolution;
+ gSysContext.lcInOrgX = Axis->min_value;
+ gSysContext.lcSysOrgX = Axis->min_value;
+ gSysContext.lcInExtX = Axis->max_value;
+ gSysContext.lcSysExtX = Axis->max_value;
+ Axis++;
+ }
+ if (Val->num_axes>=2)
+ {
+ /* Axis 2 is Y */
+ gSysDevice.Y.axMin = Axis->min_value;
+ gSysDevice.Y.axMax= Axis->max_value;
+ gSysDevice.Y.axUnits = 1;
+ gSysDevice.Y.axResolution = Axis->resolution;
+ gSysContext.lcInOrgY = Axis->min_value;
+ gSysContext.lcSysOrgY = Axis->min_value;
+ gSysContext.lcInExtY = Axis->max_value;
+ gSysContext.lcSysExtY = Axis->max_value;
+ Axis++;
+ }
+ if (Val->num_axes>=3)
+ {
+ /* Axis 3 is Normal Pressure */
+ gSysDevice.NPRESSURE.axMin = Axis->min_value;
+ gSysDevice.NPRESSURE.axMax= Axis->max_value;
+ gSysDevice.NPRESSURE.axUnits = 1;
+ gSysDevice.NPRESSURE.axResolution =
+ Axis->resolution;
+ Axis++;
+ }
+ if (Val->num_axes >= 5)
+ {
+ /* Axis 4 and 5 are X and Y tilt */
+ XAxisInfoPtr XAxis = Axis;
+ Axis++;
+ if (max (abs(Axis->max_value),
+ abs(XAxis->max_value)))
+ {
+ gSysDevice.ORIENTATION[0].axMin = 0;
+ gSysDevice.ORIENTATION[0].axMax = 3600;
+ gSysDevice.ORIENTATION[0].axUnits = 1;
+ gSysDevice.ORIENTATION[0].axResolution =
+ 235929600;
+ gSysDevice.ORIENTATION[1].axMin = -1000;
+ gSysDevice.ORIENTATION[1].axMax = 1000;
+ gSysDevice.ORIENTATION[1].axUnits = 1;
+ gSysDevice.ORIENTATION[1].axResolution =
+ 235929600;
+ Axis++;
+ }
+ }
+ axis_read_complete = TRUE;
+ }
+ break;
+ case ButtonClass:
+ {
+ CHAR *ptr = cursor->BTNNAMES;
+ int i;
+
+ Button = (XButtonInfoPtr) any;
+ cursor->BUTTONS = Button->num_buttons;
+ for (i = 0; i < cursor->BUTTONS; i++)
+ {
+ strcpy(ptr,cursor->NAME);
+ ptr+=8;
+ }
+ }
+ break;
+ }
+ any = (XAnyClassPtr) ((char*) any + any->length);
+ }
+ }
+ }
+ wine_tsx11_unlock();
+ gSysDevice.NCSRTYPES = cursor_target+1;
+ gNumCursors = cursor_target+1;
+}
+
+static int figure_deg(int x, int y)
+{
+ int rc;
+
+ if (y != 0)
+ {
+ rc = (int) 10 * (atan( (FLOAT)abs(y) / (FLOAT)abs(x)) / (3.1415 / 180));
+ if (y>0)
+ {
+ if (x>0)
+ rc += 900;
+ else
+ rc = 2700 - rc;
+ }
+ else
+ {
+ if (x>0)
+ rc = 900 - rc;
+ else
+ rc += 2700;
+ }
+ }
+ else
+ {
+ if (x >= 0)
+ rc = 900;
+ else
+ rc = 2700;
+ }
+
+ return rc;
+}
+
+static int get_button_state(int deviceid)
+{
+ return button_state[deviceid];
+}
+
+static void set_button_state(XID deviceid)
+{
+ struct x11drv_thread_data *data = x11drv_thread_data();
+ XDevice *device;
+ XDeviceState *state;
+ XInputClass *class;
+ int loop;
+ int rc = 0;
+
+ wine_tsx11_lock();
+ device = pXOpenDevice(data->display,deviceid);
+ state = pXQueryDeviceState(data->display,device);
+
+ if (state)
+ {
+ class = state->data;
+ for (loop = 0; loop < state->num_classes; loop++)
+ {
+ if (class->class == ButtonClass)
+ {
+ int loop2;
+ XButtonState *button_state = (XButtonState*)class;
+ for (loop2 = 1; loop2 <= button_state->num_buttons; loop2++)
+ {
+ if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
+ {
+ rc |= (1<<(loop2-1));
+ }
+ }
+ }
+ class = (XInputClass *) ((char *) class + class->length);
+ }
+ }
+ pXFreeDeviceState(state);
+ wine_tsx11_unlock();
+ button_state[deviceid] = rc;
+}
+
+int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
+{
+ memset(&gMsgPacket,0,sizeof(WTPACKET));
+
+ if(event->type == motion_type)
+ {
+ XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
+
+ TRACE_(event)("Received tablet motion event (%p)\n",hwnd);
+ TRACE("Received tablet motion event (%p)\n",hwnd);
+ gMsgPacket.pkTime = motion->time;
+ gMsgPacket.pkSerialNumber = gSerial++;
+ gMsgPacket.pkCursor = motion->deviceid;
+ gMsgPacket.pkX = motion->axis_data[0];
+ gMsgPacket.pkY = motion->axis_data[1];
+ gMsgPacket.pkOrientation.orAzimuth =
+ figure_deg(motion->axis_data[3],motion->axis_data[4]);
+ gMsgPacket.pkOrientation.orAltitude = 1000 - 15 * max
+ (abs(motion->axis_data[3]),abs(motion->axis_data[4]));
+ gMsgPacket.pkNormalPressure = motion->axis_data[2];
+ gMsgPacket.pkButtons = get_button_state(motion->deviceid);
+ SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
+ }
+ else if ((event->type == button_press_type)||(event->type ==
+ button_release_type))
+ {
+ XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
+
+ TRACE_(event)("Received tablet button event\n");
+ TRACE("Received tablet button %s event\n", (event->type ==
+ button_press_type)?"press":"release");
+
+ set_button_state(button->deviceid);
+ }
+ else if (event->type == key_press_type)
+ {
+ TRACE_(event)("Received tablet key press event\n");
+ FIXME("Received tablet key press event\n");
+ }
+ else if (event->type == key_release_type)
+ {
+ TRACE_(event)("Received tablet key release event\n");
+ FIXME("Received tablet key release event\n");
+ }
+ else if ((event->type == proximity_in_type) ||
+ (event->type == proximity_out_type))
+ {
+ TRACE_(event)("Received tablet proximity event\n");
+ TRACE("Received tablet proximity event\n");
+ gMsgPacket.pkStatus = (event->type==proximity_out_type)?TPS_PROXIMITY:0;
+ SendMessageW(hwndTabletDefault, WT_PROXIMITY,
+ (event->type==proximity_out_type)?0:1, (LPARAM)hwnd);
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+int X11DRV_AttachEventQueueToTablet(HWND hOwner)
+{
+ struct x11drv_thread_data *data = x11drv_thread_data();
+ int num_devices;
+ int loop;
+ int cur_loop;
+ XDeviceInfo *devices;
+ XDeviceInfo *target = NULL;
+ XDevice *the_device;
+ XInputClassInfo *ip;
+ XEventClass event_list[7];
+ Window win = X11DRV_get_whole_window( hOwner );
+
+ if (!win) return 0;
+
+ TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
+
+ wine_tsx11_lock();
+ devices = pXListInputDevices(data->display, &num_devices);
+
+ for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
+ {
+ int event_number=0;
+
+ for (loop=0; loop < num_devices; loop ++)
+ if (strcmp(devices[loop].name,gSysCursor[cur_loop].NAME)==0)
+ target = &devices[loop];
+
+ TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
+
+ the_device = pXOpenDevice(data->display, target->id);
+
+ if (!the_device)
+ {
+ WARN("Unable to Open device\n");
+ continue;
+ }
+
+ if (the_device->num_classes > 0)
+ {
+ for (ip = the_device->classes, loop=0; loop < target->num_classes;
+ ip++, loop++)
+ {
+ switch(ip->input_class)
+ {
+ case KeyClass:
+ DeviceKeyPress(the_device, key_press_type,
+ event_list[event_number]);
+ event_number++;
+ DeviceKeyRelease(the_device, key_release_type,
+ event_list[event_number]);
+ event_number++;
+ break;
+ case ButtonClass:
+ DeviceButtonPress(the_device, button_press_type,
+ event_list[event_number]);
+ event_number++;
+ DeviceButtonRelease(the_device, button_release_type,
+ event_list[event_number]);
+ event_number++;
+ break;
+ case ValuatorClass:
+ DeviceMotionNotify(the_device, motion_type,
+ event_list[event_number]);
+ event_number++;
+ ProximityIn(the_device, proximity_in_type,
+ event_list[event_number]);
+ event_number++;
+ ProximityOut(the_device, proximity_out_type,
+ event_list[event_number]);
+ event_number++;
+ break;
+ default:
+ ERR("unknown class\n");
+ break;
+ }
+ }
+ if (pXSelectExtensionEvent(data->display, win, event_list, event_number))
+ {
+ ERR( "error selecting extended events\n");
+ goto end;
+ }
+ }
+ }
+
+end:
+ wine_tsx11_unlock();
+ return 0;
+}
+
+int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
+{
+ memcpy(packet,&gMsgPacket,sizeof(WTPACKET));
+ return 1;
+}
+
+
+int static inline CopyTabletData(LPVOID target, LPVOID src, INT size)
+{
+ memcpy(target,src,size);
+ return(size);
+}
+
+/***********************************************************************
+ * X11DRV_WTInfoA (X11DRV.@)
+ */
+UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
+{
+ int rc = 0;
+ LPWTI_CURSORS_INFO tgtcursor;
+ TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
+
+ switch(wCategory)
+ {
+ case 0:
+ /* return largest necessary buffer */
+ TRACE("%i cursors\n",gNumCursors);
+ if (gNumCursors>0)
+ {
+ FIXME("Return proper size\n");
+ return 200;
+ }
+ else
+ return 0;
+ break;
+ case WTI_INTERFACE:
+ switch (nIndex)
+ {
+ WORD version;
+ case IFC_WINTABID:
+ strcpy(lpOutput,"Wine Wintab 1.1");
+ rc = 16;
+ break;
+ case IFC_SPECVERSION:
+ version = (0x01) | (0x01 << 8);
+ rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
+ break;
+ case IFC_IMPLVERSION:
+ version = (0x00) | (0x01 << 8);
+ rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
+ break;
+ default:
+ FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
+ rc = 0;
+
+ }
+ case WTI_DEFSYSCTX:
+ case WTI_DDCTXS:
+ case WTI_DEFCONTEXT:
+ switch (nIndex)
+ {
+ case 0:
+ memcpy(lpOutput, &gSysContext,
+ sizeof(LOGCONTEXTA));
+ rc = sizeof(LOGCONTEXTA);
+ break;
+ case CTX_NAME:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcName,
+ strlen(gSysContext.lcName)+1);
+ break;
+ case CTX_OPTIONS:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
+ sizeof(UINT));
+ break;
+ case CTX_STATUS:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
+ sizeof(UINT));
+ break;
+ case CTX_LOCKS:
+ rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
+ sizeof(UINT));
+ break;
+ case CTX_MSGBASE:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
+ sizeof(UINT));
+ break;
+ case CTX_DEVICE:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
+ sizeof(UINT));
+ break;
+ case CTX_PKTRATE:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
+ sizeof(UINT));
+ break;
+ case CTX_PKTMODE:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
+ sizeof(WTPKT));
+ break;
+ case CTX_MOVEMASK:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
+ sizeof(WTPKT));
+ break;
+ case CTX_BTNDNMASK:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
+ sizeof(DWORD));
+ break;
+ case CTX_BTNUPMASK:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
+ sizeof(DWORD));
+ break;
+ case CTX_INORGX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
+ sizeof(LONG));
+ break;
+ case CTX_INORGY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
+ sizeof(LONG));
+ break;
+ case CTX_INORGZ:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
+ sizeof(LONG));
+ break;
+ case CTX_INEXTX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
+ sizeof(LONG));
+ break;
+ case CTX_INEXTY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
+ sizeof(LONG));
+ break;
+ case CTX_INEXTZ:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
+ sizeof(LONG));
+ break;
+ case CTX_OUTORGX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
+ sizeof(LONG));
+ break;
+ case CTX_OUTORGY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
+ sizeof(LONG));
+ break;
+ case CTX_OUTORGZ:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
+ sizeof(LONG));
+ break;
+ case CTX_OUTEXTX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
+ sizeof(LONG));
+ break;
+ case CTX_OUTEXTY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
+ sizeof(LONG));
+ break;
+ case CTX_OUTEXTZ:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
+ sizeof(LONG));
+ break;
+ case CTX_SENSX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
+ sizeof(LONG));
+ break;
+ case CTX_SENSY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
+ sizeof(LONG));
+ break;
+ case CTX_SENSZ:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
+ sizeof(LONG));
+ break;
+ case CTX_SYSMODE:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
+ sizeof(LONG));
+ break;
+ case CTX_SYSORGX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
+ sizeof(LONG));
+ break;
+ case CTX_SYSORGY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
+ sizeof(LONG));
+ break;
+ case CTX_SYSEXTX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
+ sizeof(LONG));
+ break;
+ case CTX_SYSEXTY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
+ sizeof(LONG));
+ break;
+ case CTX_SYSSENSX:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
+ sizeof(LONG));
+ break;
+ case CTX_SYSSENSY:
+ rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
+ sizeof(LONG));
+ break;
+ default:
+ FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
+ rc = 0;
+ }
+ break;
+ case WTI_CURSORS:
+ case WTI_CURSORS+1:
+ case WTI_CURSORS+2:
+ case WTI_CURSORS+3:
+ case WTI_CURSORS+4:
+ case WTI_CURSORS+5:
+ case WTI_CURSORS+6:
+ case WTI_CURSORS+7:
+ case WTI_CURSORS+8:
+ case WTI_CURSORS+9:
+ case WTI_CURSORS+10:
+ tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
+ switch (nIndex)
+ {
+ case CSR_NAME:
+ rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
+ strlen(tgtcursor->NAME)+1);
+ break;
+ case CSR_ACTIVE:
+ rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
+ sizeof(BOOL));
+ break;
+ case CSR_PKTDATA:
+ rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
+ sizeof(WTPKT));
+ break;
+ case CSR_BUTTONS:
+ rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
+ sizeof(BYTE));
+ break;
+ case CSR_BUTTONBITS:
+ rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
+ sizeof(BYTE));
+ break;
+ case CSR_BTNNAMES:
+ FIXME("Button Names not returned correctly\n");
+ rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
+ strlen(tgtcursor->BTNNAMES)+1);
+ break;
+ case CSR_BUTTONMAP:
+ rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
+ sizeof(BYTE)*32);
+ break;
+ case CSR_SYSBTNMAP:
+ rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
+ sizeof(BYTE)*32);
+ break;
+ case CSR_NPBTNMARKS:
+ memcpy(lpOutput,&tgtcursor->NPBTNMARKS,sizeof(UINT)*2);
+ rc = sizeof(UINT)*2;
+ break;
+ case CSR_NPBUTTON:
+ rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
+ sizeof(BYTE));
+ break;
+ case CSR_NPRESPONSE:
+ FIXME("Not returning CSR_NPRESPONSE correctly\n");
+ rc = 0;
+ break;
+ case CSR_TPBUTTON:
+ rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
+ sizeof(BYTE));
+ break;
+ case CSR_TPBTNMARKS:
+ memcpy(lpOutput,&tgtcursor->TPBTNMARKS,sizeof(UINT)*2);
+ rc = sizeof(UINT)*2;
+ break;
+ case CSR_TPRESPONSE:
+ FIXME("Not returning CSR_TPRESPONSE correctly\n");
+ rc = 0;
+ break;
+ case CSR_PHYSID:
+ {
+ DWORD id;
+ rc = CopyTabletData(&id,&tgtcursor->PHYSID,
+ sizeof(DWORD));
+ id += (wCategory - WTI_CURSORS);
+ memcpy(lpOutput,&id,sizeof(DWORD));
+ }
+ break;
+ case CSR_MODE:
+ rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
+ break;
+ case CSR_MINPKTDATA:
+ rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
+ sizeof(UINT));
+ break;
+ case CSR_MINBUTTONS:
+ rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
+ sizeof(UINT));
+ break;
+ case CSR_CAPABILITIES:
+ rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
+ sizeof(UINT));
+ break;
+ case CSR_TYPE:
+ rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
+ sizeof(UINT));
+ break;
+ default:
+ FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
+ rc = 0;
+ }
+ break;
+ case WTI_DEVICES:
+ switch (nIndex)
+ {
+ case DVC_NAME:
+ rc = CopyTabletData(lpOutput,gSysDevice.NAME,
+ strlen(gSysDevice.NAME)+1);
+ break;
+ case DVC_HARDWARE:
+ rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
+ sizeof(UINT));
+ break;
+ case DVC_NCSRTYPES:
+ rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
+ sizeof(UINT));
+ break;
+ case DVC_FIRSTCSR:
+ rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
+ sizeof(UINT));
+ break;
+ case DVC_PKTRATE:
+ rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
+ sizeof(UINT));
+ break;
+ case DVC_PKTDATA:
+ rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
+ sizeof(WTPKT));
+ break;
+ case DVC_PKTMODE:
+ rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
+ sizeof(WTPKT));
+ break;
+ case DVC_CSRDATA:
+ rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
+ sizeof(WTPKT));
+ break;
+ case DVC_XMARGIN:
+ rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
+ sizeof(INT));
+ break;
+ case DVC_YMARGIN:
+ rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
+ sizeof(INT));
+ break;
+ case DVC_ZMARGIN:
+ rc = 0; /* unsupported */
+ /*
+ rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
+ sizeof(INT));
+ */
+ break;
+ case DVC_X:
+ rc = CopyTabletData(lpOutput,&gSysDevice.X,
+ sizeof(AXIS));
+ break;
+ case DVC_Y:
+ rc = CopyTabletData(lpOutput,&gSysDevice.Y,
+ sizeof(AXIS));
+ break;
+ case DVC_Z:
+ rc = 0; /* unsupported */
+ /*
+ rc = CopyTabletData(lpOutput,&gSysDevice.Z,
+ sizeof(AXIS));
+ */
+ break;
+ case DVC_NPRESSURE:
+ rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
+ sizeof(AXIS));
+ break;
+ case DVC_TPRESSURE:
+ rc = 0; /* unsupported */
+ /*
+ rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
+ sizeof(AXIS));
+ */
+ break;
+ case DVC_ORIENTATION:
+ memcpy(lpOutput,&gSysDevice.ORIENTATION,sizeof(AXIS)*3);
+ rc = sizeof(AXIS)*3;
+ break;
+ case DVC_ROTATION:
+ rc = 0; /* unsupported */
+ /*
+ memcpy(lpOutput,&gSysDevice.ROTATION,sizeof(AXIS)*3);
+ rc = sizeof(AXIS)*3;
+ */
+ break;
+ case DVC_PNPID:
+ rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
+ strlen(gSysDevice.PNPID)+1);
+ break;
+ default:
+ FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
+ rc = 0;
+ }
+ break;
+ default:
+ FIXME("Unhandled Category %i\n",wCategory);
+ }
+ return rc;
+}
+
+#else /* HAVE_X11_EXTENSIONS_XINPUT_H */
+
+int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
+{
+ return 0;
+}
+
+int X11DRV_AttachEventQueueToTablet(HWND hOwner)
+{
+ return 0;
+}
+
+int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
+{
+ return 0;
+}
+
+void X11DRV_LoadTabletInfo(HWND hwnddefault)
+{
+}
+
+UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
+{
+ return 0;
+}
+
+#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index b09bc49..f7c117f 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -475,6 +475,8 @@
void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base) ;
#endif
+extern int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event);
+
/* x11drv private window data */
struct x11drv_win_data
{
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index ae68b95..3a22b0d 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -111,6 +111,12 @@
@ cdecl ShowWindow(long long) X11DRV_ShowWindow
@ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
+# WinTab32
+@ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet
+@ cdecl GetCurrentPacket(ptr) X11DRV_GetCurrentPacket
+@ cdecl LoadTabletInfo(long) X11DRV_LoadTabletInfo
+@ cdecl WTInfoA(long long ptr) X11DRV_WTInfoA
+
# X11 locks
@ cdecl -norelay wine_tsx11_lock()
@ cdecl -norelay wine_tsx11_unlock()
diff --git a/include/config.h.in b/include/config.h.in
index 4685930..c4318c6 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -1195,6 +1195,11 @@
#undef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
+ Define to 1 if you have the <X11/extensions/XInput.h>
+ header file. */
+#undef HAVE_X11_EXTENSIONS_XINPUT_H
+
+/*
Define to 1 if you have the <X11/extensions/Xrandr.h>
header file. */
#undef HAVE_X11_EXTENSIONS_XRANDR_H
@@ -1379,6 +1384,11 @@
#undef SONAME_LIBXEXT
/*
+ Define to the soname of the libXi library.
+ */
+#undef SONAME_LIBXI
+
+/*
Define to the soname of the libXrender library.
*/
#undef SONAME_LIBXRENDER
diff --git a/include/wintab.h b/include/wintab.h
index e8161b6..e9cb5fa 100644
--- a/include/wintab.h
+++ b/include/wintab.h
@@ -328,7 +328,9 @@
#define CSR_MINPKTDATA 17 /* 1.1 */
#define CSR_MINBUTTONS 18 /* 1.1 */
#define CSR_CAPABILITIES 19 /* 1.1 */
-#define CSR_MAX 19
+/* from http://www.wacomeng.com/devsupport/ibmpc/wacomwindevfaq.html */
+#define CSR_TYPE 20
+#define CSR_MAX 20
#endif