Unstable & with drawing restored
This commit is contained in:
parent
1155067b26
commit
cd8feaf2c0
15 changed files with 1004 additions and 31 deletions
943
Externals/easytab/easytab.h
vendored
Normal file
943
Externals/easytab/easytab.h
vendored
Normal file
|
|
@ -0,0 +1,943 @@
|
|||
/*
|
||||
EasyTab.h - Single-header multi-platform tablet library
|
||||
https://github.com/ApoorvaJ/EasyTab
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
USAGE
|
||||
----------------------------------------------------------------------------
|
||||
1) Add the following lines in exactly one of your cpp files to compile the
|
||||
implementation.
|
||||
|
||||
#define EASYTAB_IMPLEMENTATION
|
||||
#include "easytab.h"
|
||||
|
||||
2) Call EasyTab_Load() with correct parameters to initialize EasyTab. These
|
||||
parameters vary per OS, so look at the function declarations or examples
|
||||
below. Function returns EASYTAB_OK if initialization was successful.
|
||||
|
||||
3) Call EasyTab_HandleEvent() in your message-handling code. The function
|
||||
returns EASYTAB_OK if the message was a tablet message, and
|
||||
EASYTAB_EVENT_NOT_HANDLED otherwise.
|
||||
|
||||
4) Call EasyTab_Unload() in your shutdown code.
|
||||
|
||||
5) Once initialized, you can query tablet state using the EasyTab pointer.
|
||||
e.g.:
|
||||
|
||||
EasyTab->PosX // X position of the pen
|
||||
EasyTab->PosY // Y position of the pen
|
||||
EasyTab->Pressure // Pressure of the pen ranging from 0.0f to 1.0f
|
||||
|
||||
For more info, have a look at the EasyTabInfo struct below.
|
||||
|
||||
|
||||
* Add -lXi to compiler options to link XInput on Linux.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
EXAMPLES
|
||||
----------------------------------------------------------------------------
|
||||
1) Windows:
|
||||
|
||||
int CALLBACK WinMain(...)
|
||||
{
|
||||
HWND Window;
|
||||
|
||||
...
|
||||
|
||||
if (EasyTab_Load(Window) != EASYTAB_OK) // Load
|
||||
{
|
||||
OutputDebugStringA("Tablet init failed\n");
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Once you've set up EasyTab loading, unloading and event handling,
|
||||
// use the EasyTab variable at any point in your program to access
|
||||
// the tablet state:
|
||||
// EasyTab->PosX
|
||||
// EasyTab->PosY
|
||||
// EasyTab->Pressure
|
||||
// For more tablet information, look at the EasyTabInfo struct.
|
||||
|
||||
...
|
||||
|
||||
EasyTab_Unload(); // Unload
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WindowProc(
|
||||
HWND Window,
|
||||
UINT Message,
|
||||
WPARAM WParam,
|
||||
LPARAM LParam)
|
||||
{
|
||||
if (EasyTab_HandleEvent(Window, Message, LParam, WParam) == EASYTAB_OK) // Event
|
||||
{
|
||||
return true; // Tablet event handled
|
||||
}
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2) Linux:
|
||||
|
||||
int main(...)
|
||||
{
|
||||
Display* Disp;
|
||||
Window Win;
|
||||
|
||||
...
|
||||
|
||||
if (EasyTab_Load(Disp, Win) != EASYTAB_OK) // Load
|
||||
{
|
||||
printf("Tablet init failed\n");
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
while (XPending(Disp)) // Event loop
|
||||
{
|
||||
XEvent Event;
|
||||
XNextEvent(XlibDisplay, &Event);
|
||||
|
||||
if (EasyTab_HandleEvent(&Event) == EASYTAB_OK) // Event
|
||||
{
|
||||
continue; // Tablet event handled
|
||||
}
|
||||
|
||||
switch (Event.type)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// Once you've set up EasyTab loading, unloading and event handling,
|
||||
// use the EasyTab variable at any point in your program to access
|
||||
// the tablet state:
|
||||
// EasyTab->PosX
|
||||
// EasyTab->PosY
|
||||
// EasyTab->Pressure
|
||||
// For more tablet information, look at the EasyTabInfo struct.
|
||||
|
||||
...
|
||||
|
||||
EasyTab_Unload(); // Unload
|
||||
}
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
CREDITS
|
||||
----------------------------------------------------------------------------
|
||||
Apoorva Joshi apoorvaj.io
|
||||
Sergio Gonzalez s3rg.io
|
||||
|
||||
This library is coded in the spirit of the stb libraries and follows the stb
|
||||
guidelines.
|
||||
|
||||
*/
|
||||
|
||||
// TODO: Null checks and warnings for EasyTab
|
||||
// TODO: Differentiate between stylus and eraser in the API
|
||||
// TODO: Linux support for relative mode
|
||||
// TODO: Documentation for relative mode
|
||||
|
||||
// =============================================================================
|
||||
// EasyTab header section
|
||||
// =============================================================================
|
||||
|
||||
#ifndef EASYTAB_H
|
||||
#define EASYTAB_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <X11/extensions/XInput.h>
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EASYTAB_OK = 0,
|
||||
|
||||
// Errors
|
||||
EASYTAB_MEMORY_ERROR = -1,
|
||||
EASYTAB_X11_ERROR = -2,
|
||||
EASYTAB_DLL_LOAD_ERROR = -3,
|
||||
EASYTAB_WACOM_WIN32_ERROR = -4,
|
||||
EASYTAB_INVALID_FUNCTION_ERROR = -5,
|
||||
|
||||
EASYTAB_EVENT_NOT_HANDLED = -16,
|
||||
} EasyTabResult;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EASYTAB_TRACKING_MODE_SYSTEM = 0,
|
||||
EASYTAB_TRACKING_MODE_RELATIVE = 1,
|
||||
} EasyTabTrackingMode;
|
||||
|
||||
#ifdef WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
// wintab.h
|
||||
// -----------------------------------------------------------------------------
|
||||
#if 1
|
||||
|
||||
DECLARE_HANDLE(HMGR);
|
||||
DECLARE_HANDLE(HCTX);
|
||||
|
||||
typedef DWORD WTPKT;
|
||||
typedef DWORD FIX32;
|
||||
|
||||
// Messages
|
||||
#if 1
|
||||
|
||||
#define WT_DEFBASE 0x7FF0
|
||||
#define WT_MAXOFFSET 0xF
|
||||
|
||||
#define _WT_PACKET(b) ((b)+0)
|
||||
#define _WT_CTXOPEN(b) ((b)+1)
|
||||
#define _WT_CTXCLOSE(b) ((b)+2)
|
||||
#define _WT_CTXUPDATE(b) ((b)+3)
|
||||
#define _WT_CTXOVERLAP(b) ((b)+4)
|
||||
#define _WT_PROXIMITY(b) ((b)+5)
|
||||
#define _WT_INFOCHANGE(b) ((b)+6)
|
||||
#define _WT_CSRCHANGE(b) ((b)+7) /* 1.1 */
|
||||
#define _WT_PACKETEXT(b) ((b)+8) /* 1.4 */
|
||||
#define _WT_MAX(b) ((b)+WT_MAXOFFSET)
|
||||
|
||||
#define WT_PACKET _WT_PACKET(WT_DEFBASE)
|
||||
#define WT_CTXOPEN _WT_CTXOPEN(WT_DEFBASE)
|
||||
#define WT_CTXCLOSE _WT_CTXCLOSE(WT_DEFBASE)
|
||||
#define WT_CTXUPDATE _WT_CTXUPDATE(WT_DEFBASE)
|
||||
#define WT_CTXOVERLAP _WT_CTXOVERLAP(WT_DEFBASE)
|
||||
#define WT_PROXIMITY _WT_PROXIMITY(WT_DEFBASE)
|
||||
#define WT_INFOCHANGE _WT_INFOCHANGE(WT_DEFBASE)
|
||||
#define WT_CSRCHANGE _WT_CSRCHANGE(WT_DEFBASE) /* 1.1 */
|
||||
#define WT_PACKETEXT _WT_PACKETEXT(WT_DEFBASE) /* 1.4 */
|
||||
#define WT_MAX _WT_MAX(WT_DEFBASE)
|
||||
|
||||
#endif // Messages
|
||||
|
||||
// Flags
|
||||
#if 1
|
||||
|
||||
#define CTX_NAME 1
|
||||
#define CTX_OPTIONS 2
|
||||
#define CTX_STATUS 3
|
||||
#define CTX_LOCKS 4
|
||||
#define CTX_MSGBASE 5
|
||||
#define CTX_DEVICE 6
|
||||
#define CTX_PKTRATE 7
|
||||
#define CTX_PKTDATA 8
|
||||
#define CTX_PKTMODE 9
|
||||
#define CTX_MOVEMASK 10
|
||||
#define CTX_BTNDNMASK 11
|
||||
#define CTX_BTNUPMASK 12
|
||||
#define CTX_INORGX 13
|
||||
#define CTX_INORGY 14
|
||||
#define CTX_INORGZ 15
|
||||
#define CTX_INEXTX 16
|
||||
#define CTX_INEXTY 17
|
||||
#define CTX_INEXTZ 18
|
||||
#define CTX_OUTORGX 19
|
||||
#define CTX_OUTORGY 20
|
||||
#define CTX_OUTORGZ 21
|
||||
#define CTX_OUTEXTX 22
|
||||
#define CTX_OUTEXTY 23
|
||||
#define CTX_OUTEXTZ 24
|
||||
#define CTX_SENSX 25
|
||||
#define CTX_SENSY 26
|
||||
#define CTX_SENSZ 27
|
||||
#define CTX_SYSMODE 28
|
||||
#define CTX_SYSORGX 29
|
||||
#define CTX_SYSORGY 30
|
||||
#define CTX_SYSEXTX 31
|
||||
#define CTX_SYSEXTY 32
|
||||
#define CTX_SYSSENSX 33
|
||||
#define CTX_SYSSENSY 34
|
||||
#define CTX_MAX 34
|
||||
|
||||
// Context option values
|
||||
#define CXO_SYSTEM 0x0001
|
||||
#define CXO_PEN 0x0002
|
||||
#define CXO_MESSAGES 0x0004
|
||||
#define CXO_MARGIN 0x8000
|
||||
#define CXO_MGNINSIDE 0x4000
|
||||
#define CXO_CSRMESSAGES 0x0008 /* 1.1 */
|
||||
|
||||
#define DVC_NAME 1
|
||||
#define DVC_HARDWARE 2
|
||||
#define DVC_NCSRTYPES 3
|
||||
#define DVC_FIRSTCSR 4
|
||||
#define DVC_PKTRATE 5
|
||||
#define DVC_PKTDATA 6
|
||||
#define DVC_PKTMODE 7
|
||||
#define DVC_CSRDATA 8
|
||||
#define DVC_XMARGIN 9
|
||||
#define DVC_YMARGIN 10
|
||||
#define DVC_ZMARGIN 11
|
||||
#define DVC_X 12
|
||||
#define DVC_Y 13
|
||||
#define DVC_Z 14
|
||||
#define DVC_NPRESSURE 15
|
||||
#define DVC_TPRESSURE 16
|
||||
#define DVC_ORIENTATION 17
|
||||
#define DVC_ROTATION 18 /* 1.1 */
|
||||
#define DVC_PNPID 19 /* 1.1 */
|
||||
#define DVC_MAX 19
|
||||
|
||||
#define PK_CONTEXT 0x0001 // reporting context
|
||||
#define PK_STATUS 0x0002 // status bits
|
||||
#define PK_TIME 0x0004 // time stamp
|
||||
#define PK_CHANGED 0x0008 // change bit vector
|
||||
#define PK_SERIAL_NUMBER 0x0010 // packet serial number
|
||||
#define PK_CURSOR 0x0020 // reporting cursor
|
||||
#define PK_BUTTONS 0x0040 // button information
|
||||
#define PK_X 0x0080 // x axis
|
||||
#define PK_Y 0x0100 // y axis
|
||||
#define PK_Z 0x0200 // z axis
|
||||
#define PK_NORMAL_PRESSURE 0x0400 // normal or tip pressure
|
||||
#define PK_TANGENT_PRESSURE 0x0800 // tangential or barrel pressure
|
||||
#define PK_ORIENTATION 0x1000 // orientation info: tilts
|
||||
#define PK_ROTATION 0x2000 // rotation info; 1.1
|
||||
|
||||
// constants for use with pktdef.h
|
||||
#define PKEXT_ABSOLUTE 1
|
||||
#define PKEXT_RELATIVE 2
|
||||
|
||||
#define WTI_DEFCONTEXT 3
|
||||
#define WTI_DEFSYSCTX 4
|
||||
#define WTI_DEVICES 100
|
||||
#define WTI_DDCTXS 400 /* 1.1 */
|
||||
#define WTI_DSCTXS 500 /* 1.1 */
|
||||
|
||||
#endif // Flags
|
||||
|
||||
typedef struct tagAXIS {
|
||||
LONG axMin;
|
||||
LONG axMax;
|
||||
UINT axUnits;
|
||||
FIX32 axResolution;
|
||||
} AXIS, *PAXIS, NEAR *NPAXIS, FAR *LPAXIS;
|
||||
|
||||
#define LCNAMELEN 40
|
||||
typedef struct tagLOGCONTEXTA {
|
||||
char lcName[LCNAMELEN];
|
||||
UINT lcOptions;
|
||||
UINT lcStatus;
|
||||
UINT lcLocks;
|
||||
UINT lcMsgBase;
|
||||
UINT lcDevice;
|
||||
UINT lcPktRate;
|
||||
WTPKT lcPktData;
|
||||
WTPKT lcPktMode;
|
||||
WTPKT lcMoveMask;
|
||||
DWORD lcBtnDnMask;
|
||||
DWORD lcBtnUpMask;
|
||||
LONG lcInOrgX;
|
||||
LONG lcInOrgY;
|
||||
LONG lcInOrgZ;
|
||||
LONG lcInExtX;
|
||||
LONG lcInExtY;
|
||||
LONG lcInExtZ;
|
||||
LONG lcOutOrgX;
|
||||
LONG lcOutOrgY;
|
||||
LONG lcOutOrgZ;
|
||||
LONG lcOutExtX;
|
||||
LONG lcOutExtY;
|
||||
LONG lcOutExtZ;
|
||||
FIX32 lcSensX;
|
||||
FIX32 lcSensY;
|
||||
FIX32 lcSensZ;
|
||||
BOOL lcSysMode;
|
||||
int lcSysOrgX;
|
||||
int lcSysOrgY;
|
||||
int lcSysExtX;
|
||||
int lcSysExtY;
|
||||
FIX32 lcSysSensX;
|
||||
FIX32 lcSysSensY;
|
||||
} LOGCONTEXTA, *PLOGCONTEXTA, NEAR *NPLOGCONTEXTA, FAR *LPLOGCONTEXTA;
|
||||
|
||||
typedef struct tagEXTENSIONBASE { /* 1.4 */
|
||||
HCTX nContext;
|
||||
UINT nStatus;
|
||||
DWORD nTime;
|
||||
UINT nSerialNumber;
|
||||
} EXTENSIONBASE;
|
||||
|
||||
#endif // wintab.h
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define PACKETDATA PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE
|
||||
#define PACKETMODE 0
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// pktdef.h
|
||||
// -----------------------------------------------------------------------------
|
||||
#if 1
|
||||
|
||||
// TODO: Simplify this file if we have a fixed packet format.
|
||||
// The macros here are too ugly.
|
||||
|
||||
#ifndef PACKETNAME
|
||||
/* if no packet name prefix */
|
||||
#define __PFX(x) x
|
||||
#define __IFX(x,y) x ## y
|
||||
#else
|
||||
/* add prefixes and infixes to packet format names */
|
||||
#define __PFX(x) __PFX2(PACKETNAME,x)
|
||||
#define __PFX2(p,x) __PFX3(p,x)
|
||||
#define __PFX3(p,x) p ## x
|
||||
#define __IFX(x,y) __IFX2(x,PACKETNAME,y)
|
||||
#define __IFX2(x,i,y) __IFX3(x,i,y)
|
||||
#define __IFX3(x,i,y) x ## i ## y
|
||||
#endif
|
||||
|
||||
#define __SFX2(x,s) __SFX3(x,s)
|
||||
#define __SFX3(x,s) x ## s
|
||||
|
||||
#define __TAG __IFX(tag,PACKET)
|
||||
#define __TYPES __PFX(PACKET), * __IFX(P,PACKET), NEAR * __IFX(NP,PACKET), FAR * __IFX(LP,PACKET)
|
||||
|
||||
#define __TAGE __IFX(tag,PACKETEXT)
|
||||
#define __TYPESE __PFX(PACKETEXT), * __IFX(P,PACKETEXT), NEAR * __IFX(NP,PACKETEXT), FAR * __IFX(LP,PACKETEXT)
|
||||
|
||||
#define __DATA (__PFX(PACKETDATA))
|
||||
#define __MODE (__PFX(PACKETMODE))
|
||||
#define __EXT(x) __SFX2(__PFX(PACKET),x)
|
||||
|
||||
|
||||
typedef struct __TAG {
|
||||
#if (__DATA & PK_CONTEXT)
|
||||
HCTX pkContext;
|
||||
#endif
|
||||
#if (__DATA & PK_STATUS)
|
||||
UINT pkStatus;
|
||||
#endif
|
||||
#if (__DATA & PK_TIME)
|
||||
DWORD pkTime;
|
||||
#endif
|
||||
#if (__DATA & PK_CHANGED)
|
||||
WTPKT pkChanged;
|
||||
#endif
|
||||
#if (__DATA & PK_SERIAL_NUMBER)
|
||||
UINT pkSerialNumber;
|
||||
#endif
|
||||
#if (__DATA & PK_CURSOR)
|
||||
UINT pkCursor;
|
||||
#endif
|
||||
#if (__DATA & PK_BUTTONS)
|
||||
DWORD pkButtons;
|
||||
#endif
|
||||
#if (__DATA & PK_X)
|
||||
LONG pkX;
|
||||
#endif
|
||||
#if (__DATA & PK_Y)
|
||||
LONG pkY;
|
||||
#endif
|
||||
#if (__DATA & PK_Z)
|
||||
LONG pkZ;
|
||||
#endif
|
||||
#if (__DATA & PK_NORMAL_PRESSURE)
|
||||
#if (__MODE & PK_NORMAL_PRESSURE)
|
||||
/* relative */
|
||||
int pkNormalPressure;
|
||||
#else
|
||||
/* absolute */
|
||||
UINT pkNormalPressure;
|
||||
#endif
|
||||
#endif
|
||||
#if (__DATA & PK_TANGENT_PRESSURE)
|
||||
#if (__MODE & PK_TANGENT_PRESSURE)
|
||||
/* relative */
|
||||
int pkTangentPressure;
|
||||
#else
|
||||
/* absolute */
|
||||
UINT pkTangentPressure;
|
||||
#endif
|
||||
#endif
|
||||
#if (__DATA & PK_ORIENTATION)
|
||||
ORIENTATION pkOrientation;
|
||||
#endif
|
||||
#if (__DATA & PK_ROTATION)
|
||||
ROTATION pkRotation; /* 1.1 */
|
||||
#endif
|
||||
|
||||
#ifndef NOWTEXTENSIONS
|
||||
/* extensions begin here. */
|
||||
#if (__EXT(FKEYS) == PKEXT_RELATIVE) || (__EXT(FKEYS) == PKEXT_ABSOLUTE)
|
||||
UINT pkFKeys;
|
||||
#endif
|
||||
#if (__EXT(TILT) == PKEXT_RELATIVE) || (__EXT(TILT) == PKEXT_ABSOLUTE)
|
||||
TILT pkTilt;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} __TYPES;
|
||||
|
||||
#ifndef NOWTEXTENSIONS
|
||||
typedef struct __TAGE {
|
||||
EXTENSIONBASE pkBase;
|
||||
|
||||
#if (__EXT(EXPKEYS) == PKEXT_RELATIVE) || (__EXT(EXPKEYS) == PKEXT_ABSOLUTE)
|
||||
EXPKEYSDATA pkExpKeys; /* 1.4 */
|
||||
#endif
|
||||
#if (__EXT(TOUCHSTRIP) == PKEXT_RELATIVE) || (__EXT(TOUCHSTRIP) == PKEXT_ABSOLUTE)
|
||||
SLIDERDATA pkTouchStrip; /* 1.4 */
|
||||
#endif
|
||||
#if (__EXT(TOUCHRING) == PKEXT_RELATIVE) || (__EXT(TOUCHRING) == PKEXT_ABSOLUTE)
|
||||
SLIDERDATA pkTouchRing; /* 1.4 */
|
||||
#endif
|
||||
|
||||
} __TYPESE;
|
||||
#endif
|
||||
|
||||
#undef PACKETNAME
|
||||
#undef __TAG
|
||||
#undef __TAGE
|
||||
#undef __TAG2
|
||||
#undef __TYPES
|
||||
#undef __TYPESE
|
||||
#undef __TYPES2
|
||||
#undef __DATA
|
||||
#undef __MODE
|
||||
#undef __PFX
|
||||
#undef __PFX2
|
||||
#undef __PFX3
|
||||
#undef __IFX
|
||||
#undef __IFX2
|
||||
#undef __IFX3
|
||||
#undef __SFX2
|
||||
#undef __SFX3
|
||||
|
||||
#endif // pktdef.h
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef UINT (WINAPI * WTINFOA) (UINT, UINT, LPVOID);
|
||||
typedef HCTX (WINAPI * WTOPENA) (HWND, LPLOGCONTEXTA, BOOL);
|
||||
typedef BOOL (WINAPI * WTGETA) (HCTX, LPLOGCONTEXTA);
|
||||
typedef BOOL (WINAPI * WTSETA) (HCTX, LPLOGCONTEXTA);
|
||||
typedef BOOL (WINAPI * WTCLOSE) (HCTX);
|
||||
typedef BOOL (WINAPI * WTENABLE) (HCTX, BOOL);
|
||||
typedef BOOL (WINAPI * WTPACKET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTOVERLAP) (HCTX, BOOL);
|
||||
typedef BOOL (WINAPI * WTSAVE) (HCTX, LPVOID);
|
||||
typedef BOOL (WINAPI * WTCONFIG) (HCTX, HWND);
|
||||
typedef HCTX (WINAPI * WTRESTORE) (HWND, LPVOID, BOOL);
|
||||
typedef BOOL (WINAPI * WTEXTSET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTEXTGET) (HCTX, UINT, LPVOID);
|
||||
typedef BOOL (WINAPI * WTQUEUESIZESET) (HCTX, int);
|
||||
typedef int (WINAPI * WTDATAPEEK) (HCTX, UINT, UINT, int, LPVOID, LPINT);
|
||||
typedef int (WINAPI * WTPACKETSGET) (HCTX, int, LPVOID);
|
||||
typedef HMGR (WINAPI * WTMGROPEN) (HWND, UINT);
|
||||
typedef BOOL (WINAPI * WTMGRCLOSE) (HMGR);
|
||||
typedef HCTX (WINAPI * WTMGRDEFCONTEXT) (HMGR, BOOL);
|
||||
typedef HCTX (WINAPI * WTMGRDEFCONTEXTEX) (HMGR, UINT, BOOL);
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Enums
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Use this enum in conjunction with EasyTab->Buttons to check for tablet button
|
||||
presses.
|
||||
e.g. To check for lower pen button press, use:
|
||||
|
||||
if (EasyTab->Buttons & EasyTab_Buttons_Pen_Lower)
|
||||
{
|
||||
// Lower button is pressed
|
||||
}
|
||||
*/
|
||||
enum EasyTab_Buttons_
|
||||
{
|
||||
EasyTab_Buttons_Pen_Touch = 1 << 0, // Pen is touching tablet
|
||||
EasyTab_Buttons_Pen_Lower = 1 << 1, // Lower pen button is pressed
|
||||
EasyTab_Buttons_Pen_Upper = 1 << 2, // Upper pen button is pressed
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Structs
|
||||
// -----------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
int32_t PosX, PosY;
|
||||
float Pressure; // Range: 0.0f to 1.0f
|
||||
int32_t Buttons; // Bit field. Use with the EasyTab_Buttons_ enum.
|
||||
|
||||
int32_t RangeX, RangeY;
|
||||
int32_t MaxPressure;
|
||||
|
||||
#ifdef __linux__
|
||||
XDevice* Device;
|
||||
uint32_t MotionType;
|
||||
XEventClass EventClasses[1024];
|
||||
uint32_t NumEventClasses;
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef WIN32
|
||||
HINSTANCE Dll;
|
||||
HCTX Context;
|
||||
|
||||
WTINFOA WTInfoA;
|
||||
WTOPENA WTOpenA;
|
||||
WTGETA WTGetA;
|
||||
WTSETA WTSetA;
|
||||
WTCLOSE WTClose;
|
||||
WTPACKET WTPacket;
|
||||
WTENABLE WTEnable;
|
||||
WTOVERLAP WTOverlap;
|
||||
WTSAVE WTSave;
|
||||
WTCONFIG WTConfig;
|
||||
WTRESTORE WTRestore;
|
||||
WTEXTSET WTExtSet;
|
||||
WTEXTGET WTExtGet;
|
||||
WTQUEUESIZESET WTQueueSizeSet;
|
||||
WTDATAPEEK WTDataPeek;
|
||||
WTPACKETSGET WTPacketsGet;
|
||||
WTMGROPEN WTMgrOpen;
|
||||
WTMGRCLOSE WTMgrClose;
|
||||
WTMGRDEFCONTEXT WTMgrDefContext;
|
||||
WTMGRDEFCONTEXTEX WTMgrDefContextEx;
|
||||
#endif // WIN32
|
||||
} EasyTabInfo;
|
||||
|
||||
extern EasyTabInfo* EasyTab;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(__linux__)
|
||||
|
||||
EasyTabResult EasyTab_Load(Display* Disp, Window Win);
|
||||
EasyTabResult EasyTab_HandleEvent(XEvent* Event);
|
||||
void EasyTab_Unload(Display* Disp);
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
EasyTabResult EasyTab_Load(HWND Window);
|
||||
EasyTabResult EasyTab_Load_Ex(HWND Window,
|
||||
EasyTabTrackingMode Mode,
|
||||
float RelativeModeSensitivity,
|
||||
int32_t MoveCursor);
|
||||
EasyTabResult EasyTab_HandleEvent(HWND Window,
|
||||
UINT Message,
|
||||
LPARAM LParam,
|
||||
WPARAM WParam);
|
||||
void EasyTab_Unload();
|
||||
|
||||
#else
|
||||
|
||||
// Save some trouble when porting.
|
||||
#error "Unsupported platform."
|
||||
|
||||
#endif // __linux__ _WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#endif // EASYTAB_H
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// EasyTab implementation section
|
||||
// =============================================================================
|
||||
|
||||
#ifdef EASYTAB_IMPLEMENTATION
|
||||
|
||||
EasyTabInfo* EasyTab;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Linux implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifdef __linux__
|
||||
|
||||
EasyTabResult EasyTab_Load(Display* Disp, Window Win)
|
||||
{
|
||||
EasyTab = (EasyTabInfo*)calloc(1, sizeof(EasyTabInfo)); // We want init to zero, hence calloc.
|
||||
if (!EasyTab) { return EASYTAB_MEMORY_ERROR; }
|
||||
|
||||
int32_t Count;
|
||||
XDeviceInfoPtr Devices = (XDeviceInfoPtr)XListInputDevices(Disp, &Count);
|
||||
if (!Devices) { return EASYTAB_X11_ERROR; }
|
||||
|
||||
for (int32_t i = 0; i < Count; i++)
|
||||
{
|
||||
if (!strstr(Devices[i].name, "stylus") &&
|
||||
!strstr(Devices[i].name, "eraser")) { continue; }
|
||||
|
||||
EasyTab->Device = XOpenDevice(Disp, Devices[i].id);
|
||||
XAnyClassPtr ClassPtr = Devices[i].inputclassinfo;
|
||||
|
||||
for (int32_t j = 0; j < Devices[i].num_classes; j++)
|
||||
{
|
||||
#if defined(__cplusplus)
|
||||
switch (ClassPtr->c_class)
|
||||
#else
|
||||
switch (ClassPtr->class)
|
||||
#endif
|
||||
{
|
||||
case ValuatorClass:
|
||||
{
|
||||
XValuatorInfo *Info = (XValuatorInfo *)ClassPtr;
|
||||
// X
|
||||
if (Info->num_axes > 0)
|
||||
{
|
||||
int32_t min = Info->axes[0].min_value;
|
||||
EasyTab->RangeX = Info->axes[0].max_value;
|
||||
//printf("Max/min x values: %d, %d\n", min, EasyTab->RangeX); // TODO: Platform-print macro
|
||||
}
|
||||
|
||||
// Y
|
||||
if (Info->num_axes > 1)
|
||||
{
|
||||
int32_t min = Info->axes[1].min_value;
|
||||
EasyTab->RangeY = Info->axes[1].max_value;
|
||||
//printf("Max/min y values: %d, %d\n", min, EasyTab->RangeY);
|
||||
}
|
||||
|
||||
// Pressure
|
||||
if (Info->num_axes > 2)
|
||||
{
|
||||
int32_t min = Info->axes[2].min_value;
|
||||
EasyTab->MaxPressure = Info->axes[2].max_value;
|
||||
//printf("Max/min pressure values: %d, %d\n", min, EasyTab->MaxPressure);
|
||||
}
|
||||
|
||||
XEventClass EventClass;
|
||||
DeviceMotionNotify(EasyTab->Device, EasyTab->MotionType, EventClass);
|
||||
if (EventClass)
|
||||
{
|
||||
EasyTab->EventClasses[EasyTab->NumEventClasses] = EventClass;
|
||||
EasyTab->NumEventClasses++;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
ClassPtr = (XAnyClassPtr) ((uint8_t*)ClassPtr + ClassPtr->length); // TODO: Access this as an array to avoid pointer arithmetic?
|
||||
}
|
||||
|
||||
XSelectExtensionEvent(Disp, Win, EasyTab->EventClasses, EasyTab->NumEventClasses);
|
||||
}
|
||||
|
||||
XFreeDeviceList(Devices);
|
||||
|
||||
if (EasyTab->Device != 0) { return EASYTAB_OK; }
|
||||
else { return EASYTAB_X11_ERROR; }
|
||||
}
|
||||
|
||||
EasyTabResult EasyTab_HandleEvent(XEvent* Event)
|
||||
{
|
||||
if (Event->type != EasyTab->MotionType) { return EASYTAB_EVENT_NOT_HANDLED; }
|
||||
|
||||
XDeviceMotionEvent* MotionEvent = (XDeviceMotionEvent*)(Event);
|
||||
EasyTab->PosX = MotionEvent->x;
|
||||
EasyTab->PosY = MotionEvent->y;
|
||||
EasyTab->Pressure = (float)MotionEvent->axis_data[2] / (float)EasyTab->MaxPressure;
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
void EasyTab_Unload(Display* Disp)
|
||||
{
|
||||
XCloseDevice(Disp, EasyTab->Device);
|
||||
free(EasyTab);
|
||||
EasyTab = NULL;
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Windows implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifdef WIN32
|
||||
|
||||
#define GETPROCADDRESS(type, func) \
|
||||
EasyTab->func = (type)GetProcAddress(EasyTab->Dll, #func); \
|
||||
if (!EasyTab->func) \
|
||||
{ \
|
||||
OutputDebugStringA("Function " #func " not found in Wintab32.dll.\n"); \
|
||||
return EASYTAB_INVALID_FUNCTION_ERROR; \
|
||||
}
|
||||
|
||||
|
||||
EasyTabResult EasyTab_Load(HWND Window)
|
||||
{
|
||||
return EasyTab_Load_Ex(Window, EASYTAB_TRACKING_MODE_SYSTEM, 0, 1);
|
||||
}
|
||||
|
||||
EasyTabResult EasyTab_Load_Ex(HWND Window,
|
||||
EasyTabTrackingMode TrackingMode,
|
||||
float RelativeModeSensitivity,
|
||||
int32_t MoveCursor)
|
||||
{
|
||||
EasyTab = (EasyTabInfo*)calloc(1, sizeof(EasyTabInfo)); // We want init to zero, hence calloc.
|
||||
if (!EasyTab) { return EASYTAB_MEMORY_ERROR; }
|
||||
|
||||
// Load Wintab DLL and get function addresses
|
||||
{
|
||||
EasyTab->Dll = LoadLibraryA("Wintab32.dll");
|
||||
if (!EasyTab->Dll)
|
||||
{
|
||||
OutputDebugStringA("Wintab32.dll not found.\n");
|
||||
return EASYTAB_DLL_LOAD_ERROR;
|
||||
}
|
||||
|
||||
GETPROCADDRESS(WTINFOA , WTInfoA);
|
||||
GETPROCADDRESS(WTOPENA , WTOpenA);
|
||||
GETPROCADDRESS(WTGETA , WTGetA);
|
||||
GETPROCADDRESS(WTSETA , WTSetA);
|
||||
GETPROCADDRESS(WTCLOSE , WTClose);
|
||||
GETPROCADDRESS(WTPACKET , WTPacket);
|
||||
GETPROCADDRESS(WTENABLE , WTEnable);
|
||||
GETPROCADDRESS(WTOVERLAP , WTOverlap);
|
||||
GETPROCADDRESS(WTSAVE , WTSave);
|
||||
GETPROCADDRESS(WTCONFIG , WTConfig);
|
||||
GETPROCADDRESS(WTRESTORE , WTRestore);
|
||||
GETPROCADDRESS(WTEXTSET , WTExtSet);
|
||||
GETPROCADDRESS(WTEXTGET , WTExtGet);
|
||||
GETPROCADDRESS(WTQUEUESIZESET , WTQueueSizeSet);
|
||||
GETPROCADDRESS(WTDATAPEEK , WTDataPeek);
|
||||
GETPROCADDRESS(WTPACKETSGET , WTPacketsGet);
|
||||
GETPROCADDRESS(WTMGROPEN , WTMgrOpen);
|
||||
GETPROCADDRESS(WTMGRCLOSE , WTMgrClose);
|
||||
GETPROCADDRESS(WTMGRDEFCONTEXT , WTMgrDefContext);
|
||||
GETPROCADDRESS(WTMGRDEFCONTEXTEX , WTMgrDefContextEx);
|
||||
}
|
||||
|
||||
if (!EasyTab->WTInfoA(0, 0, NULL))
|
||||
{
|
||||
OutputDebugStringA("Wintab services not available.\n");
|
||||
return EASYTAB_WACOM_WIN32_ERROR;
|
||||
}
|
||||
|
||||
// Open context
|
||||
{
|
||||
LOGCONTEXTA LogContext = {0};
|
||||
AXIS RangeX = {0};
|
||||
AXIS RangeY = {0};
|
||||
AXIS Pressure = {0};
|
||||
|
||||
EasyTab->WTInfoA(WTI_DDCTXS, 0, &LogContext);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_X, &RangeX);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_Y, &RangeY);
|
||||
EasyTab->WTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
|
||||
LogContext.lcPktData = PACKETDATA; // ??
|
||||
LogContext.lcOptions |= CXO_MESSAGES;
|
||||
if (MoveCursor) { LogContext.lcOptions |= CXO_SYSTEM; }
|
||||
LogContext.lcPktMode = PACKETMODE;
|
||||
LogContext.lcMoveMask = PACKETDATA;
|
||||
LogContext.lcBtnUpMask = LogContext.lcBtnDnMask;
|
||||
|
||||
LogContext.lcOutOrgX = 0;
|
||||
LogContext.lcOutOrgY = 0;
|
||||
LogContext.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
|
||||
LogContext.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
LogContext.lcSysOrgX = 0;
|
||||
LogContext.lcSysOrgY = 0;
|
||||
LogContext.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
|
||||
LogContext.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
if (TrackingMode == EASYTAB_TRACKING_MODE_RELATIVE)
|
||||
{
|
||||
LogContext.lcPktMode |= PK_X | PK_Y; // TODO: Should this be included in the
|
||||
// PACKETMODE macro define up top?
|
||||
LogContext.lcSysMode = 1;
|
||||
|
||||
if (RelativeModeSensitivity > 1.0f)
|
||||
{
|
||||
RelativeModeSensitivity = 1.0f;
|
||||
}
|
||||
else if (RelativeModeSensitivity < 0.0f)
|
||||
{
|
||||
RelativeModeSensitivity = 0.0f;
|
||||
}
|
||||
|
||||
// Wintab expects sensitivity to be a 32-bit fixed point number
|
||||
// with the radix point between the two words. Thus, the type
|
||||
// contains 16 bits to the left of the radix point and 16 bits to
|
||||
// the right of it.
|
||||
//
|
||||
// 0x10000 Hex
|
||||
// = 65,536 Decimal
|
||||
// = 0000 0000 0000 0001 . 0000 0000 0000 0000 Binary
|
||||
// = 1.0 Fixed Point
|
||||
uint32_t Sensitivity = (uint32_t)(0x10000 * RelativeModeSensitivity);
|
||||
|
||||
if (MoveCursor)
|
||||
{
|
||||
LogContext.lcSysSensX = LogContext.lcSysSensY = Sensitivity;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext.lcSensX = LogContext.lcSensY = Sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
EasyTab->Context = EasyTab->WTOpenA(Window, &LogContext, TRUE);
|
||||
|
||||
if (!EasyTab->Context)
|
||||
{
|
||||
OutputDebugStringA("Wintab context couldn't be opened.\n");
|
||||
return EASYTAB_WACOM_WIN32_ERROR;
|
||||
}
|
||||
|
||||
// Get tablet capabilites
|
||||
{
|
||||
EasyTab->MaxPressure = Pressure.axMax;
|
||||
EasyTab->RangeX = RangeX.axMax;
|
||||
EasyTab->RangeY = RangeY.axMax;
|
||||
}
|
||||
}
|
||||
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
#undef GETPROCADDRESS
|
||||
|
||||
EasyTabResult EasyTab_HandleEvent(HWND Window, UINT Message, LPARAM LParam, WPARAM WParam)
|
||||
{
|
||||
PACKET Packet = { 0 };
|
||||
|
||||
if (Message == WT_PACKET &&
|
||||
(HCTX)LParam == EasyTab->Context &&
|
||||
EasyTab->WTPacket(EasyTab->Context, (UINT)WParam, &Packet))
|
||||
{
|
||||
POINT Point = { 0 };
|
||||
Point.x = Packet.pkX;
|
||||
Point.y = Packet.pkY;
|
||||
ScreenToClient(Window, &Point);
|
||||
EasyTab->PosX = Point.x;
|
||||
EasyTab->PosY = Point.y;
|
||||
|
||||
EasyTab->Pressure = (float)Packet.pkNormalPressure / (float)EasyTab->MaxPressure;
|
||||
EasyTab->Buttons = Packet.pkButtons;
|
||||
return EASYTAB_OK;
|
||||
}
|
||||
|
||||
return EASYTAB_EVENT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void EasyTab_Unload()
|
||||
{
|
||||
if (EasyTab->Context) { EasyTab->WTClose(EasyTab->Context); }
|
||||
if (EasyTab->Dll) { FreeLibrary(EasyTab->Dll); }
|
||||
free(EasyTab);
|
||||
EasyTab = NULL;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // EASYTAB_IMPLEMENTATION
|
||||
Loading…
Add table
Add a link
Reference in a new issue