mirror of
https://github.com/glfw/glfw.git
synced 2025-10-03 13:20:58 +00:00
Add minimal wintab32 support
This commit is contained in:
parent
2fbb560eb7
commit
79ac263771
@ -1510,6 +1510,57 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
|
||||
*/
|
||||
typedef void (* GLFWjoystickfun)(int,int);
|
||||
|
||||
/*! @brief The function signature for pen tablet data callbacks.
|
||||
*
|
||||
* This is the function signature for pen tablet data callback functions.
|
||||
*
|
||||
* @param[in] x pen position relative to the screen.
|
||||
* @param[in] y pen position relative to the screen.
|
||||
* @param[in] z pen position relative to the tablet.
|
||||
* @param[in] pen pressure from 0.0 to 1.0.
|
||||
* @param[in] pen pitch in degree.
|
||||
* @param[in] pen yaw in degree.
|
||||
* @param[in] pen roll in degree.
|
||||
*
|
||||
* @sa @ref pen_tablet_data
|
||||
* @sa @ref glfwSetPenTabletDataCallback
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef void (* GLFWpentabletdatafun)(double,double,double,double,double,double,double);
|
||||
|
||||
/*! @brief The function signature for pen tablet cursor callbacks.
|
||||
*
|
||||
* This is the function signature for pen tablet cursor callback functions.
|
||||
*
|
||||
* @param[in] pen cursor identifier.
|
||||
*
|
||||
* @sa @ref pen_tablet_cursor
|
||||
* @sa @ref glfwSetPenTabletCursorCallback
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef void (* GLFWpentabletcursorfun)(unsigned int);
|
||||
|
||||
/*! @brief The function signature for pen tablet proximity callbacks.
|
||||
*
|
||||
* This is the function signature for pen tablet proximity callback functions.
|
||||
*
|
||||
* @param[in] pen proximity state.
|
||||
*
|
||||
* @sa @ref pen_tablet_proximity
|
||||
* @sa @ref glfwSetPenTabletProximityCallback
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef void (* GLFWpentabletproximityfun)(int);
|
||||
|
||||
/*! @brief Video mode type.
|
||||
*
|
||||
* This describes a single video mode.
|
||||
@ -4963,6 +5014,72 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
||||
*/
|
||||
GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
|
||||
|
||||
/*! @brief Sets the pen tablet data callback.
|
||||
*
|
||||
* This function sets the pen tablet data callback, or removes the
|
||||
* currently set callback. This is called when the pen tablet data is updated.
|
||||
*
|
||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||
* callback.
|
||||
* @return The previously set callback, or `NULL` if no callback was set or the
|
||||
* library had not been [initialized](@ref intro_init).
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref pen_tablet_event
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWpentabletdatafun glfwSetPenTabletDataCallback(GLFWpentabletdatafun cbfun);
|
||||
|
||||
/*! @brief Sets the pen tablet cursor callback.
|
||||
*
|
||||
* This function sets the pen tablet cursor callback, or removes the
|
||||
* currently set callback. This is called when the pen tablet cursor has changed.
|
||||
*
|
||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||
* callback.
|
||||
* @return The previously set callback, or `NULL` if no callback was set or the
|
||||
* library had not been [initialized](@ref intro_init).
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref pen_tablet_event
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWpentabletcursorfun glfwSetPenTabletCursorCallback(GLFWpentabletcursorfun cbfun);
|
||||
|
||||
/*! @brief Sets the pen tablet proximity callback.
|
||||
*
|
||||
* This function sets the pen tablet proximity callback, or removes the
|
||||
* currently set callback. This is called when the pen tablet proximity has changed.
|
||||
*
|
||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||
* callback.
|
||||
* @return The previously set callback, or `NULL` if no callback was set or the
|
||||
* library had not been [initialized](@ref intro_init).
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref pen_tablet_event
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWpentabletproximityfun glfwSetPenTabletProximityCallback(GLFWpentabletproximityfun cbfun);
|
||||
|
||||
/*! @brief Sets the clipboard to the specified string.
|
||||
*
|
||||
* This function sets the system clipboard to the specified, UTF-8 encoded
|
||||
|
44
src/input.c
44
src/input.c
@ -401,6 +401,29 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
|
||||
js->hats[hat] = value;
|
||||
}
|
||||
|
||||
// Notifies shared code of the new value of the pen tablet data
|
||||
//
|
||||
void _glfwInputPenTabletData(double x, double y, double z, double pressure, double pitch, double yaw, double roll)
|
||||
{
|
||||
if (_glfw.callbacks.pentabletdata)
|
||||
_glfw.callbacks.pentabletdata(x, y, z, pressure, pitch, yaw, roll);
|
||||
}
|
||||
|
||||
// Notifies shared code of the new value of the pen tablet cursor
|
||||
//
|
||||
void _glfwInputPenTabletCursor(unsigned int cursor)
|
||||
{
|
||||
if (_glfw.callbacks.pentabletcursor)
|
||||
_glfw.callbacks.pentabletcursor(cursor);
|
||||
}
|
||||
|
||||
// Notifies shared code of the new value of the pen tablet proximity
|
||||
//
|
||||
void _glfwInputPenTabletProximity(int proximity)
|
||||
{
|
||||
if (_glfw.callbacks.pentabletproximity)
|
||||
_glfw.callbacks.pentabletproximity(proximity);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@ -1294,6 +1317,27 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWpentabletdatafun glfwSetPenTabletDataCallback(GLFWpentabletdatafun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.pentabletdata, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWpentabletcursorfun glfwSetPenTabletCursorCallback(GLFWpentabletcursorfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.pentabletcursor, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWpentabletproximityfun glfwSetPenTabletProximityCallback(GLFWpentabletproximityfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.pentabletproximity, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||
{
|
||||
assert(string != NULL);
|
||||
|
@ -567,6 +567,9 @@ struct _GLFWlibrary
|
||||
struct {
|
||||
GLFWmonitorfun monitor;
|
||||
GLFWjoystickfun joystick;
|
||||
GLFWpentabletdatafun pentabletdata;
|
||||
GLFWpentabletcursorfun pentabletcursor;
|
||||
GLFWpentabletproximityfun pentabletproximity;
|
||||
} callbacks;
|
||||
|
||||
// This is defined in the window API's platform.h
|
||||
@ -728,6 +731,10 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||
|
||||
void _glfwInputPenTabletData(double x, double y, double z, double pressure, double pitch, double yaw, double roll);
|
||||
void _glfwInputPenTabletCursor(unsigned int cursor);
|
||||
void _glfwInputPenTabletProximity(int proximity);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
void _glfwInputError(int code, const char* format, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
@ -159,6 +159,21 @@ static GLFWbool loadLibraries(void)
|
||||
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
||||
}
|
||||
|
||||
_glfw.win32.wintab32.instance = LoadLibraryA("Wintab32.dll");
|
||||
if (_glfw.win32.wintab32.instance)
|
||||
{
|
||||
_glfw.win32.wintab32.WTInfoA = (PFN_WTInfoA)
|
||||
GetProcAddress(_glfw.win32.wintab32.instance, "WTInfoA");
|
||||
_glfw.win32.wintab32.WTOpenA = (PFN_WTOpenA)
|
||||
GetProcAddress(_glfw.win32.wintab32.instance, "WTOpenA");
|
||||
_glfw.win32.wintab32.WTQueueSizeSet = (PFN_WTQueueSizeSet)
|
||||
GetProcAddress(_glfw.win32.wintab32.instance, "WTQueueSizeSet");
|
||||
_glfw.win32.wintab32.WTClose = (PFN_WTClose)
|
||||
GetProcAddress(_glfw.win32.wintab32.instance, "WTClose");
|
||||
_glfw.win32.wintab32.WTPacket = (PFN_WTPacket)
|
||||
GetProcAddress(_glfw.win32.wintab32.instance, "WTPacket");
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@ -186,6 +201,9 @@ static void freeLibraries(void)
|
||||
|
||||
if (_glfw.win32.ntdll.instance)
|
||||
FreeLibrary(_glfw.win32.ntdll.instance);
|
||||
|
||||
if (_glfw.win32.wintab32.instance)
|
||||
FreeLibrary(_glfw.win32.wintab32.instance);
|
||||
}
|
||||
|
||||
// Create key code translation tables
|
||||
@ -327,6 +345,46 @@ static void createKeyTables(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Init wintab context see https://developer-docs.wacom.com/display/DevDocs/Windows+Wintab+Documentation
|
||||
//
|
||||
static void initWintabContext(HWND hwnd)
|
||||
{
|
||||
if (_glfw.win32.wintab32.instance) {
|
||||
LOGCONTEXTA context = {0};
|
||||
|
||||
_glfw.win32.wintab32.WTInfoA(4, 0, &context);
|
||||
context.lcPktData = 0x0080 | 0x0100 | 0x0200 | 0x0040 | 0x0400 | 0x1000 | 0x0008 | 0x0020; // X Y Z BUTTONS NPRESSURE ORIENTATION CHANGED CURSOR
|
||||
context.lcPktMode = 0;
|
||||
context.lcMoveMask = context.lcPktData;
|
||||
context.lcBtnUpMask = context.lcBtnDnMask;
|
||||
context.lcOptions |= 0x0004; // CXO MESSAGES
|
||||
context.lcOutOrgX = context.lcInOrgX;
|
||||
context.lcOutOrgY = context.lcInOrgY;
|
||||
context.lcOutExtX = context.lcInExtX;
|
||||
context.lcOutExtY = -context.lcInExtY;
|
||||
|
||||
// open wintab context
|
||||
_glfw.win32.wintab32.context = _glfw.win32.wintab32.WTOpenA(hwnd, &context, TRUE);
|
||||
if (_glfw.win32.wintab32.context) {
|
||||
_glfw.win32.wintab32.WTQueueSizeSet(_glfw.win32.wintab32.context, 256);
|
||||
_glfw.win32.wintab32.WTInfoA(4, 0, &_glfw.win32.wintab32.contextInfo);
|
||||
_glfw.win32.wintab32.WTInfoA(100, 15, &_glfw.win32.wintab32.pressureInfo);
|
||||
_glfw.win32.wintab32.WTInfoA(100, 17, &_glfw.win32.wintab32.orientationInfo);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_glfw.win32.wintab32.context = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate wintab context
|
||||
//
|
||||
static void terminateWintabContext(void)
|
||||
{
|
||||
if (_glfw.win32.wintab32.instance && _glfw.win32.wintab32.context)
|
||||
_glfw.win32.wintab32.WTClose(_glfw.win32.wintab32.context);
|
||||
}
|
||||
|
||||
// Creates a dummy window for behind-the-scenes work
|
||||
//
|
||||
static HWND createHelperWindow(void)
|
||||
@ -577,6 +635,7 @@ int _glfwPlatformInit(void)
|
||||
|
||||
_glfwInitTimerWin32();
|
||||
_glfwInitJoysticksWin32();
|
||||
initWintabContext(_glfw.win32.helperWindowHandle);
|
||||
|
||||
_glfwPollMonitorsWin32();
|
||||
return GLFW_TRUE;
|
||||
@ -604,6 +663,7 @@ void _glfwPlatformTerminate(void)
|
||||
_glfwTerminateEGL();
|
||||
|
||||
_glfwTerminateJoysticksWin32();
|
||||
terminateWintabContext();
|
||||
|
||||
freeLibraries();
|
||||
}
|
||||
|
@ -258,6 +258,78 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,
|
||||
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
||||
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
||||
|
||||
// wintab.dll function pointer typedefs
|
||||
#define WT_PACKET 0x7FF0
|
||||
#define WT_PROXIMITY 0x7FF5
|
||||
DECLARE_HANDLE(HCTX);
|
||||
|
||||
typedef struct tagAXIS {
|
||||
LONG min;
|
||||
LONG max;
|
||||
UINT units;
|
||||
DWORD resolution;
|
||||
} AXIS;
|
||||
|
||||
typedef struct tagORIENTATION {
|
||||
int azimuth;
|
||||
int altitude;
|
||||
int twist;
|
||||
} ORIENTATION;
|
||||
|
||||
typedef struct tagPACKET {
|
||||
DWORD changed;
|
||||
UINT cursor;
|
||||
DWORD buttons;
|
||||
DWORD x;
|
||||
DWORD y;
|
||||
DWORD z;
|
||||
UINT normalPressure;
|
||||
ORIENTATION orientation;
|
||||
} PACKET;
|
||||
|
||||
typedef struct LOGCONTEXTA {
|
||||
char lcName[40];
|
||||
UINT lcOptions;
|
||||
UINT lcStatus;
|
||||
UINT lcLocks;
|
||||
UINT lcMsgBase;
|
||||
UINT lcDevice;
|
||||
UINT lcPktRate;
|
||||
DWORD lcPktData;
|
||||
DWORD lcPktMode;
|
||||
DWORD 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;
|
||||
DWORD lcSensX;
|
||||
DWORD lcSensY;
|
||||
DWORD lcSensZ;
|
||||
BOOL lcSysMode;
|
||||
int lcSysOrgX;
|
||||
int lcSysOrgY;
|
||||
int lcSysExtX;
|
||||
int lcSysExtY;
|
||||
DWORD lcSysSensX;
|
||||
DWORD lcSysSensY;
|
||||
} LOGCONTEXTA, *PLOGCONTEXTA, NEAR *NPLOGCONTEXTA, FAR *LPLOGCONTEXTA;
|
||||
|
||||
typedef UINT (WINAPI * PFN_WTInfoA)(UINT,UINT,LPVOID);
|
||||
typedef HCTX (WINAPI * PFN_WTOpenA)(HWND,LPLOGCONTEXTA,BOOL);
|
||||
typedef BOOL (WINAPI * PFN_WTQueueSizeSet)(HCTX,int);
|
||||
typedef BOOL (WINAPI * PFN_WTClose)(HCTX);
|
||||
typedef BOOL (WINAPI * PFN_WTPacket)(HCTX,UINT,LPVOID);
|
||||
|
||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||
|
||||
typedef struct VkWin32SurfaceCreateInfoKHR
|
||||
@ -383,6 +455,19 @@ typedef struct _GLFWlibraryWin32
|
||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
||||
} ntdll;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
PFN_WTInfoA WTInfoA;
|
||||
PFN_WTOpenA WTOpenA;
|
||||
PFN_WTQueueSizeSet WTQueueSizeSet;
|
||||
PFN_WTClose WTClose;
|
||||
PFN_WTPacket WTPacket;
|
||||
HCTX context;
|
||||
LOGCONTEXTA contextInfo;
|
||||
AXIS pressureInfo;
|
||||
AXIS orientationInfo[3];
|
||||
} wintab32;
|
||||
|
||||
} _GLFWlibraryWin32;
|
||||
|
||||
// Win32-specific per-monitor data
|
||||
|
@ -616,6 +616,48 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WT_PROXIMITY:
|
||||
{
|
||||
_glfwInputPenTabletProximity(lParam != 0);
|
||||
}
|
||||
|
||||
case WT_PACKET:
|
||||
if (_glfw.win32.wintab32.instance)
|
||||
{
|
||||
#define FIX2DOUBLE(x) ((double)(HIWORD(x))+((double)LOWORD(x)/65536))
|
||||
PACKET packet;
|
||||
LOGCONTEXTA contextInfo = _glfw.win32.wintab32.contextInfo;
|
||||
AXIS pressureInfo = _glfw.win32.wintab32.pressureInfo;
|
||||
AXIS altInfo = _glfw.win32.wintab32.orientationInfo[1];
|
||||
AXIS aziInfo = _glfw.win32.wintab32.orientationInfo[0];
|
||||
AXIS rollInfo = _glfw.win32.wintab32.orientationInfo[2];
|
||||
|
||||
while (_glfw.win32.wintab32.WTPacket(_glfw.win32.wintab32.context, (UINT)wParam, &packet)) {
|
||||
|
||||
double x, y, z, pressure, pitch=0, yaw=0, roll=0;
|
||||
|
||||
x = ((double)(packet.x - contextInfo.lcInOrgX) / contextInfo.lcInExtX) * contextInfo.lcSysExtX + contextInfo.lcSysOrgX;
|
||||
y = ((double)(packet.y - contextInfo.lcInOrgY) / contextInfo.lcInExtY) * contextInfo.lcSysExtY + contextInfo.lcSysOrgY;
|
||||
z = ((double)(packet.z - contextInfo.lcOutOrgZ) / contextInfo.lcOutExtZ);
|
||||
pressure = (double)(packet.normalPressure - pressureInfo.min) / (pressureInfo.max - pressureInfo.min);
|
||||
if (aziInfo.resolution && altInfo.resolution) {
|
||||
double alt = (double)(packet.orientation.altitude - altInfo.min) / (altInfo.max - altInfo.min);
|
||||
double azi = (double)(packet.orientation.azimuth - aziInfo.min) / (aziInfo.max - aziInfo.min);
|
||||
pitch = (0.5 - alt) * 180.0;
|
||||
yaw = azi * 360.0;
|
||||
}
|
||||
if (rollInfo.resolution) { // roll seems to be mostly unsupported so this is untested
|
||||
roll = (double)(packet.orientation.twist - rollInfo.min) / (rollInfo.max - rollInfo.min) * 360.0;
|
||||
}
|
||||
|
||||
if (packet.changed & 0x0020) { // CURSOR changed
|
||||
_glfwInputPenTabletCursor(packet.cursor);
|
||||
}
|
||||
|
||||
_glfwInputPenTabletData(x, y, z, pressure, pitch, yaw, roll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
|
@ -42,6 +42,10 @@
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
// Event index
|
||||
static unsigned int counter = 0;
|
||||
|
||||
@ -493,6 +497,24 @@ static void joystick_callback(int jid, int event)
|
||||
}
|
||||
}
|
||||
|
||||
void penTabletData_callback(double x, double y, double z, double pressure, double pitch, double yaw, double roll)
|
||||
{
|
||||
printf("%08x at %0.3f: pen: %f %f %f %f %f %f %f\n",
|
||||
counter++, glfwGetTime(), x, y, z, pressure, pitch, yaw, roll);
|
||||
}
|
||||
|
||||
void penTabletCursor_callback(unsigned int cursor)
|
||||
{
|
||||
printf("%08x at %0.3f: pen cursor: %d\n",
|
||||
counter++, glfwGetTime(), cursor);
|
||||
}
|
||||
|
||||
void penTabletProximity_callback(int proximity)
|
||||
{
|
||||
printf("%08x at %0.3f: pen proximity: %d\n",
|
||||
counter++, glfwGetTime(), proximity);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Slot* slots;
|
||||
@ -510,6 +532,9 @@ int main(int argc, char** argv)
|
||||
|
||||
glfwSetMonitorCallback(monitor_callback);
|
||||
glfwSetJoystickCallback(joystick_callback);
|
||||
glfwSetPenTabletDataCallback(penTabletData_callback);
|
||||
glfwSetPenTabletCursorCallback(penTabletCursor_callback);
|
||||
glfwSetPenTabletProximityCallback(penTabletProximity_callback);
|
||||
|
||||
while ((ch = getopt(argc, argv, "hfn:")) != -1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user