Adds wintab32 support using XInput. Merged from CrossOver Office.
I am including this on the wine-devel list because there was discussion and comment about it there.
-aric
Index: dlls/wintab32/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/wintab32/Makefile.in,v retrieving revision 1.2 diff -u -r1.2 Makefile.in --- dlls/wintab32/Makefile.in 23 Mar 2003 20:00:02 -0000 1.2 +++ dlls/wintab32/Makefile.in 23 Apr 2003 13:55:27 -0000 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = wintab32.dll -IMPORTS = kernel32 +IMPORTS = kernel32 user32 ALTNAMES = wintab.dll LDDLLFLAGS = @LDDLLFLAGS@ @@ -13,7 +13,8 @@ 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.1 diff -u -r1.1 context.c --- dlls/wintab32/context.c 17 Dec 2002 01:49:16 -0000 1.1 +++ dlls/wintab32/context.c 23 Apr 2003 13:55:27 -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,27 +20,737 @@ */ #include "config.h" +#include <stdio.h> +#include <stdlib.h> -#include "windef.h" #include "winbase.h" +#include "windef.h" #include "winerror.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 + */ + +#define CURSORMAX 10 + +BOOL gLoaded= FALSE; +LOGCONTEXTA gSysContext; +WTI_CURSORS_INFO gSysCursor[CURSORMAX]; +WTI_DEVICES_INFO gSysDevice; +INT gNumCursors; + +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; + memset(&gSysContext,0,sizeof(LOGCONTEXTA)); + memset(&gSysDevice,0,sizeof(WTI_DEVICES_INFO)); + memset(gSysCursor,0,sizeof(WTI_CURSORS_INFO)*gNumCursors); + gNumCursors = pLoadTabletInfo(&gSysContext, &gSysDevice, gSysCursor, + CURSORMAX, 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); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; + int rc = 0; + LPWTI_CURSORS_INFO tgtcursor; + TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput); + + if (gLoaded == FALSE) + LoadTablet(); + switch(wCategory) + { + case 0: + /* return largest nessecary 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: + DUMPCONTEXT(gSysContext); + 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; } /*********************************************************************** @@ -59,11 +770,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, gSysCursor, gNumCursors); + + 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; } /*********************************************************************** @@ -83,9 +821,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; } @@ -95,11 +856,36 @@ */ 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; + + TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts); + + 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); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + TRACE("Copied %i packets\n",limit); - return 0; + return limit; } /*********************************************************************** @@ -107,11 +893,33 @@ */ BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt) { - FIXME("(%p, %d, %p): stub\n", hCtx, wSerial, lpPkt); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + int rc = 0; + LPOPENCONTEXT context; + LPWTPACKET wtp; + + TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt); + + 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); - return FALSE; + TRACE("Returning %i\n",rc+1); + return rc+1; } /*********************************************************************** @@ -119,11 +927,14 @@ */ 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; + context = TABLET_FindOpenContext(hCtx); + context->enabled = fEnable; + + return TRUE; } /*********************************************************************** @@ -133,9 +944,7 @@ { FIXME("(%p, %u): stub\n", hCtx, fToTop); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; + return TRUE; } /*********************************************************************** @@ -155,11 +964,14 @@ */ 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); + context = TABLET_FindOpenContext(hCtx); - return FALSE; + memcpy(lpLogCtx,&context->context,sizeof(LOGCONTEXTA)); + + return TRUE; } /*********************************************************************** @@ -251,11 +1063,27 @@ */ int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts) { - FIXME("(%p, %d, %p): stub\n", hCtx, cMaxPkts, lpPkts); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; + int limit; + LPOPENCONTEXT context; + LPVOID ptr = lpPkts; + + TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts); + + 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; } /*********************************************************************** @@ -264,12 +1092,53 @@ 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); + context = TABLET_FindOpenContext(hCtx); - return 0; + 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; } /*********************************************************************** @@ -278,12 +1147,48 @@ 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); + context = TABLET_FindOpenContext(hCtx); - return 0; + 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; } /*********************************************************************** @@ -291,9 +1196,24 @@ */ 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); + 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; } @@ -303,11 +1223,11 @@ */ int WINAPI WTQueueSizeGet(HCTX hCtx) { - FIXME("(%p): stub\n", hCtx); + LPOPENCONTEXT context; + TRACE("(%p)\n", hCtx); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; + context = TABLET_FindOpenContext(hCtx); + return context->QueueSize; } /*********************************************************************** @@ -315,9 +1235,18 @@ */ 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; + context = TABLET_FindOpenContext(hCtx); + + EnterCriticalSection(&csTablet); + context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0, + context->PacketQueue, sizeof(WTPACKET)*nPkts); + + context->QueueSize = nPkts; + LeaveCriticalSection(&csTablet); + + return nPkts; } Index: dlls/x11drv/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/x11drv/Makefile.in,v retrieving revision 1.30 diff -u -r1.30 Makefile.in --- dlls/x11drv/Makefile.in 31 Oct 2002 02:38:20 -0000 1.30 +++ dlls/x11drv/Makefile.in 23 Apr 2003 13:55:27 -0000 @@ -38,7 +38,8 @@ x11ddraw.c \ x11drv_main.c \ xrender.c \ - xvidmode.c + xvidmode.c \ + wintab.c PROGRAMS = wineclipsrv Index: dlls/x11drv/event.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/event.c,v retrieving revision 1.18 diff -u -r1.18 event.c --- dlls/x11drv/event.c 23 Jan 2003 01:29:58 -0000 1.18 +++ dlls/x11drv/event.c 23 Apr 2003 13:55:28 -0000 @@ -275,8 +275,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 extention 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) { Index: dlls/x11drv/x11drv.spec =================================================================== RCS file: /home/wine/wine/dlls/x11drv/x11drv.spec,v retrieving revision 1.45 diff -u -r1.45 x11drv.spec --- dlls/x11drv/x11drv.spec 22 Apr 2003 00:15:48 -0000 1.45 +++ dlls/x11drv/x11drv.spec 23 Apr 2003 13:55:28 -0000 @@ -104,3 +104,8 @@ # X11 locks @ cdecl -norelay wine_tsx11_lock() @ cdecl -norelay wine_tsx11_unlock() + +# WinTab32 +@ cdecl LoadTabletInfo(ptr ptr ptr long ptr) X11DRV_LoadTabletInfo +@ cdecl AttachEventQueueToTablet(ptr ptr long) X11DRV_AttachEventQueueToTablet +@ cdecl GetCurrentPacket(ptr) X11DRV_GetCurrentPacket Index: include/wintab.h =================================================================== RCS file: /home/wine/wine/include/wintab.h,v retrieving revision 1.1 diff -u -r1.1 wintab.h --- include/wintab.h 17 Dec 2002 01:49:16 -0000 1.1 +++ include/wintab.h 23 Apr 2003 13:55:28 -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 --- /dev/null Thu Aug 30 15:30:55 2001 +++ dlls/wintab32/wintab32.c Wed Apr 23 08:22:37 2003 @@ -0,0 +1,150 @@ +/* + * 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 "winbase.h" +#include "windef.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; + +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"); + 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 Wed Apr 23 08:26:57 2003 @@ -0,0 +1,329 @@ +/* + * 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_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 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_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(LPLOGCONTEXTA context, LPWTI_DEVICES_INFO + device, LPWTI_CURSORS_INFO cursor_list, int + num_cursors, HWND hwnddefault); + +typedef int X11_GetCurrentPacket(LPWTPACKET packet); + +typedef int X11_AttachEventQueueToTablet(HWND hOwner, LPWTI_CURSORS_INFO + cursor_list, int num_cursors); + +X11_LoadTabletInfo *pLoadTabletInfo; +X11_AttachEventQueueToTablet *pAttachEventQueueToTablet; +X11_GetCurrentPacket *pGetCurrentPacket; --- /dev/null Thu Aug 30 15:30:55 2001 +++ dlls/x11drv/wintab.c Wed Apr 23 08:27:47 2003 @@ -0,0 +1,551 @@ +/* + * 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 "ts_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" +#include <dlfcn.h> +#include "../wintab32/wintab_internal.h" +#include <stdlib.h> + +WINE_DEFAULT_DEBUG_CHANNEL(wintab32); +WINE_DECLARE_DEBUG_CHANNEL(event); + +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}; + + +/* 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; +} + +int X11DRV_LoadTabletInfo(LPLOGCONTEXTA context, LPWTI_DEVICES_INFO device, + LPWTI_CURSORS_INFO cursor_list, int num_cursors, 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 0; + } + + hwndTabletDefault = hwnddefault; + + /* Do base initializaion */ + strcpy(context->lcName, "Wine Tablet Context"); + strcpy(device->NAME,"Wine Tablet Device"); + + context->lcOptions = CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + context->lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN | + CXL_SENSITIVITY | CXL_SYSOUT; + + context->lcMsgBase= WT_DEFBASE; + context->lcDevice = 0; + context->lcPktData = + PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR | + PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION; + context->lcMoveMask= + PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION; + context->lcStatus = CXS_ONTOP; + context->lcPktRate = 100; + context->lcBtnDnMask = 0xffffffff; + context->lcBtnUpMask = 0xffffffff; + context->lcSensX = 65536; + context->lcSensY = 65536; + context->lcSensX = 65536; + context->lcSensZ = 65536; + context->lcSysSensX= 65536; + context->lcSysSensY= 65536; + + /* Device Defaults */ + device->HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS; + device->FIRSTCSR= 0; + device->PKTRATE = 100; + device->PKTDATA = + PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR | + PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION; + strcpy(device->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 0; + } + 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 Extention Device\n"); + cursor_target++; + target = &devices[loop]; + cursor = &cursor_list[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 */ + device->X.axMin = Axis->min_value; + device->X.axMax= Axis->max_value; + device->X.axUnits = 1; + device->X.axResolution = Axis->resolution; + context->lcInOrgX = Axis->min_value; + context->lcSysOrgX = Axis->min_value; + context->lcInExtX = Axis->max_value; + context->lcSysExtX = Axis->max_value; + Axis++; + } + if (Val->num_axes>=2) + { + /* Axis 2 is Y */ + device->Y.axMin = Axis->min_value; + device->Y.axMax= Axis->max_value; + device->Y.axUnits = 1; + device->Y.axResolution = Axis->resolution; + context->lcInOrgY = Axis->min_value; + context->lcSysOrgY = Axis->min_value; + context->lcInExtY = Axis->max_value; + context->lcSysExtY = Axis->max_value; + Axis++; + } + if (Val->num_axes>=3) + { + /* Axis 3 is Normal Pressure */ + device->NPRESSURE.axMin = Axis->min_value; + device->NPRESSURE.axMax= Axis->max_value; + device->NPRESSURE.axUnits = 1; + device->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))) + { + device->ORIENTATION[0].axMin = 0; + device->ORIENTATION[0].axMax = 3600; + device->ORIENTATION[0].axUnits = 1; + device->ORIENTATION[0].axResolution = + 235929600; + device->ORIENTATION[1].axMin = -1000; + device->ORIENTATION[1].axMax = 1000; + device->ORIENTATION[1].axUnits = 1; + device->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(); + device->NCSRTYPES = cursor_target+1; + return 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)("Recieved tablet motion event (%p)\n",hwnd); + TRACE("Recieved 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]; + + if (!gMsgPacket.pkNormalPressure) + button_state[motion->deviceid] &= ~(1); + else + button_state[motion->deviceid] |= 1; + + 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)("Recieved tablet button event\n"); + TRACE("Recieved 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)("Recieved tablet key press event\n"); + FIXME("Recieved tablet key press event\n"); + } + else if (event->type == key_release_type) + { + TRACE_(event)("Recieved tablet key release event\n"); + FIXME("Recieved tablet key release event\n"); + } + else if ((event->type == proximity_in_type) || + (event->type == proximity_out_type)) + { + TRACE_(event)("Recieved tablet proximity event\n"); + TRACE("Recieved 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, LPWTI_CURSORS_INFO cursor_list, + int num_cursors) +{ + 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, num_cursors); + + devices = pXListInputDevices(data->display, &num_devices); + + for (cur_loop=0; cur_loop < num_cursors; cur_loop++) + { + int event_number=0; + + for (loop=0; loop < num_devices; loop ++) + if (strcmp(devices[loop].name,cursor_list[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; +}