wintab work

Aric Stewart aric at codeweavers.com
Thu Jan 8 09:11:10 CST 2004


Sorry all, This is way way way _way_ overdue. But it is really the first 
time i have had a chance to really take some time and review the changes 
Alexandre gave me, retest everything and put together a patch against 
the tip.

I did some quick testing and it appears that this will work.

I have broken it into 2 patches

wine_wintab.diff is all the wintab work except for the x11drv stuff
wine_x11_wintab.diff is the changes to x11drv. the reason for this is 
because i still have the ime patch that i submitted earlier in my wine 
tree so i had to had edit that x11 patch to try to make it not dependent 
on the xim stuff being already applied. This make there a chance that 
there are bits that may not apply cleanly, and if you are committing 
both of my patches (xim and this) then they wont apply cleanly without a 
bit of fudging.

I am also giving you 2 test applications i used for wintab testing. 
SYSPRESS.EXE and TILTTEST.EXE These applications helped alot on testing 
things. They where found on the wacom developers site, i think i still 
have the source kicking around somewhere.


Changelog:  Enables Tablet support with both Tilt and Pressure

-aric
-------------- next part --------------
Index: dlls/wintab32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/wintab32/Makefile.in,v
retrieving revision 1.3
diff -u -w -r1.3 Makefile.in
--- dlls/wintab32/Makefile.in	11 Oct 2003 01:09:16 -0000	1.3
+++ dlls/wintab32/Makefile.in	8 Jan 2004 14:57:45 -0000
@@ -3,14 +3,15 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = wintab32.dll
-IMPORTS   = kernel32
+IMPORTS   = kernel32 user32
 ALTNAMES  = wintab.dll
 
 SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
 
 C_SRCS = \
 	context.c \
-	manager.c
+	manager.c \
+	wintab32.c
 
 C_SRCS16 = \
 	wintab16.c
Index: dlls/wintab32/context.c
===================================================================
RCS file: /home/wine/wine/dlls/wintab32/context.c,v
retrieving revision 1.2
diff -u -w -r1.2 context.c
--- dlls/wintab32/context.c	5 Sep 2003 23:08:26 -0000	1.2
+++ dlls/wintab32/context.c	8 Jan 2004 14:57:46 -0000
@@ -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,340 @@
  */
 
 #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 "user.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
+ */
+
+BOOL                gLoaded= FALSE;
+
+LPOPENCONTEXT       gOpenContexts = NULL;
+INT                 gContextCount = 0;
+HCTX                gTopContext = (HCTX)0xc00;
+
+extern HWND     hwndDefault;
+extern CRITICAL_SECTION csTablet;
+
+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 */
+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 0x%x\n",(INT)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=NULL;
+    ptr = gOpenContexts;
+    while (ptr)
+    {
+        TRACE("Trying Context %lx  (%x %x)\n",(LONG)ptr->handle,(INT)hwnd,
+                (INT)ptr->hwndOwner);
+
+        if (ptr->hwndOwner == hwnd) 
+           return ptr;
+    }
+    return NULL;
+}
+
+LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
+{
+    LPOPENCONTEXT ptr=NULL;
+
+    EnterCriticalSection(&csTablet);
+
+    ptr = gOpenContexts;
+    while (ptr)
+    {
+        TRACE("Trying Queue %lx  (%x %x)\n",(LONG)ptr->handle,(INT)hwnd,
+                (INT)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 +373,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);
+    newcontext->handle = gTopContext++;
+    newcontext->next = gOpenContexts;
+
+    EnterCriticalSection(&csTablet);
+    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 +424,32 @@
  */
 BOOL WINAPI WTClose(HCTX hCtx)
 {
-    FIXME("(%p): stub\n", hCtx);
+    LPOPENCONTEXT context,ptr;
 
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    TRACE("(%p)\n", hCtx);
+
+    ptr = context = gOpenContexts;
+   
+    while ((context->handle != hCtx) && (context))
+    {
+        ptr = context;
+        context = context->next;
+    }
+    if (!context)
+        return TRUE;
+
+    EnterCriticalSection(&csTablet);
+    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,23 +459,74 @@
  */
 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);
 
+    if (!hCtx || !lpPkts) return 0;
+
+    context = TABLET_FindOpenContext(hCtx);
+    TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
+
+    EnterCriticalSection(&csTablet);
+    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;
+}
+
 /***********************************************************************
  *		WTPacket (WINTAB32.24)
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+
+    EnterCriticalSection(&csTablet);
+    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,16 @@
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+    context->enabled = fEnable;
+
+    return TRUE;
 }
 
 /***********************************************************************
@@ -135,9 +553,7 @@
 {
     FIXME("(%p, %u): stub\n", hCtx, fToTop);
 
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-
-    return FALSE;
+    return TRUE;
 }
 
 /***********************************************************************
@@ -157,11 +573,17 @@
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+
+    memcpy(lpLogCtx,&context->context,sizeof(LOGCONTEXTA));
+
+    return TRUE;
 }
 
 /***********************************************************************
@@ -253,49 +675,166 @@
  */
 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);
+
+    if (!hCtx || !lpPkts) return 0;
+
+    context = TABLET_FindOpenContext(hCtx);
 
+    EnterCriticalSection(&csTablet);
+    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;
+}
+
 /***********************************************************************
  *		WTDataGet (WINTAB32.81)
  */
 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;
 
+    context = TABLET_FindOpenContext(hCtx);
+
+    EnterCriticalSection(&csTablet);
+    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;
+}
+
 /***********************************************************************
  *		WTDataPeek (WINTAB32.82)
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+
+    EnterCriticalSection(&csTablet);
+    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;
+}
+
 /***********************************************************************
  *		WTQueuePacketsEx (WINTAB32.200)
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+
+    EnterCriticalSection(&csTablet);
+    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 +844,13 @@
  */
 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;
+    context = TABLET_FindOpenContext(hCtx);
+    return context->QueueSize;
 }
 
 /***********************************************************************
@@ -317,9 +858,20 @@
  */
 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;
+
+    context = TABLET_FindOpenContext(hCtx);
+
+    EnterCriticalSection(&csTablet);
+    context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
+                        context->PacketQueue, sizeof(WTPACKET)*nPkts);    
+    
+    context->QueueSize = nPkts;
+    LeaveCriticalSection(&csTablet);
+
+    return nPkts;
 }
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/wintab32/wintab32.c	Thu Jan  8 08:47:13 2004
@@ -0,0 +1,155 @@
+/*
+ * 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  = (HWND)NULL;
+static HANDLE hTabletInst;
+static const WCHAR
+WC_TABLETCLASSNAME[] = {'W','i','n','e','T','a','b','l','e','t','C','l','a','s','s',0};
+CRITICAL_SECTION csTablet;
+
+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 = (WNDPROC) 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};
+    static HMODULE hx11drv = NULL;
+
+    TRACE("%p, %lx, %p\n",hInstDLL,fdwReason,lpReserved);
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            TRACE("Initialization\n");
+            InitializeCriticalSection(&csTablet);
+            hx11drv = LoadLibraryA("x11drv.dll");
+            if (hx11drv)
+            {
+                pLoadTabletInfo = (X11_LoadTabletInfo*)GetProcAddress(hx11drv,
+                                    "LoadTabletInfo");
+                pAttachEventQueueToTablet = (X11_AttachEventQueueToTablet*)
+                            GetProcAddress(hx11drv, "AttachEventQueueToTablet");
+                pGetCurrentPacket = (X11_GetCurrentPacket*)
+                                   GetProcAddress(hx11drv, "GetCurrentPacket");
+                pWTInfoA = (void *)GetProcAddress(hx11drv, "WTInfoA");
+                TABLET_Register();
+                hTabletInst = hInstDLL;
+                hwndDefault = CreateWindowW(WC_TABLETCLASSNAME, name,
+                                WS_POPUPWINDOW,0,0,0,0,0,0,hTabletInst,0);
+            }
+            else
+                return FALSE;
+            break;
+        case DLL_PROCESS_DETACH:
+            TRACE("Detaching\n");
+            if (hx11drv)
+            {
+                FreeLibrary(hx11drv);
+                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 = wParam | 0x1 << 16;
+                    TABLET_PostTabletMessage(handler, WT_PROXIMITY,
+                                        (WPARAM)handler->handle, (LPARAM)prox,
+                                        TRUE);
+                }
+                break;
+            }
+    }
+    return 0;
+}
+
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/wintab32/wintab_internal.h	Thu Jan  8 08:47:13 2004
@@ -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
+ */
+
+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;
+
+LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx);
+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 */
+typedef int X11_LoadTabletInfo(HWND hwnddefault);
+
+typedef int X11_GetCurrentPacket(LPWTPACKET packet);
+
+typedef int X11_AttachEventQueueToTablet(HWND hOwner);
+
+X11_LoadTabletInfo *pLoadTabletInfo;
+X11_AttachEventQueueToTablet *pAttachEventQueueToTablet;
+X11_GetCurrentPacket *pGetCurrentPacket;
+
+extern UINT (*pWTInfoA)(UINT wCategory, UINT nIndex, LPVOID lpOutput);
Index: include/wintab.h
===================================================================
RCS file: /home/wine/wine/include/wintab.h,v
retrieving revision 1.1
diff -u -w -r1.1 wintab.h
--- include/wintab.h	17 Dec 2002 01:49:16 -0000	1.1
+++ include/wintab.h	8 Jan 2004 14:59:11 -0000
@@ -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
 
-------------- next part --------------
Index: dlls/x11drv/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/Makefile.in,v
retrieving revision 1.38
diff -u -w -r1.38 Makefile.in
--- dlls/x11drv/Makefile.in	5 Dec 2003 00:20:28 -0000	1.38
+++ dlls/x11drv/Makefile.in	8 Jan 2004 14:59:54 -0000
@@ -34,10 +34,12 @@
 	text.c \
 	window.c \
 	winpos.c \
+	wintab.c \
 	x11ddraw.c \
 	x11drv_main.c \
 	xdnd.c \
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.30
diff -u -w -r1.30 event.c
--- dlls/x11drv/event.c	5 Dec 2003 04:45:50 -0000	1.30
+++ dlls/x11drv/event.c	8 Jan 2004 14:59:54 -0000
@@ -275,8 +277,18 @@
       WARN( "Got event %s for unknown Window %08lx\n",
             event_names[event->type], event->xany.window );
   else
-      TRACE("Got event %s for hwnd %p\n",
-            event_names[event->type], hWnd );
+      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 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)
     {
RCS file: /home/wine/wine/dlls/x11drv/x11drv.spec,v
retrieving revision 1.50
diff -u -w -r1.50 x11drv.spec
--- dlls/x11drv/x11drv.spec	26 Nov 2003 22:03:34 -0000	1.50
+++ dlls/x11drv/x11drv.spec	8 Jan 2004 14:59:57 -0000
@@ -114,3 +114,12 @@
 # X11 locks
 @ cdecl -norelay wine_tsx11_lock()
 @ cdecl -norelay wine_tsx11_unlock()
+
+# WinTab32
+@ cdecl LoadTabletInfo(long) X11DRV_LoadTabletInfo
+@ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet
+@ cdecl GetCurrentPacket(ptr) X11DRV_GetCurrentPacket
+@ cdecl WTInfoA(long long ptr) X11DRV_WTInfoA
Index: dlls/x11drv/x11drv_main.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv_main.c,v
retrieving revision 1.83
diff -u -w -r1.83 x11drv_main.c
--- dlls/x11drv/x11drv_main.c	5 Dec 2003 00:11:48 -0000	1.83
+++ dlls/x11drv/x11drv_main.c	8 Jan 2004 14:59:57 -0000
@@ -62,7 +62,10 @@
 #include "xrandr.h"
 #include "dga2.h"
 #include "wine/server.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/x11drv/wintab.c	Thu Jan  8 08:47:17 2004
@@ -0,0 +1,1134 @@
+/*
+ * 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 <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XI.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;
+
+
+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;
+
+HWND                hwndTabletDefault = (HWND)NULL;
+WTPACKET            gMsgPacket;
+static  DWORD       gSerial = 0;
+static  INT         button_state[10] = {0,0,0,0,0,0,0,0,0,0};
+
+#define             CURSORMAX 10
+
+static LOGCONTEXTA      gSysContext;
+static WTI_DEVICES_INFO gSysDevice;
+static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
+static INT              gNumCursors;
+
+
+/* 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
+
+INT X11DRV_XInput_Init(void)
+{
+    xinput_handle = wine_dlopen("libXi.so", 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;
+    WND             *wndPtr;
+
+    wine_tsx11_lock();
+
+    wndPtr = WIN_GetPtr(hOwner);
+    win = ((struct x11drv_win_data*)wndPtr->pDriverData)->whole_window;
+
+    TRACE("Creating context for window 0x%x (%lx)  %i cursors\n",(INT)hOwner,
+              win, gNumCursors);
+
+    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:
+    WIN_ReleasePtr(wndPtr);
+    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;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: TILTTEST.EXE
Type: application/octet-stream
Size: 38400 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20040108/a71c4829/TILTTEST.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SYSPRESS.EXE
Type: application/octet-stream
Size: 24576 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20040108/a71c4829/SYSPRESS.obj


More information about the wine-devel mailing list