Blender V5.0
GHOST_Wintab.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9
10/* Wacom's Wintab documentation is periodically offline, moved, and increasingly hidden away. You
11 * can find a (painstakingly) archived copy of the documentation at
12 * https://web.archive.org/web/20201122230125/https://developer-docs-legacy.wacom.com/display/DevDocs/Windows+Wintab+Documentation
13 */
14
15#pragma once
16
17#include <memory>
18#include <stdio.h>
19#include <vector>
20#include <wtypes.h>
21
22#include "GHOST_Types.h"
23
24#include <wintab.h>
25/* PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first. */
26#define PACKETDATA \
27 (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
28#define PACKETMODE 0
29#include <pktdef.h>
30
31#if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL
32# define WINTAB_PRINTF(x, ...) \
33 { \
34 if (GHOST_Wintab::getDebug()) { \
35 printf(x, __VA_ARGS__); \
36 } \
37 } \
38 (void)0
39#else
40# define WINTAB_PRINTF(x, ...) \
41 { \
42 if (GHOST_Wintab::getDebug()) { \
43 printf(x, ##__VA_ARGS__); \
44 } \
45 } \
46 (void)0
47#endif
48
49/* Typedefs for Wintab functions to allow dynamic loading. */
50typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
51typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
52typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
53typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
54typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
55typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
56typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
57typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
58typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
59typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
60
61/* Typedefs for Wintab and Windows resource management. */
62typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary)> unique_hmodule;
63typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx;
64
73
74class GHOST_Wintab {
75 public:
81 static GHOST_Wintab *loadWintab(HWND hwnd);
82
84
88 void enable();
89
93 void disable();
94
98 void gainFocus();
99
103 void loseFocus();
104
108 void leaveRange();
109
113 void remapCoordinates();
114
122 void mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out);
123
127 void updateCursorInfo();
128
133 void processInfoChange(LPARAM lParam);
134
139 bool devicesPresent();
140
145 void getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
146
151 bool trustCoordinates();
152
166 bool testCoordinates(int sysX, int sysY, int wtX, int wtY);
167
173
174 /* Sets Wintab debugging.
175 * \param debug: True to enable Wintab debugging.
176 */
177 static void setDebug(bool debug);
178
179 /* Returns whether Wintab logging should occur.
180 * \return True if Wintab logging should occur.
181 */
182 static bool getDebug();
183
184 private:
186 unique_hmodule handle_;
188 GHOST_WIN32_WTInfo fp_info_ = nullptr;
189 GHOST_WIN32_WTGet fp_get_ = nullptr;
190 GHOST_WIN32_WTSet fp_set_ = nullptr;
191 GHOST_WIN32_WTPacketsGet fp_packets_get_ = nullptr;
192 GHOST_WIN32_WTEnable fp_enable_ = nullptr;
193 GHOST_WIN32_WTOverlap fp_overlap_ = nullptr;
194
196 unique_hctx context_;
198 bool enabled_ = false;
200 bool focused_ = false;
201
203 DWORD buttons_ = 0;
204
206 struct Range {
208 int org = 0;
210 int ext = 1;
211 };
212
214 struct Coord {
216 Range x = {};
218 Range y = {};
219 };
221 bool coord_trusted_ = false;
223 Coord tablet_coord_ = {};
225 Coord system_coord_ = {};
226
227 int max_pressure_ = 0;
228 int max_azimuth_ = 0;
229 int max_altitude_ = 0;
230
232 UINT num_devices_ = 0;
234 std::vector<PACKET> pkts_;
236 GHOST_TabletData last_tablet_data_ = GHOST_TABLET_DATA_NONE;
237
239 static bool debug_;
240
241 GHOST_Wintab(unique_hmodule handle,
245 GHOST_WIN32_WTPacketsGet packetsGet,
247 GHOST_WIN32_WTOverlap overlap,
248 unique_hctx hctx,
249 Coord tablet,
250 Coord system,
251 size_t queueSize);
252
259 GHOST_TButton mapWintabToGhostButton(UINT cursor, WORD physicalButton);
260
265 static GHOST_Wintab *loadWintabUnsafe(HWND hwnd);
266
271 static void modifyContext(LOGCONTEXT &lc);
272
279 static void extractCoordinates(LOGCONTEXT &lc, Coord &tablet, Coord &system);
280
281 /* Prints Wintab Context information. */
282 void printContextDebugInfo();
283};
GHOST_TEventType
@ GHOST_kEventCursorMove
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
GHOST_TButton
@ GHOST_kButtonMaskNone
BOOL(API * GHOST_WIN32_WTOverlap)(HCTX, BOOL)
BOOL(API * GHOST_WIN32_WTEnable)(HCTX, BOOL)
std::unique_ptr< std::remove_pointer_t< HCTX >, GHOST_WIN32_WTClose > unique_hctx
HCTX(API * GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL)
BOOL(API * GHOST_WIN32_WTClose)(HCTX)
BOOL(API * GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA)
std::unique_ptr< std::remove_pointer_t< HMODULE >, decltype(&::FreeLibrary)> unique_hmodule
BOOL(API * GHOST_WIN32_WTQueueSizeSet)(HCTX, int)
BOOL(API * GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA)
UINT(API * GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID)
int(API * GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID)
int(API * GHOST_WIN32_WTQueueSizeGet)(HCTX)
unsigned long long int uint64_t
void mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out)
GHOST_TabletData getLastTabletData()
bool devicesPresent()
void getInput(std::vector< GHOST_WintabInfoWin32 > &outWintabInfo)
void processInfoChange(LPARAM lParam)
void updateCursorInfo()
void remapCoordinates()
static GHOST_Wintab * loadWintab(HWND hwnd)
bool trustCoordinates()
static bool getDebug()
bool testCoordinates(int sysX, int sysY, int wtX, int wtY)
static void setDebug(bool debug)
GHOST_TEventType type
GHOST_TabletData tabletData