Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-04-14 19:01:14 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-04-14 19:58:37 +0300
commite90d8422d0ed38743390f2184fde27550d7b48a7 (patch)
tree9bc56f3545c46a521d8c923b974417214f2b2c21
parent65f674b570fc5eb1b5011bf8ae5cc3e031026665 (diff)
Revert "Windows: support high resolution tablet pen events for Wintab"
This reverts commit 1a3928f33c and 1a3928f3. This is not working stable with some Wintab implementations, so reverting for now. This leaves only the Windows Ink changes for 2.83.
-rw-r--r--intern/ghost/intern/GHOST_System.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp148
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h10
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp455
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h118
5 files changed, 203 insertions, 530 deletions
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index c404fe21e41..eaaa2ff6ee6 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -238,7 +238,7 @@ class GHOST_System : public GHOST_ISystem {
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
* \param api Enum indicating which API to use.
*/
- virtual void setTabletAPI(GHOST_TTabletAPI api);
+ void setTabletAPI(GHOST_TTabletAPI api);
GHOST_TTabletAPI getTabletAPI(void);
#ifdef WITH_INPUT_NDOF
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index b91792938d5..fdd022e44ac 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -938,100 +938,15 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
window->updateMouseCapture(MouseReleased);
}
- /* Check for active Wintab mouse emulation in addition to a tablet in range because a proximity
- * leave event might have fired before the Windows mouse up event, thus there are still tablet
- * events to grab. The described behavior was observed in a Wacom Bamboo CTE-450.
- */
- if (window->m_tabletInRange || window->wintabSysButPressed()) {
- if (window->useTabletAPI(GHOST_kTabletWintab) && processWintabEvents(type, window)) {
- // Wintab processing only handles in-contact events.
- return NULL;
- }
- else if (window->useTabletAPI(GHOST_kTabletNative)) {
+ if (window->m_tabletInRange) {
+ if (window->useTabletAPI(GHOST_kTabletNative)) {
// Win32 Pointer processing handles input while in-range and in-contact events.
return NULL;
}
-
- // If using Wintab and this was a button down event but no button event was queued while
- // processing Wintab packets, fall through to create a button event.
}
return new GHOST_EventButton(
- system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE);
-}
-
-GHOST_TSuccess GHOST_SystemWin32::processWintabEvents(GHOST_TEventType type,
- GHOST_WindowWin32 *window)
-{
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
-
- /* Only process Wintab packets if we can correlate them to a Window's mouse button event. When a
- * button event associated to a mouse button by Wintab occurs outside of WM_*BUTTON events,
- * there's no way to tell if other simultaneously pressed non-mouse mapped buttons are associated
- * to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and thus it is not
- * possible to determine if a mouse click event should occur.
- */
- if (!window->getMousePressed() && !window->wintabSysButPressed()) {
- return GHOST_kFailure;
- }
-
- std::vector<GHOST_WintabInfoWin32> wintabInfo;
- if (!window->getWintabInfo(wintabInfo)) {
- return GHOST_kFailure;
- }
-
- auto wtiIter = wintabInfo.begin();
-
- /* We only process events that correlate to a mouse button events, so there may exist Wintab
- * button down events that were instead mapped to e.g. scroll still in the queue. We need to
- * skip those and find the last button down mapped to mouse buttons.
- */
- if (!window->wintabSysButPressed()) {
- for (auto it = wtiIter; it != wintabInfo.end(); it++) {
- if (it->type == GHOST_kEventButtonDown) {
- wtiIter = it;
- }
- }
- }
-
- for (; wtiIter != wintabInfo.end(); wtiIter++) {
- auto info = *wtiIter;
-
- switch (info.type) {
- case GHOST_kEventButtonDown: {
- /* While changing windows with a tablet, Window's mouse button events normally occur before
- * tablet proximity events, so a button up event can't be differentiated as occurring from
- * a Wintab tablet or a normal mouse and a Ghost button event will always be generated.
- *
- * If we were called during a button down event create a ghost button down event, otherwise
- * don't duplicate the prior button down as it interrupts drawing immediately after
- * changing a window.
- */
- if (type == GHOST_kEventButtonDown) {
- // Move cursor to point of contact because GHOST_EventButton does not include position.
- system->pushEvent(new GHOST_EventCursor(
- info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
- system->pushEvent(
- new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
- }
- window->updateWintabSysBut(MousePressed);
- break;
- }
- case GHOST_kEventCursorMove:
- system->pushEvent(new GHOST_EventCursor(
- info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
- break;
- case GHOST_kEventButtonUp:
- system->pushEvent(
- new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
- window->updateWintabSysBut(MouseReleased);
- break;
- default:
- break;
- }
- }
-
- return GHOST_kSuccess;
+ system->getMilliSeconds(), type, window, mask, window->getTabletData());
}
void GHOST_SystemWin32::processPointerEvents(
@@ -1119,19 +1034,13 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- if (window->m_tabletInRange || window->wintabSysButPressed()) {
- if (window->useTabletAPI(GHOST_kTabletWintab) &&
- processWintabEvents(GHOST_kEventCursorMove, window)) {
- return NULL;
- }
- else if (window->useTabletAPI(GHOST_kTabletNative)) {
+ if (window->m_tabletInRange) {
+ if (window->useTabletAPI(GHOST_kTabletNative)) {
// Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
// input aren't normally generated when using WM_POINTER events, but manually moving the
// system cursor as we do in WM_POINTER handling does.
return NULL;
}
-
- // If using Wintab but no button event is currently active, fall through to default handling
}
system->getCursorPosition(x_screen, y_screen);
@@ -1164,7 +1073,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen + x_accum,
y_screen + y_accum,
- GHOST_TABLET_DATA_NONE);
+ window->getTabletData());
}
}
else {
@@ -1173,7 +1082,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen,
y_screen,
- GHOST_TABLET_DATA_NONE);
+ window->getTabletData());
}
return NULL;
}
@@ -1284,6 +1193,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
+ window->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
@@ -1311,19 +1221,6 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
}
-void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
-{
- GHOST_System::setTabletAPI(api);
-
- GHOST_WindowManager *wm = getWindowManager();
- GHOST_WindowWin32 *activeWindow = (GHOST_WindowWin32 *)wm->getActiveWindow();
-
- for (GHOST_IWindow *win : wm->getWindows()) {
- GHOST_WindowWin32 *windowsWindow = (GHOST_WindowWin32 *)win;
- windowsWindow->updateWintab(windowsWindow == activeWindow);
- }
-}
-
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
{
minmax->ptMinTrackSize.x = 320;
@@ -1559,17 +1456,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
////////////////////////////////////////////////////////////////////////
- // Wintab events, processed
+ // Tablet events, processed
////////////////////////////////////////////////////////////////////////
- case WT_INFOCHANGE: {
- window->processWintabInfoChangeEvent(lParam);
+ case WT_PACKET:
+ window->processWin32TabletEvent(wParam, lParam);
break;
- }
- case WT_PROXIMITY: {
- bool inRange = LOWORD(lParam);
- window->processWintabProximityEvent(inRange);
+ case WT_CSRCHANGE:
+ case WT_PROXIMITY:
+ window->processWin32TabletInitEvent();
break;
- }
////////////////////////////////////////////////////////////////////////
// Pointer events, processed
////////////////////////////////////////////////////////////////////////
@@ -1708,9 +1603,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
if (LOWORD(wParam) == WA_INACTIVE)
window->lostMouseCapture();
-
- window->updateWintab(LOWORD(wParam) != WA_INACTIVE);
-
+ window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
@@ -1768,11 +1661,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
else {
event = processWindowEvent(GHOST_kEventWindowSize, window);
}
-
- if (msg == WM_SIZE && wParam == SIZE_MINIMIZED) {
- window->updateWintab(false);
- }
-
break;
case WM_CAPTURECHANGED:
window->lostMouseCapture();
@@ -1823,12 +1711,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
- case WM_DISPLAYCHANGE:
- for (GHOST_IWindow *iter_win : system->getWindowManager()->getWindows()) {
- GHOST_WindowWin32 *iter_win32win = (GHOST_WindowWin32 *)iter_win;
- iter_win32win->processWintabDisplayChangeEvent();
- }
- break;
////////////////////////////////////////////////////////////////////////
// Window events, ignored
////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 05221cbdc40..c6d810d2a38 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -266,16 +266,6 @@ class GHOST_SystemWin32 : public GHOST_System {
int mouseY,
void *data);
- /***************************************************************************************
- ** Modify tablet API
- ***************************************************************************************/
-
- /**
- * Set which tablet API to use.
- * \param api Enum indicating which API to use.
- */
- void setTabletAPI(GHOST_TTabletAPI api) override;
-
protected:
/**
* Initializes the system.
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 1ca0dd47cbe..b0ba7b6befb 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -72,7 +72,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
bool is_debug,
bool dialog)
: GHOST_Window(width, height, state, wantStereoVisual, false),
- m_tabletInRange(false),
m_inLiveResize(false),
m_system(system),
m_hDC(0),
@@ -81,15 +80,19 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_nPressedButtons(0),
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
- m_wintab(),
m_normal_state(GHOST_kWindowStateNormal),
m_user32(NULL),
m_fpGetPointerInfoHistory(NULL),
m_fpGetPointerPenInfoHistory(NULL),
m_fpGetPointerTouchInfoHistory(NULL),
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL),
- m_debug_context(is_debug)
+ m_debug_context(is_debug),
+ m_tabletInRange(false)
{
+ // Initialize tablet variables
+ memset(&m_wintab, 0, sizeof(m_wintab));
+ m_tabletData = GHOST_TABLET_DATA_NONE;
+
// Create window
if (state != GHOST_kWindowStateFullScreen) {
RECT rect;
@@ -294,25 +297,66 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_user32, "GetPointerTouchInfoHistory");
}
- if ((m_wintab.handle = ::LoadLibrary("Wintab32.dll")) &&
- (m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA")) &&
- (m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA")) &&
- (m_wintab.get = (GHOST_WIN32_WTGet)::GetProcAddress(m_wintab.handle, "WTGetA")) &&
- (m_wintab.set = (GHOST_WIN32_WTSet)::GetProcAddress(m_wintab.handle, "WTSetA")) &&
- (m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose")) &&
- (m_wintab.packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(m_wintab.handle,
- "WTPacketsGet")) &&
- (m_wintab.queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(m_wintab.handle,
- "WTQueueSizeGet")) &&
- (m_wintab.queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(m_wintab.handle,
- "WTQueueSizeSet")) &&
- (m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable")) &&
- (m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap"))) {
- initializeWintab();
- // Determine which tablet API to use and enable it.
- updateWintab(true);
- }
+ // Initialize Wintab
+ m_wintab.handle = ::LoadLibrary("Wintab32.dll");
+ if (m_wintab.handle) {
+ // Get API functions
+ m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA");
+ m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA");
+ m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose");
+ m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket");
+ m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable");
+ m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap");
+
+ // Let's see if we can initialize tablet here.
+ // Check if WinTab available by getting system context info.
+ LOGCONTEXT lc = {0};
+ lc.lcOptions |= CXO_SYSTEM;
+ if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
+ // Now init the tablet
+ /* The maximum tablet size, pressure and orientation (tilt) */
+ AXIS TabletX, TabletY, Pressure, Orientation[3];
+
+ // Open a Wintab context
+
+ // Open the context
+ lc.lcPktData = PACKETDATA;
+ lc.lcPktMode = PACKETMODE;
+ lc.lcOptions |= CXO_MESSAGES;
+ lc.lcMoveMask = PACKETDATA;
+
+ /* Set the entire tablet as active */
+ m_wintab.info(WTI_DEVICES, DVC_X, &TabletX);
+ m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY);
+
+ /* get the max pressure, to divide into a float */
+ BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
+ if (pressureSupport)
+ m_wintab.maxPressure = Pressure.axMax;
+ else
+ m_wintab.maxPressure = 0;
+
+ /* get the max tilt axes, to divide into floats */
+ BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
+ if (tiltSupport) {
+ /* does the tablet support azimuth ([0]) and altitude ([1]) */
+ if (Orientation[0].axResolution && Orientation[1].axResolution) {
+ /* all this assumes the minimum is 0 */
+ m_wintab.maxAzimuth = Orientation[0].axMax;
+ m_wintab.maxAltitude = Orientation[1].axMax;
+ }
+ else { /* no so dont do tilt stuff */
+ m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
+ }
+ }
+ // The Wintab spec says we must open the context disabled if we are using cursor masks.
+ m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE);
+ if (m_wintab.enable && m_wintab.tablet) {
+ m_wintab.enable(m_wintab.tablet, TRUE);
+ }
+ }
+ }
CoCreateInstance(
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
@@ -326,8 +370,8 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
if (m_wintab.handle) {
- if (m_wintab.close && m_wintab.context) {
- m_wintab.close(m_wintab.context);
+ if (m_wintab.close && m_wintab.tablet) {
+ m_wintab.close(m_wintab.tablet);
}
FreeLibrary(m_wintab.handle);
@@ -776,27 +820,6 @@ bool GHOST_WindowWin32::getMousePressed() const
return m_nPressedButtons;
}
-bool GHOST_WindowWin32::wintabSysButPressed() const
-{
- return m_wintab.numSysButtons;
-}
-
-void GHOST_WindowWin32::updateWintabSysBut(GHOST_MouseCaptureEventWin32 event)
-{
- switch (event) {
- case MousePressed:
- m_wintab.numSysButtons++;
- break;
- case MouseReleased:
- if (m_wintab.numSysButtons)
- m_wintab.numSysButtons--;
- break;
- case OperatorGrab:
- case OperatorUngrab:
- break;
- }
-}
-
HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
{
// Convert GHOST cursor to Windows OEM cursor
@@ -1000,103 +1023,6 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
return (getStandardCursor(cursorShape)) ? GHOST_kSuccess : GHOST_kFailure;
}
-void GHOST_WindowWin32::updateWintab(bool active)
-{
- if (m_wintab.enable && m_wintab.overlap && m_wintab.context) {
- bool useWintab = useTabletAPI(GHOST_kTabletWintab);
- bool enable = active && useWintab;
-
- // Disabling context while the Window is not minimized can cause issues on receiving Wintab
- // input while changing a window for some drivers, so only disable if either Wintab had been
- // disabled or the window is minimized.
- m_wintab.enable(m_wintab.context, useWintab && !::IsIconic(m_hWnd));
- m_wintab.overlap(m_wintab.context, enable);
-
- if (!enable) {
- // WT_PROXIMITY event doesn't occur unless tablet's cursor leaves the proximity while the
- // window is active.
- m_tabletInRange = false;
- m_wintab.numSysButtons = 0;
- m_wintab.sysButtonsPressed = 0;
- }
- }
-}
-
-void GHOST_WindowWin32::initializeWintab()
-{
- // return if wintab library handle doesn't exist or wintab is already initialized
- if (!m_wintab.handle || m_wintab.context) {
- return;
- }
-
- // Let's see if we can initialize tablet here.
- // Check if WinTab available by getting system context info.
- LOGCONTEXT lc = {0};
- if (m_wintab.open && m_wintab.info && m_wintab.queueSizeGet && m_wintab.queueSizeSet &&
- m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
- // Now init the tablet
- /* The pressure and orientation (tilt) */
- AXIS Pressure, Orientation[3];
-
- // Open a Wintab context
-
- // Open the context
- lc.lcPktData = PACKETDATA;
- lc.lcPktMode = PACKETMODE;
- lc.lcMoveMask = PACKETDATA;
- // Wacom maps y origin to the tablet's bottom
- // Invert to match Windows y origin mapping to the screen top
- lc.lcOutExtY = -lc.lcOutExtY;
-
- m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
-
- /* get the max pressure, to divide into a float */
- BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
- m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
-
- /* get the max tilt axes, to divide into floats */
- BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
- /* does the tablet support azimuth ([0]) and altitude ([1]) */
- if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
- /* all this assumes the minimum is 0 */
- m_wintab.maxAzimuth = Orientation[0].axMax;
- m_wintab.maxAltitude = Orientation[1].axMax;
- }
- else { /* no so dont do tilt stuff */
- m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
- }
-
- // The Wintab spec says we must open the context disabled if we are using cursor masks.
- m_wintab.context = m_wintab.open(m_hWnd, &lc, FALSE);
-
- // Wintab provides no way to determine the maximum queue size aside from checking if attempts
- // to change the queue size are successful.
- const int maxQueue = 500;
- int queueSize = m_wintab.queueSizeGet(m_wintab.context);
-
- while (queueSize < maxQueue) {
- int testSize = min(queueSize + 16, maxQueue);
- if (m_wintab.queueSizeSet(m_wintab.context, testSize)) {
- queueSize = testSize;
- }
- else {
- /* From Windows Wintab Documentation for WTQueueSizeSet:
- * "If the return value is zero, the context has no queue because the function deletes the
- * original queue before attempting to create a new one. The application must continue
- * calling the function with a smaller queue size until the function returns a non - zero
- * value."
- *
- * In our case we start with a known valid queue size and in the event of failure roll
- * back to the last valid queue size.
- */
- m_wintab.queueSizeSet(m_wintab.context, queueSize);
- break;
- }
- }
- m_wintab.pkts.resize(queueSize);
- }
-}
-
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
{
@@ -1179,20 +1105,28 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
return GHOST_kSuccess;
}
-void GHOST_WindowWin32::processWintabDisplayChangeEvent()
+void GHOST_WindowWin32::setTabletData(GHOST_TabletData *pTabletData)
{
- LOGCONTEXT lc_sys = {0}, lc_curr = {0};
-
- if (m_wintab.info && m_wintab.get && m_wintab.set && m_wintab.info(WTI_DEFSYSCTX, 0, &lc_sys)) {
+ if (pTabletData) {
+ m_tabletData = *pTabletData;
+ }
+ else {
+ m_tabletData = GHOST_TABLET_DATA_NONE;
+ }
+}
- m_wintab.get(m_wintab.context, &lc_curr);
+void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
+{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
+ }
- lc_curr.lcOutOrgX = lc_sys.lcOutOrgX;
- lc_curr.lcOutOrgY = lc_sys.lcOutOrgY;
- lc_curr.lcOutExtX = lc_sys.lcOutExtX;
- lc_curr.lcOutExtY = -lc_sys.lcOutExtY;
+ if (m_wintab.enable && m_wintab.tablet) {
+ m_wintab.enable(m_wintab.tablet, state);
- m_wintab.set(m_wintab.context, &lc_curr);
+ if (m_wintab.overlap && state) {
+ m_wintab.overlap(m_wintab.tablet, TRUE);
+ }
}
}
@@ -1202,7 +1136,7 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
return true;
}
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
- if (m_wintab.numDevices)
+ if (m_wintab.tablet)
return api == GHOST_kTabletWintab;
else
return api == GHOST_kTabletNative;
@@ -1212,180 +1146,115 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
}
}
-void GHOST_WindowWin32::processWintabProximityEvent(bool inRange)
+void GHOST_WindowWin32::processWin32TabletInitEvent()
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
// Let's see if we can initialize tablet here
- if (m_wintab.info && m_wintab.context) {
+ if (m_wintab.info && m_wintab.tablet) {
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
- m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
+ if (pressureSupport)
+ m_wintab.maxPressure = Pressure.axMax;
+ else
+ m_wintab.maxPressure = 0;
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
- /* does the tablet support azimuth ([0]) and altitude ([1]) */
- if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
- m_wintab.maxAzimuth = Orientation[0].axMax;
- m_wintab.maxAltitude = Orientation[1].axMax;
- }
- else { /* no so dont do tilt stuff */
- m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
+ if (tiltSupport) {
+ /* does the tablet support azimuth ([0]) and altitude ([1]) */
+ if (Orientation[0].axResolution && Orientation[1].axResolution) {
+ m_wintab.maxAzimuth = Orientation[0].axMax;
+ m_wintab.maxAltitude = Orientation[1].axMax;
+ }
+ else { /* no so dont do tilt stuff */
+ m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
+ }
}
}
- m_tabletInRange = inRange;
-}
-
-void GHOST_WindowWin32::processWintabInfoChangeEvent(LPARAM lParam)
-{
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
-
- // Update number of connected Wintab digitizers
- if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
- m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
- updateWintab((GHOST_WindowWin32 *)system->getWindowManager()->getActiveWindow() == this);
- }
-}
-
-GHOST_TSuccess GHOST_WindowWin32::wintabMouseToGhost(UINT cursor,
- DWORD physicalButton,
- GHOST_TButtonMask &ghostButton)
-{
- const DWORD numButtons = 32;
- BYTE logicalButtons[numButtons] = {0};
- BYTE systemButtons[numButtons] = {0};
-
- m_wintab.info(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons);
- m_wintab.info(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons);
-
- if (physicalButton >= numButtons) {
- return GHOST_kFailure;
- }
- BYTE lb = logicalButtons[physicalButton];
-
- if (lb >= numButtons) {
- return GHOST_kFailure;
- }
- switch (systemButtons[lb]) {
- case SBN_LCLICK:
- ghostButton = GHOST_kButtonMaskLeft;
- return GHOST_kSuccess;
- case SBN_RCLICK:
- ghostButton = GHOST_kButtonMaskRight;
- return GHOST_kSuccess;
- case SBN_MCLICK:
- ghostButton = GHOST_kButtonMaskMiddle;
- return GHOST_kSuccess;
- default:
- return GHOST_kFailure;
- }
+ m_tabletData.Active = GHOST_kTabletModeNone;
}
-GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
+void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
- return GHOST_kFailure;
- }
-
- if (!(m_wintab.packetsGet && m_wintab.context)) {
- return GHOST_kFailure;
+ return;
}
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
-
- const int numPackets = m_wintab.packetsGet(
- m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
- outWintabInfo.resize(numPackets);
-
- for (int i = 0; i < numPackets; i++) {
- PACKET pkt = m_wintab.pkts[i];
- GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE;
- switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
- case 0:
- tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
- break;
- case 1:
- tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
- break;
- case 2:
- tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
- break;
- }
+ if (m_wintab.packet && m_wintab.tablet) {
+ PACKET pkt;
+ if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
+ switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
+ case 0:
+ m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
+ break;
+ case 1:
+ m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
+ break;
+ case 2:
+ m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
+ break;
+ }
- if (m_wintab.maxPressure > 0) {
- tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
- }
+ if (m_wintab.maxPressure > 0) {
+ m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
+ }
+ else {
+ m_tabletData.Pressure = 1.0f;
+ }
- if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
- ORIENTATION ort = pkt.pkOrientation;
- float vecLen;
- float altRad, azmRad; /* in radians */
-
- /*
- * from the wintab spec:
- * orAzimuth Specifies the clockwise rotation of the
- * cursor about the z axis through a full circular range.
- *
- * orAltitude Specifies the angle with the x-y plane
- * through a signed, semicircular range. Positive values
- * specify an angle upward toward the positive z axis;
- * negative values specify an angle downward toward the negative z axis.
- *
- * wintab.h defines .orAltitude as a UINT but documents .orAltitude
- * as positive for upward angles and negative for downward angles.
- * WACOM uses negative altitude values to show that the pen is inverted;
- * therefore we cast .orAltitude as an (int) and then use the absolute value.
- */
-
- /* convert raw fixed point data to radians */
- altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
- azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
-
- /* find length of the stylus' projected vector on the XY plane */
- vecLen = cos(altRad);
-
- /* from there calculate X and Y components based on azimuth */
- tabletData.Xtilt = sin(azmRad) * vecLen;
- tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
- }
+ if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
+ ORIENTATION ort = pkt.pkOrientation;
+ float vecLen;
+ float altRad, azmRad; /* in radians */
- outWintabInfo[i].x = pkt.pkX;
- outWintabInfo[i].y = pkt.pkY;
+ /*
+ * from the wintab spec:
+ * orAzimuth Specifies the clockwise rotation of the
+ * cursor about the z axis through a full circular range.
+ *
+ * orAltitude Specifies the angle with the x-y plane
+ * through a signed, semicircular range. Positive values
+ * specify an angle upward toward the positive z axis;
+ * negative values specify an angle downward toward the negative z axis.
+ *
+ * wintab.h defines .orAltitude as a UINT but documents .orAltitude
+ * as positive for upward angles and negative for downward angles.
+ * WACOM uses negative altitude values to show that the pen is inverted;
+ * therefore we cast .orAltitude as an (int) and then use the absolute value.
+ */
- // Some Wintab libraries don't handle relative button input correctly, so we track button
- // presses manually.
- DWORD buttonsChanged = m_wintab.sysButtonsPressed ^ pkt.pkButtons;
+ /* convert raw fixed point data to radians */
+ altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
+ azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
- // Find the index for the changed button from the button map.
- DWORD physicalButton = 0;
- for (DWORD diff = (unsigned)buttonsChanged >> 1; diff > 0; diff = (unsigned)diff >> 1) {
- physicalButton++;
- }
+ /* find length of the stylus' projected vector on the XY plane */
+ vecLen = cos(altRad);
- if (buttonsChanged &&
- wintabMouseToGhost(pkt.pkCursor, physicalButton, outWintabInfo[i].button)) {
- if (buttonsChanged & pkt.pkButtons) {
- outWintabInfo[i].type = GHOST_kEventButtonDown;
+ /* from there calculate X and Y components based on azimuth */
+ m_tabletData.Xtilt = sin(azmRad) * vecLen;
+ m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
}
else {
- outWintabInfo[i].type = GHOST_kEventButtonUp;
+ m_tabletData.Xtilt = 0.0f;
+ m_tabletData.Ytilt = 0.0f;
}
}
- else {
- outWintabInfo[i].type = GHOST_kEventCursorMove;
- }
-
- m_wintab.sysButtonsPressed = pkt.pkButtons;
+ }
+}
- // Wintab does not support performance counters, so use low frequency counter instead
- outWintabInfo[i].time = system->tickCountToMillis(pkt.pkTime);
- outWintabInfo[i].tabletData = tabletData;
+void GHOST_WindowWin32::bringTabletContextToFront()
+{
+ if (!useTabletAPI(GHOST_kTabletWintab)) {
+ return;
}
- return GHOST_kSuccess;
+ if (m_wintab.overlap && m_wintab.tablet) {
+ m_wintab.overlap(m_wintab.tablet, TRUE);
+ }
}
GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index d4427f67e9b..2951901ceb4 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -36,9 +36,8 @@
#endif
#include <wintab.h>
-#define PACKETDATA \
- (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
-#define PACKETMODE 0
+#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
+#define PACKETMODE PK_BUTTONS
#include <pktdef.h>
class GHOST_SystemWin32;
@@ -46,13 +45,9 @@ class GHOST_DropTargetWin32;
// typedefs for WinTab functions to allow dynamic loading
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
-typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
-typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
-typedef BOOL(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
-typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
-typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
+typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
@@ -233,14 +228,7 @@ struct GHOST_PointerInfoWin32 {
GHOST_TButtonMask buttonMask;
POINT pixelLocation;
GHOST_TUns64 time;
- GHOST_TabletData tabletData;
-};
-struct GHOST_WintabInfoWin32 {
- GHOST_TInt32 x, y;
- GHOST_TEventType type;
- GHOST_TButtonMask button;
- GHOST_TUns64 time;
GHOST_TabletData tabletData;
};
@@ -434,16 +422,12 @@ class GHOST_WindowWin32 : public GHOST_Window {
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
- /**
- * Handle setup and switch between Wintab and Pointer APIs
- * \param active Whether the window is or will be in an active state
- */
- void updateWintab(bool active);
+ const GHOST_TabletData &GetTabletData()
+ {
+ return m_tabletData;
+ }
- /**
- * Query whether given tablet API should be used.
- * \param api Tablet API to test.
- */
+ void setTabletData(GHOST_TabletData *tabletData);
bool useTabletAPI(GHOST_TTabletAPI api) const;
/**
@@ -456,28 +440,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
WPARAM wParam,
LPARAM lParam);
- /**
- * Handle Wintab coordinate changes when DisplayChange events occur.
- */
- void processWintabDisplayChangeEvent();
-
- /**
- * Set tablet details when a cursor enters range
- */
- void processWintabProximityEvent(bool inRange);
-
- /**
- * Handle Wintab info changes such as change in number of connected tablets.
- * \param lParam LPARAM of the event
- */
- void processWintabInfoChangeEvent(LPARAM lParam);
-
- /**
- * Translate Wintab packets into GHOST_WintabInfoWin32 structs.
- * \param outWintabInfo Storage to return resulting GHOST_WintabInfoWin32 structs
- * \return Success if able to read packets, even if there are none
- */
- GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
+ void processWin32TabletActivateEvent(WORD state);
+ void processWin32TabletInitEvent();
+ void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
+ void bringTabletContextToFront();
GHOST_TSuccess beginFullScreen() const
{
@@ -497,19 +463,6 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
bool getMousePressed() const;
- /**
- * Get if there are currently pressed Wintab buttons associated to a Windows mouse button press
- * \return True if there are currently any pressed Wintab buttons associated to a Windows
- * mouse button press
- */
- bool wintabSysButPressed() const;
-
- /**
- * Register a Wintab button has been associated to a Windows mouse button press
- * \param event Whether the button was pressed or released
- */
- void updateWintabSysBut(GHOST_MouseCaptureEventWin32 event);
-
/** Whether a tablet stylus is being tracked */
bool m_tabletInRange;
@@ -593,49 +546,28 @@ class GHOST_WindowWin32 : public GHOST_Window {
static const wchar_t *s_windowClassName;
static const int s_maxTitleLength;
+ /** Tablet data for GHOST */
+ GHOST_TabletData m_tabletData;
+
/* Wintab API */
struct {
/** WinTab dll handle */
- HMODULE handle = NULL;
+ HMODULE handle;
/** API functions */
- GHOST_WIN32_WTInfo info = NULL;
- GHOST_WIN32_WTGet get = NULL;
- GHOST_WIN32_WTSet set = NULL;
- GHOST_WIN32_WTOpen open = NULL;
- GHOST_WIN32_WTClose close = NULL;
- GHOST_WIN32_WTPacketsGet packetsGet = NULL;
- GHOST_WIN32_WTQueueSizeGet queueSizeGet = NULL;
- GHOST_WIN32_WTQueueSizeSet queueSizeSet = NULL;
- GHOST_WIN32_WTEnable enable = NULL;
- GHOST_WIN32_WTOverlap overlap = NULL;
+ GHOST_WIN32_WTInfo info;
+ GHOST_WIN32_WTOpen open;
+ GHOST_WIN32_WTClose close;
+ GHOST_WIN32_WTPacket packet;
+ GHOST_WIN32_WTEnable enable;
+ GHOST_WIN32_WTOverlap overlap;
/** Stores the Tablet context if detected Tablet features using WinTab.dll */
- HCTX context = NULL;
- /** Number of connected Wintab digitizers */
- UINT numDevices = 0;
- /** Number of cursors currently in contact mapped to system buttons */
- GHOST_TUns8 numSysButtons = 0;
- /** Cursors currently in contact mapped to system buttons */
- DWORD sysButtonsPressed = 0;
- LONG maxPressure = 0;
- LONG maxAzimuth = 0, maxAltitude = 0;
- /* Queue size doesn't change once set, so reuse the same buffer */
- std::vector<PACKET> pkts;
+ HCTX tablet;
+ LONG maxPressure;
+ LONG maxAzimuth, maxAltitude;
} m_wintab;
- /**
- * Wintab setup
- */
- void initializeWintab();
-
- /**
- * Convert Wintab system mapped (mouse) buttons into Ghost button mask
- */
- GHOST_TSuccess wintabMouseToGhost(UINT cursor,
- DWORD physicalButton,
- GHOST_TButtonMask &buttonMask);
-
GHOST_TWindowState m_normal_state;
/** user32 dll handle*/