add wacom support on Windows

This commit is contained in:
2017-05-17 00:33:02 +01:00
parent c987b19c83
commit 6d14ccd426
10 changed files with 1773 additions and 17 deletions

View File

@@ -369,7 +369,8 @@ HGLRC hRC;
wchar_t* className;
bool keys[256];
#include <WbemCli.h>
#include <WbemCli.h>
#include "wacom.h"
int read_WMI_info()
{
@@ -585,6 +586,7 @@ int main()
App::I.init();
ShowWindow(hWnd, SW_NORMAL);
WacomTablet::I.init(hWnd);
MSG msg;
bool running = true;
@@ -618,6 +620,7 @@ int main()
}
// Clean up
WacomTablet::I.terminate();
DestroyWindow(hWnd);
UnregisterClass(className, hInst);
}
@@ -635,6 +638,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
App::I.update(0.f);
SwapBuffers(hDC);
break;
case WM_ACTIVATE:
{
int active = GET_WM_ACTIVATE_STATE(wp, lp);
WacomTablet::I.set_focus(active);
break;
}
case WT_PACKET:
WacomTablet::I.handle_message(hWnd, msg, wp, lp);
break;
case WM_KEYDOWN:
keys[wp] = true;
App::I.key_down(convert_key((int)wp));
@@ -647,10 +659,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
App::I.key_char((int)wp);
break;
case WM_MOUSEMOVE:
App::I.mouse_move((float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp));
App::I.mouse_move((float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), WacomTablet::I.get_pressure());
break;
case WM_LBUTTONDOWN:
App::I.mouse_down(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp));
App::I.mouse_down(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), WacomTablet::I.get_pressure());
SetCapture(hWnd);
break;
case WM_LBUTTONUP:
@@ -658,7 +670,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
ReleaseCapture();
break;
case WM_RBUTTONDOWN:
App::I.mouse_down(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp));
App::I.mouse_down(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), 1.f);
SetCapture(hWnd);
break;
case WM_RBUTTONUP:

182
engine/wacom.cpp Normal file
View File

@@ -0,0 +1,182 @@
#include "pch.h"
#include "log.h"
#include "wacom.h"
WacomTablet WacomTablet::I;
void WacomTablet::set_focus(int activate)
{
/* if switching in the middle, disable the region */
if (g_hCtx)
{
gpWTEnable(g_hCtx, activate);
if (g_hCtx && activate)
{
gpWTOverlap(g_hCtx, TRUE);
}
}
}
HCTX WacomTablet::TabletInit(HWND hWnd)
{
HCTX hctx = NULL;
UINT wDevice = 0;
UINT wExtX = 0;
UINT wExtY = 0;
UINT wWTInfoRetVal = 0;
AXIS TabletX = { 0 };
AXIS TabletY = { 0 };
// Set option to move system cursor before getting default system context.
glogContext.lcOptions |= CXO_SYSTEM;
// Open default system context so that we can get tablet data
// in screen coordinates (not tablet coordinates).
wWTInfoRetVal = gpWTInfoA(WTI_DEFSYSCTX, 0, &glogContext);
assert(wWTInfoRetVal == sizeof(LOGCONTEXTA));
assert(glogContext.lcOptions & CXO_SYSTEM);
// modify the digitizing region
sprintf_s(glogContext.lcName, "PanoPainter Digitizing %x", (unsigned int)GetModuleHandle(0));
// We process WT_PACKET (CXO_MESSAGES) messages.
glogContext.lcOptions |= CXO_MESSAGES;
// What data items we want to be included in the tablet packets
glogContext.lcPktData = PACKETDATA;
// Which packet items should show change in value since the last
// packet (referred to as 'relative' data) and which items
// should be 'absolute'.
glogContext.lcPktMode = PACKETMODE;
// This bitfield determines whether or not this context will receive
// a packet when a value for each packet field changes. This is not
// supported by the Intuos Wintab. Your context will always receive
// packets, even if there has been no change in the data.
glogContext.lcMoveMask = PACKETDATA;
// Which buttons events will be handled by this context. lcBtnMask
// is a bitfield with one bit per button.
glogContext.lcBtnUpMask = glogContext.lcBtnDnMask;
// Set the entire tablet as active
wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_X, &TabletX);
assert(wWTInfoRetVal == sizeof(AXIS));
wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_Y, &TabletY);
assert(wWTInfoRetVal == sizeof(AXIS));
// Pressure resolution
wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &TabletPressure);
assert(wWTInfoRetVal == sizeof(AXIS));
LOG("Tablet pressure: %d", TabletPressure.axMin);
wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_NAME, 0);
if (wWTInfoRetVal > 0)
{
CHAR* TabletName = new CHAR[wWTInfoRetVal];
wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_NAME, TabletName);
LOG("Tablet: %s", TabletName);
delete TabletName;
}
/*
glogContext.lcInOrgX = 0;
glogContext.lcInOrgY = 0;
glogContext.lcInExtX = TabletX.axMax;
glogContext.lcInExtY = TabletY.axMax;
// Guarantee the output coordinate space to be in screen coordinates.
glogContext.lcOutOrgX = GetSystemMetrics( SM_XVIRTUALSCREEN );
glogContext.lcOutOrgY = GetSystemMetrics( SM_YVIRTUALSCREEN );
glogContext.lcOutExtX = GetSystemMetrics( SM_CXSCREEN / *SM_CXVIRTUALSCREEN* / ); //SM_CXSCREEN );
// In Wintab, the tablet origin is lower left. Move origin to upper left
// so that it coincides with screen origin.
glogContext.lcOutExtY = -GetSystemMetrics( SM_CYSCREEN / *SM_CYVIRTUALSCREEN* / ); //SM_CYSCREEN );
*/
// Leave the system origin and extents as received:
// lcSysOrgX, lcSysOrgY, lcSysExtX, lcSysExtY
// open the region
// The Wintab spec says we must open the context disabled if we are
// using cursor masks.
hctx = gpWTOpenA(hWnd, &glogContext, FALSE);
LOG("HCTX: %i", (int)hctx);
return hctx;
}
bool WacomTablet::init(HWND hWnd)
{
// Init WinTab
if (LoadWintab())
{
/* check if WinTab available. */
if (gpWTInfoA(0, 0, NULL))
{
g_hCtx = TabletInit(hWnd);
if (!g_hCtx)
{
LOG("Could Not Open Tablet Context.");
return false;
}
else
{
set_focus(true);
return true;
}
}
else
{
LOG("WinTab Services Not Available.");
return false;
}
}
else
{
LOG("Unable to initialize Wacom WinTab");
return false;
}
}
void WacomTablet::terminate()
{
UnloadWintab();
}
void WacomTablet::handle_message(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PACKET pkt;
static POINT ptOld, ptNew;
static UINT prsOld, prsNew;
if (gpWTPacket((HCTX)lParam, wParam, &pkt))
{
if (HIWORD(pkt.pkButtons) == TBN_DOWN)
m_pen_down = true;
if (HIWORD(pkt.pkButtons) == TBN_UP)
m_pen_down = false;
ptOld = ptNew;
prsOld = prsNew;
ptNew.x = pkt.pkX;
ptNew.y = pkt.pkY;
prsNew = pkt.pkNormalPressure;
m_pen_pos = { pkt.pkX, pkt.pkX };
m_pen_pres = (float)pkt.pkNormalPressure / (float)TabletPressure.axMax;
}
}
float WacomTablet::get_pressure() const
{
return m_pen_down ? m_pen_pres : 1.f;
}

29
engine/wacom.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include "WinTab/msgpack.h"
#include "WinTab/wintab.h"
#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE)
#define PACKETMODE PK_BUTTONS
#include "WinTab/pktdef.h"
#include "WinTab/Utils.h"
class WacomTablet
{
HCTX g_hCtx = NULL;
AXIS TabletPressure = { 0 };
LOGCONTEXTA glogContext = { 0 };
glm::vec2 m_pen_pos{ 0 };
float m_pen_pres{ 1 };
bool m_pen_down = false;
int m_pen_idle = 0;
bool m_mouse_down = false;
HCTX TabletInit(HWND hWnd);
public:
static WacomTablet I;
bool init(HWND hWnd);
void terminate();
void handle_message(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam);
void set_focus(int activate);
float get_pressure() const;
};