diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-09-18 06:38:38 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-09-18 06:38:38 +0400 |
commit | a393a9c6f05b66692fbbb7ae2a3f101744e550f0 (patch) | |
tree | 53db86557caf05aff57456acf0b88ad759d653da /intern | |
parent | b75d2c56c86ec030dbdf1031361952cccfb89878 (diff) |
same as r23322 in 2.4x
--- 2.4x log
use functions to detect stylus and eraser from the wine project, supposed to work with non-wacom tablets too (searches for wizardpen & acecad as well as 'stylus').
2.4x did an exact check on the name, 2.5 does a case insensitive search on the type.
This does a case insensitive check on both the name and type.
close the devices on exit too.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 128 |
1 files changed, 114 insertions, 14 deletions
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 708256f75f5..ab46c050fa3 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -414,6 +414,100 @@ static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) { return 0 ; } +/* These C functions are copied from Wine 1.1.13's wintab.c */ +#define BOOL int +#define TRUE 1 +#define FALSE 0 + +static bool match_token(const char *haystack, const char *needle) +{ + const char *p, *q; + for (p = haystack; *p; ) + { + while (*p && isspace(*p)) + p++; + if (! *p) + break; + + for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++) + p++; + if (! *q && (isspace(*p) || !*p)) + return TRUE; + + while (*p && ! isspace(*p)) + p++; + } + return FALSE; +} + +/* Determining if an X device is a Tablet style device is an imperfect science. +** We rely on common conventions around device names as well as the type reported +** by Wacom tablets. This code will likely need to be expanded for alternate tablet types +** +** Wintab refers to any device that interacts with the tablet as a cursor, +** (stylus, eraser, tablet mouse, airbrush, etc) +** this is not to be confused with wacom x11 configuration "cursor" device. +** Wacoms x11 config "cursor" refers to its device slot (which we mirror with +** our gSysCursors) for puck like devices (tablet mice essentially). +*/ + +static BOOL is_tablet_cursor(const char *name, const char *type) +{ + int i; + static const char *tablet_cursor_whitelist[] = { + "wacom", + "wizardpen", + "acecad", + "tablet", + "cursor", + "stylus", + "eraser", + "pad", + NULL + }; + + for (i=0; tablet_cursor_whitelist[i] != NULL; i++) { + if (name && match_token(name, tablet_cursor_whitelist[i])) + return TRUE; + if (type && match_token(type, tablet_cursor_whitelist[i])) + return TRUE; + } + return FALSE; +} + +static BOOL is_stylus(const char *name, const char *type) +{ + int i; + static const char* tablet_stylus_whitelist[] = { + "stylus", + "wizardpen", + "acecad", + NULL + }; + + for (i=0; tablet_stylus_whitelist[i] != NULL; i++) { + if (name && match_token(name, tablet_stylus_whitelist[i])) + return TRUE; + if (type && match_token(type, tablet_stylus_whitelist[i])) + return TRUE; + } + + return FALSE; +} + +static BOOL is_eraser(const char *name, const char *type) +{ + if (name && match_token(name, "eraser")) + return TRUE; + if (type && match_token(type, "eraser")) + return TRUE; + return FALSE; +} +#undef BOOL +#undef TRUE +#undef FALSE +/* end code copied from wine */ + void GHOST_WindowX11::initXInputDevices() { static XErrorHandler old_handler = (XErrorHandler) 0 ; @@ -423,28 +517,21 @@ void GHOST_WindowX11::initXInputDevices() if(version->present) { int device_count; XDeviceInfo* device_info = XListInputDevices(m_display, &device_count); - m_xtablet.StylusDevice = 0; - m_xtablet.EraserDevice = 0; + m_xtablet.StylusDevice = NULL; + m_xtablet.EraserDevice = NULL; m_xtablet.CommonData.Active= GHOST_kTabletModeNone; /* Install our error handler to override Xlib's termination behavior */ old_handler = XSetErrorHandler(ApplicationErrorHandler) ; for(int i=0; i<device_count; ++i) { - std::string type = ""; + char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL; - if(device_info[i].type) { - const char *orig = XGetAtomName(m_display, device_info[i].type); - // Make a copy so we can convert to lower case - if(orig) { - type = orig; - XFree((void*)orig); - std::transform(type.begin(), type.end(), type.begin(), ::tolower); - } - } +// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i); - if(type.find("stylus") != std::string::npos) { + if(m_xtablet.StylusDevice==NULL && is_stylus(device_info[i].name, device_type)) { +// printf("\tfound stylus\n"); m_xtablet.StylusID= device_info[i].id; m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID); @@ -453,6 +540,7 @@ void GHOST_WindowX11::initXInputDevices() XAnyClassPtr ici = device_info[i].inputclassinfo; for(int j=0; j<m_xtablet.StylusDevice->num_classes; ++j) { if(ici->c_class==ValuatorClass) { +// printf("\t\tfound ValuatorClass\n"); XValuatorInfo* xvi = (XValuatorInfo*)ici; m_xtablet.PressureLevels = xvi->axes[2].max_value; @@ -469,11 +557,16 @@ void GHOST_WindowX11::initXInputDevices() m_xtablet.StylusID= 0; } } - if(type.find("eraser") != std::string::npos) { + else if(m_xtablet.EraserDevice==NULL && is_eraser(device_info[i].name, device_type)) { +// printf("\tfound eraser\n"); m_xtablet.EraserID= device_info[i].id; m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID); if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID= 0; } + + if(device_type) { + XFree((void*)device_type); + } } /* Restore handler */ @@ -1125,6 +1218,13 @@ GHOST_WindowX11:: XFreeCursor(m_display, m_custom_cursor); } + /* close tablet devices */ + if(m_xtablet.StylusDevice) + XCloseDevice(m_display, m_xtablet.StylusDevice); + + if(m_xtablet.EraserDevice) + XCloseDevice(m_display, m_xtablet.EraserDevice); + if (m_context) { if (m_context == s_firstContext) { s_firstContext = NULL; |