241 static PtrWTGet ptrWTGet = 0; |
241 static PtrWTGet ptrWTGet = 0; |
242 |
242 |
243 static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue. |
243 static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue. |
244 HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle) |
244 HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle) |
245 bool qt_tablet_tilt_support; |
245 bool qt_tablet_tilt_support; |
246 static void tabletInit(UINT wActiveCsr, HCTX hTab); |
246 |
|
247 #ifndef QT_NO_TABLETEVENT |
|
248 static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab); |
|
249 static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor); |
247 static void initWinTabFunctions(); // resolve the WINTAB api functions |
250 static void initWinTabFunctions(); // resolve the WINTAB api functions |
|
251 #endif // QT_NO_TABLETEVENT |
248 |
252 |
249 |
253 |
250 #ifndef QT_NO_ACCESSIBILITY |
254 #ifndef QT_NO_ACCESSIBILITY |
251 extern IAccessible *qt_createWindowsAccessible(QAccessibleInterface *object); |
255 extern IAccessible *qt_createWindowsAccessible(QAccessibleInterface *object); |
252 #endif // QT_NO_ACCESSIBILITY |
256 #endif // QT_NO_ACCESSIBILITY |
254 extern bool qt_tabletChokeMouse; |
258 extern bool qt_tabletChokeMouse; |
255 extern QWidget* qt_get_tablet_widget(); |
259 extern QWidget* qt_get_tablet_widget(); |
256 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); |
260 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); |
257 extern QRegion qt_dirtyRegion(QWidget *); |
261 extern QRegion qt_dirtyRegion(QWidget *); |
258 |
262 |
259 typedef QHash<UINT, QTabletDeviceData> QTabletCursorInfo; |
263 typedef QHash<quint64, QTabletDeviceData> QTabletCursorInfo; |
260 Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo) |
264 Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo) |
261 QTabletDeviceData currentTabletPointer; |
265 QTabletDeviceData currentTabletPointer; |
262 |
266 |
263 // from qregion_win.cpp |
267 // from qregion_win.cpp |
264 extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); |
268 extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); |
787 // QFont::locale_init(); ### Uncomment when it does something on Windows |
793 // QFont::locale_init(); ### Uncomment when it does something on Windows |
788 |
794 |
789 if (QApplication::desktopSettingsAware()) |
795 if (QApplication::desktopSettingsAware()) |
790 qt_set_windows_resources(); |
796 qt_set_windows_resources(); |
791 |
797 |
|
798 #ifndef QT_NO_TABLETEVENT |
792 initWinTabFunctions(); |
799 initWinTabFunctions(); |
|
800 #endif // QT_NO_TABLETEVENT |
793 QApplicationPrivate::inputContext = new QWinInputContext(0); |
801 QApplicationPrivate::inputContext = new QWinInputContext(0); |
794 |
802 |
795 // Read the initial cleartype settings... |
803 // Read the initial cleartype settings... |
796 qt_win_read_cleartype_settings(); |
804 qt_win_read_cleartype_settings(); |
797 qt_win_owndc_required = false; |
805 qt_win_owndc_required = false; |
828 |
836 |
829 #if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) |
837 #if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) |
830 priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo; |
838 priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo; |
831 priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments; |
839 priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments; |
832 #elif !defined(Q_WS_WINCE) |
840 #elif !defined(Q_WS_WINCE) |
|
841 #if !defined(QT_NO_NATIVE_GESTURES) |
833 priv->GetGestureInfo = |
842 priv->GetGestureInfo = |
834 (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"), |
843 (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"), |
835 "GetGestureInfo"); |
844 "GetGestureInfo"); |
836 priv->GetGestureExtraArgs = |
845 priv->GetGestureExtraArgs = |
837 (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"), |
846 (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"), |
843 (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"), |
852 (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"), |
844 "SetGestureConfig"); |
853 "SetGestureConfig"); |
845 priv->GetGestureConfig = |
854 priv->GetGestureConfig = |
846 (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"), |
855 (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"), |
847 "GetGestureConfig"); |
856 "GetGestureConfig"); |
|
857 #endif // QT_NO_NATIVE_GESTURES |
848 priv->BeginPanningFeedback = |
858 priv->BeginPanningFeedback = |
849 (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), |
859 (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), |
850 "BeginPanningFeedback"); |
860 "BeginPanningFeedback"); |
851 priv->UpdatePanningFeedback = |
861 priv->UpdatePanningFeedback = |
852 (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), |
862 (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), |
2321 result = widget->translateTabletEvent(msg, localPacketBuf, nPackets); |
2329 result = widget->translateTabletEvent(msg, localPacketBuf, nPackets); |
2322 } |
2330 } |
2323 } |
2331 } |
2324 break; |
2332 break; |
2325 case WT_PROXIMITY: |
2333 case WT_PROXIMITY: |
2326 if (ptrWTPacketsGet) { |
2334 |
2327 bool enteredProximity = LOWORD(lParam) != 0; |
2335 #ifndef QT_NO_TABLETEVENT |
2328 PACKET proximityBuffer[QT_TABLET_NPACKETQSIZE]; |
2336 if (ptrWTPacketsGet && ptrWTInfo) { |
2329 int totalPacks = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, proximityBuffer); |
2337 const bool enteredProximity = LOWORD(lParam) != 0; |
2330 if (totalPacks > 0 && enteredProximity) { |
2338 PACKET proximityBuffer[1]; // we are only interested in the first packet in this case |
2331 uint currentCursor = proximityBuffer[0].pkCursor; |
2339 const int totalPacks = ptrWTPacketsGet(qt_tablet_context, 1, proximityBuffer); |
2332 if (!tCursorInfo()->contains(currentCursor)) |
2340 if (totalPacks > 0) { |
2333 tabletInit(currentCursor, qt_tablet_context); |
2341 const UINT currentCursor = proximityBuffer[0].pkCursor; |
2334 currentTabletPointer = tCursorInfo()->value(currentCursor); |
2342 |
|
2343 UINT csr_physid; |
|
2344 ptrWTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &csr_physid); |
|
2345 UINT csr_type; |
|
2346 ptrWTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &csr_type); |
|
2347 const UINT deviceIdMask = 0xFF6; // device type mask && device color mask |
|
2348 quint64 uniqueId = (csr_type & deviceIdMask); |
|
2349 uniqueId = (uniqueId << 32) | csr_physid; |
|
2350 |
|
2351 // initialising and updating the cursor should be done in response to |
|
2352 // WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send |
|
2353 // the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES |
|
2354 const QTabletCursorInfo *const globalCursorInfo = tCursorInfo(); |
|
2355 if (!globalCursorInfo->contains(uniqueId)) |
|
2356 tabletInit(uniqueId, csr_type, qt_tablet_context); |
|
2357 |
|
2358 currentTabletPointer = globalCursorInfo->value(uniqueId); |
|
2359 tabletUpdateCursor(currentTabletPointer, currentCursor); |
2335 } |
2360 } |
2336 qt_tabletChokeMouse = false; |
2361 qt_tabletChokeMouse = false; |
2337 #ifndef QT_NO_TABLETEVENT |
2362 |
2338 QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity |
2363 QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity |
2339 : QEvent::TabletLeaveProximity, |
2364 : QEvent::TabletLeaveProximity, |
2340 QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0, |
2365 QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0, |
2341 0, 0, 0, 0, 0, currentTabletPointer.llId); |
2366 0, 0, 0, 0, 0, currentTabletPointer.llId); |
2342 QApplication::sendEvent(qApp, &tabletProximity); |
2367 QApplication::sendEvent(qApp, &tabletProximity); |
2343 #endif // QT_NO_TABLETEVENT |
2368 } |
2344 } |
2369 #endif // QT_NO_TABLETEVENT |
|
2370 |
2345 break; |
2371 break; |
2346 #ifdef Q_WS_WINCE_WM |
2372 #ifdef Q_WS_WINCE_WM |
2347 case WM_SETFOCUS: { |
2373 case WM_SETFOCUS: { |
2348 HIMC hC; |
2374 HIMC hC; |
2349 hC = ImmGetContext(hwnd); |
2375 hC = ImmGetContext(hwnd); |
2497 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); |
2523 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); |
2498 BOOL bResult = false; |
2524 BOOL bResult = false; |
2499 if (qAppPriv->GetGestureInfo) |
2525 if (qAppPriv->GetGestureInfo) |
2500 bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); |
2526 bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); |
2501 if (bResult) { |
2527 if (bResult) { |
2502 // if (gi.dwID == GID_BEGIN) { |
2528 if (gi.dwID == GID_BEGIN) { |
2503 // // find the alien widget for the gesture position. |
2529 // find the alien widget for the gesture position. |
2504 // // This might not be accurate as the position is the center |
2530 // This might not be accurate as the position is the center |
2505 // // point of two fingers for multi-finger gestures. |
2531 // point of two fingers for multi-finger gestures. |
2506 // QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); |
2532 QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); |
2507 // QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); |
2533 QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); |
2508 // qAppPriv->gestureWidget = w ? w : widget; |
2534 qAppPriv->gestureWidget = w ? w : widget; |
2509 // } |
2535 } |
2510 // if (qAppPriv->gestureWidget) |
2536 if (qAppPriv->gestureWidget) |
2511 // static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); |
2537 static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); |
2512 // if (qAppPriv->CloseGestureInfoHandle) |
2538 if (qAppPriv->CloseGestureInfoHandle) |
2513 // qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); |
2539 qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); |
2514 // if (gi.dwID == GID_END) |
2540 if (gi.dwID == GID_END) |
2515 // qAppPriv->gestureWidget = 0; |
2541 qAppPriv->gestureWidget = 0; |
2516 // } else { |
2542 } else { |
2517 // DWORD dwErr = GetLastError(); |
2543 DWORD dwErr = GetLastError(); |
2518 // if (dwErr > 0) |
2544 if (dwErr > 0) |
2519 // qWarning() << "translateGestureEvent: error = " << dwErr; |
2545 qWarning() << "translateGestureEvent: error = " << dwErr; |
2520 } |
2546 } |
2521 result = true; |
2547 result = true; |
2522 break; |
2548 break; |
2523 } |
2549 } |
2524 default: |
2550 default: |
3313 // Windows Wintab to QTabletEvent translation |
3339 // Windows Wintab to QTabletEvent translation |
3314 // |
3340 // |
3315 |
3341 |
3316 // the following is adapted from the wintab syspress example (public domain) |
3342 // the following is adapted from the wintab syspress example (public domain) |
3317 /* -------------------------------------------------------------------------- */ |
3343 /* -------------------------------------------------------------------------- */ |
3318 static void tabletInit(UINT wActiveCsr, HCTX hTab) |
3344 // Initialize the "static" information of a cursor device (pen, airbrush, etc). |
3319 { |
3345 // The QTabletDeviceData is initialized with the data that do not change in time |
|
3346 // (number of button, type of device, etc) but do not initialize the variable data |
|
3347 // (e.g.: pen or eraser) |
|
3348 #ifndef QT_NO_TABLETEVENT |
|
3349 |
|
3350 static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab) |
|
3351 { |
|
3352 Q_ASSERT(ptrWTInfo); |
|
3353 Q_ASSERT(ptrWTGet); |
|
3354 |
|
3355 Q_ASSERT(!tCursorInfo()->contains(uniqueId)); |
|
3356 |
3320 /* browse WinTab's many info items to discover pressure handling. */ |
3357 /* browse WinTab's many info items to discover pressure handling. */ |
3321 if (ptrWTInfo && ptrWTGet) { |
3358 AXIS np; |
3322 AXIS np; |
3359 LOGCONTEXT lc; |
3323 LOGCONTEXT lc; |
3360 |
3324 BYTE wPrsBtn; |
3361 /* get the current context for its device variable. */ |
3325 BYTE logBtns[32]; |
3362 ptrWTGet(hTab, &lc); |
3326 UINT size; |
3363 |
3327 |
3364 /* get the size of the pressure axis. */ |
3328 /* discover the LOGICAL button generated by the pressure channel. */ |
3365 QTabletDeviceData tdd; |
3329 /* get the PHYSICAL button from the cursor category and run it */ |
3366 tdd.llId = uniqueId; |
3330 /* through that cursor's button map (usually the identity map). */ |
3367 |
3331 wPrsBtn = (BYTE)-1; |
3368 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np); |
3332 ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_NPBUTTON, &wPrsBtn); |
3369 tdd.minPressure = int(np.axMin); |
3333 size = ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_BUTTONMAP, &logBtns); |
3370 tdd.maxPressure = int(np.axMax); |
3334 if ((UINT)wPrsBtn < size) |
3371 |
3335 wPrsBtn = logBtns[wPrsBtn]; |
3372 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np); |
3336 |
3373 tdd.minTanPressure = int(np.axMin); |
3337 /* get the current context for its device variable. */ |
3374 tdd.maxTanPressure = int(np.axMax); |
3338 ptrWTGet(hTab, &lc); |
3375 |
3339 |
3376 LOGCONTEXT lcMine; |
3340 /* get the size of the pressure axis. */ |
3377 |
3341 QTabletDeviceData tdd; |
3378 /* get default region */ |
3342 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np); |
3379 ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); |
3343 tdd.minPressure = int(np.axMin); |
3380 |
3344 tdd.maxPressure = int(np.axMax); |
3381 tdd.minX = 0; |
3345 |
3382 tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); |
3346 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np); |
3383 |
3347 tdd.minTanPressure = int(np.axMin); |
3384 tdd.minY = 0; |
3348 tdd.maxTanPressure = int(np.axMax); |
3385 tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); |
3349 |
3386 |
3350 LOGCONTEXT lcMine; |
3387 tdd.minZ = 0; |
3351 |
3388 tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); |
3352 /* get default region */ |
3389 |
3353 ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); |
3390 const uint cursorTypeBitMask = 0x0F06; // bitmask to find the specific cursor type (see Wacom FAQ) |
3354 |
3391 if (((csr_type & 0x0006) == 0x0002) && ((csr_type & cursorTypeBitMask) != 0x0902)) { |
3355 tdd.minX = 0; |
3392 tdd.currentDevice = QTabletEvent::Stylus; |
3356 tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); |
3393 } else { |
3357 |
3394 switch (csr_type & cursorTypeBitMask) { |
3358 tdd.minY = 0; |
|
3359 tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); |
|
3360 |
|
3361 tdd.minZ = 0; |
|
3362 tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); |
|
3363 |
|
3364 int csr_type, |
|
3365 csr_physid; |
|
3366 ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_TYPE, &csr_type); |
|
3367 ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_PHYSID, &csr_physid); |
|
3368 tdd.llId = csr_type & 0x0F06; |
|
3369 tdd.llId = (tdd.llId << 24) | csr_physid; |
|
3370 #ifndef QT_NO_TABLETEVENT |
|
3371 if (((csr_type & 0x0006) == 0x0002) && ((csr_type & 0x0F06) != 0x0902)) { |
|
3372 tdd.currentDevice = QTabletEvent::Stylus; |
|
3373 } else { |
|
3374 switch (csr_type & 0x0F06) { |
|
3375 case 0x0802: |
3395 case 0x0802: |
3376 tdd.currentDevice = QTabletEvent::Stylus; |
3396 tdd.currentDevice = QTabletEvent::Stylus; |
3377 break; |
3397 break; |
3378 case 0x0902: |
3398 case 0x0902: |
3379 tdd.currentDevice = QTabletEvent::Airbrush; |
3399 tdd.currentDevice = QTabletEvent::Airbrush; |
3387 case 0x0804: |
3407 case 0x0804: |
3388 tdd.currentDevice = QTabletEvent::RotationStylus; |
3408 tdd.currentDevice = QTabletEvent::RotationStylus; |
3389 break; |
3409 break; |
3390 default: |
3410 default: |
3391 tdd.currentDevice = QTabletEvent::NoDevice; |
3411 tdd.currentDevice = QTabletEvent::NoDevice; |
3392 } |
3412 } |
3393 } |
3413 } |
3394 |
3414 tCursorInfo()->insert(uniqueId, tdd); |
3395 switch (wActiveCsr % 3) { |
3415 } |
3396 case 2: |
|
3397 tdd.currentPointerType = QTabletEvent::Eraser; |
|
3398 break; |
|
3399 case 1: |
|
3400 tdd.currentPointerType = QTabletEvent::Pen; |
|
3401 break; |
|
3402 case 0: |
|
3403 tdd.currentPointerType = QTabletEvent::Cursor; |
|
3404 break; |
|
3405 default: |
|
3406 tdd.currentPointerType = QTabletEvent::UnknownPointer; |
|
3407 } |
|
3408 #endif // QT_NO_TABLETEVENT |
3416 #endif // QT_NO_TABLETEVENT |
3409 tCursorInfo()->insert(wActiveCsr, tdd); |
3417 |
3410 } |
3418 // Update the "dynamic" informations of a cursor device (pen, airbrush, etc). |
3411 } |
3419 // The dynamic information is the information of QTabletDeviceData that can change |
|
3420 // in time (eraser or pen if a device is turned around). |
|
3421 #ifndef QT_NO_TABLETEVENT |
|
3422 |
|
3423 static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor) |
|
3424 { |
|
3425 switch (currentCursor % 3) { // %3 for dual track |
|
3426 case 0: |
|
3427 tdd.currentPointerType = QTabletEvent::Cursor; |
|
3428 break; |
|
3429 case 1: |
|
3430 tdd.currentPointerType = QTabletEvent::Pen; |
|
3431 break; |
|
3432 case 2: |
|
3433 tdd.currentPointerType = QTabletEvent::Eraser; |
|
3434 break; |
|
3435 default: |
|
3436 tdd.currentPointerType = QTabletEvent::UnknownPointer; |
|
3437 } |
|
3438 } |
|
3439 #endif // QT_NO_TABLETEVENT |
3412 |
3440 |
3413 bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, |
3441 bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, |
3414 int numPackets) |
3442 int numPackets) |
3415 { |
3443 { |
3416 Q_UNUSED(msg); |
3444 Q_UNUSED(msg); |