Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnsview_tablet.mm
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4// This file is included from qnsview.mm, and only used to organize the code
5
6#ifndef QT_NO_TABLETEVENT
7
8#include <QtGui/qpointingdevice.h>
9#include <QtCore/private/qflatmap_p.h>
10
11Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
12
14Q_GLOBAL_STATIC(QCocoaTabletDeviceMap, devicesInProximity)
15
16@implementation QNSView (Tablet)
17
18- (bool)handleTabletEvent:(NSEvent *)theEvent
19{
20 static bool ignoreButtonMapping = qEnvironmentVariableIsSet("QT_MAC_TABLET_IGNORE_BUTTON_MAPPING");
21
22 if (!m_platformWindow)
23 return false;
24
25 NSEventType eventType = [theEvent type];
26 if (eventType != NSEventTypeTabletPoint && [theEvent subtype] != NSEventSubtypeTabletPoint)
27 return false; // Not a tablet event.
28
29 ulong timestamp = [theEvent timestamp] * 1000;
30
31 QPointF windowPoint;
32 QPointF screenPoint;
33 [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint: &windowPoint andScreenPoint: &screenPoint];
34
35 // We use devicesInProximity because deviceID is typically 0,
36 // so QInputDevicePrivate::fromId() won't work.
37 const auto deviceId = theEvent.deviceID;
38 const auto *device = devicesInProximity->value(deviceId);
39 if (!device && deviceId == 0) {
40 // Application started up with stylus in proximity already, so we missed the proximity event?
41 // Create a generic tablet device for now.
42 device = tabletToolInstance(theEvent);
43 devicesInProximity->insert(deviceId, device);
44 }
45
46 if (Q_UNLIKELY(!device))
47 return false;
48
49 bool down = (eventType != NSEventTypeMouseMoved);
50
51 qreal pressure;
52 if (down) {
53 pressure = [theEvent pressure];
54 } else {
55 pressure = 0.0;
56 }
57
58 NSPoint tilt = [theEvent tilt];
59 int xTilt = qRound(tilt.x * 60.0);
60 int yTilt = qRound(tilt.y * -60.0);
61 qreal tangentialPressure = 0;
62 qreal rotation = 0;
63 int z = 0;
65 z = [theEvent absoluteZ];
66
68 tangentialPressure = ([theEvent tangentialPressure] * 2.0) - 1.0;
69
70 rotation = 360.0 - [theEvent rotation];
71 if (rotation > 180.0)
72 rotation -= 360.0;
73
74 Qt::KeyboardModifiers keyboardModifiers = QAppleKeyMapper::fromCocoaModifiers(theEvent.modifierFlags);
75 Qt::MouseButtons buttons = ignoreButtonMapping ? static_cast<Qt::MouseButtons>(static_cast<uint>([theEvent buttonMask])) : m_buttons;
76
77 QWindowSystemInterface::handleTabletEvent(m_platformWindow->window(), timestamp, device, windowPoint, screenPoint,
78 buttons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, keyboardModifiers);
79 return true;
80}
81
82- (void)tabletPoint:(NSEvent *)theEvent
83{
84 if ([self isTransparentForUserInput])
85 return [super tabletPoint:theEvent];
86
87 [self handleTabletEvent: theEvent];
88}
89
97static const QPointingDevice *tabletToolInstance(NSEvent *theEvent)
98{
99 qint64 uid = theEvent.uniqueID;
100 uint bits = theEvent.vendorPointingDeviceType;
101 if (bits == 0 && uid != 0) {
102 // Fallback. It seems that the driver doesn't always include all the information.
103 // High-End Wacom devices store their "type" in the uper bits of the Unique ID.
104 // I'm not sure how to handle it for consumer devices, but I'll test that in a bit.
105 bits = uid >> 32;
106 }
107
108 // Defined in the "EN0056-NxtGenImpGuideX"
109 // on Wacom's Developer Website (www.wacomeng.com)
110 static const quint32 CursorTypeBitMask = 0x0F06;
111 quint32 toolId = bits & CursorTypeBitMask;
112 QInputDevice::Capabilities caps = QInputDevice::Capability::Position |
115 int buttonCount = 3; // the tip, plus two barrel buttons
116 if (((bits & 0x0006) == 0x0002) && (toolId != 0x0902)) {
118 } else {
119 switch (toolId) {
120 // TODO same cases as in qxcbconnection_xi2.cpp? then we could share this function
121 case 0x0802:
123 break;
124 case 0x0902:
127 buttonCount = 2;
128 break;
129 case 0x0004:
132 break;
133 case 0x0006:
135 break;
136 case 0x0804:
139 buttonCount = 1;
140 break;
141 default:
143 }
144 }
145
146 uint capabilityMask = theEvent.capabilityMask;
147 if (capabilityMask & 0x0200)
149 if (capabilityMask & 0x0800)
151
153 switch (theEvent.pointingDeviceType) {
154 case NSPointingDeviceTypeUnknown:
155 default:
156 break;
157 case NSPointingDeviceTypePen:
159 break;
160 case NSPointingDeviceTypeCursor:
162 break;
163 case NSPointingDeviceTypeEraser:
165 break;
166 }
167
168 const auto uniqueID = QPointingDeviceUniqueId::fromNumericId(uid);
169 auto windowSystemId = theEvent.deviceID;
170 const QPointingDevice *ret = QPointingDevicePrivate::queryTabletDevice(device, pointerType, uniqueID, caps, windowSystemId);
171 if (!ret) {
172 // TODO get the device name? (first argument)
173 // TODO associate each stylus with a "master" device representing the tablet itself
174 ret = new QPointingDevice(QString(), windowSystemId, device, pointerType,
175 caps, 1, buttonCount, QString(), uniqueID, QCocoaIntegration::instance());
177 }
179 devPriv->toolId = toolId;
180 return ret;
181}
182
183- (void)tabletProximity:(NSEvent *)theEvent
184{
185 if ([self isTransparentForUserInput])
186 return [super tabletProximity:theEvent];
187
188 const ulong timestamp = theEvent.timestamp * 1000;
189 const qint64 windowSystemId = theEvent.deviceID;
190 const QPointingDevice *device = tabletToolInstance(theEvent);
191 // TODO which window?
192 QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(nullptr, timestamp, device, theEvent.isEnteringProximity);
193 // The windowSystemId starts at 0, but is "unique" while in proximity
194 if (theEvent.isEnteringProximity)
195 devicesInProximity->insert_or_assign(windowSystemId, device);
196 else
197 devicesInProximity->remove(windowSystemId);
198}
199@end
200
201#endif
IOBluetoothDevice * device
static QCocoaIntegration * instance()
DeviceType
This enum represents the type of device that generated a QPointerEvent.
\inmodule QtCore\reentrant
Definition qpoint.h:217
static const QPointingDevice * queryTabletDevice(QInputDevice::DeviceType deviceType, QPointingDevice::PointerType pointerType, QPointingDeviceUniqueId uniqueId, QInputDevice::Capabilities capabilities=QInputDevice::Capability::None, qint64 systemId=0)
static QPointingDevicePrivate * get(QPointingDevice *q)
static QPointingDeviceUniqueId fromNumericId(qint64 id)
Constructs a unique pointer ID from numeric ID id.
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
PointerType
This enum represents what is interacting with the pointing device.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static bool handleTabletEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, const QPointF &local, const QPointF &global, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
static void registerInputDevice(const QInputDevice *device)
static bool handleTabletEnterLeaveProximityEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, bool inProximity, const QPointF &local=QPointF(), const QPointF &global=QPointF(), Qt::MouseButtons buttons={}, int xTilt=0, int yTilt=0, qreal tangentialPressure=0, qreal rotation=0, int z=0, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
QString self
Definition language.cpp:58
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define Q_LOGGING_CATEGORY(name,...)
return ret
Qt::MouseButtons m_buttons
Definition qnsview.mm:102
QFlatMap< qint64, const QPointingDevice * > QCocoaTabletDeviceMap
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLenum type
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
unsigned int quint32
Definition qtypes.h:50
unsigned long ulong
Definition qtypes.h:35
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
static QPointingDevice::PointerType pointerType(unsigned currentCursor)
@ CursorTypeBitMask