1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40// This file is included from qnsview.mm, and only used to organize the code
41
42#ifndef QT_NO_GESTURES
43
44Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
45
46@implementation QNSView (Gestures)
47
48- (bool)handleGestureAsBeginEnd:(NSEvent *)event
49{
50    if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan)
51        return false;
52
53    if ([event phase] == NSEventPhaseBegan) {
54        [self beginGestureWithEvent:event];
55        return true;
56    }
57
58    if ([event phase] == NSEventPhaseEnded) {
59        [self endGestureWithEvent:event];
60        return true;
61    }
62
63    return false;
64}
65- (void)magnifyWithEvent:(NSEvent *)event
66{
67    if (!m_platformWindow)
68        return;
69
70    if ([self handleGestureAsBeginEnd:event])
71        return;
72
73    qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << Qt::hex << [event deviceID];
74    const NSTimeInterval timestamp = [event timestamp];
75    QPointF windowPoint;
76    QPointF screenPoint;
77    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
78    QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::ZoomNativeGesture,
79                                                            [event magnification], windowPoint, screenPoint);
80}
81
82- (void)smartMagnifyWithEvent:(NSEvent *)event
83{
84    if (!m_platformWindow)
85        return;
86
87    static bool zoomIn = true;
88    qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << Qt::hex << [event deviceID];
89    const NSTimeInterval timestamp = [event timestamp];
90    QPointF windowPoint;
91    QPointF screenPoint;
92    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
93    QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SmartZoomNativeGesture,
94                                                            zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint);
95    zoomIn = !zoomIn;
96}
97
98- (void)rotateWithEvent:(NSEvent *)event
99{
100    if (!m_platformWindow)
101        return;
102
103    if ([self handleGestureAsBeginEnd:event])
104        return;
105
106    const NSTimeInterval timestamp = [event timestamp];
107    QPointF windowPoint;
108    QPointF screenPoint;
109    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
110    QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::RotateNativeGesture,
111                                                            -[event rotation], windowPoint, screenPoint);
112}
113
114- (void)swipeWithEvent:(NSEvent *)event
115{
116    if (!m_platformWindow)
117        return;
118
119    qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << Qt::hex << [event deviceID];
120    const NSTimeInterval timestamp = [event timestamp];
121    QPointF windowPoint;
122    QPointF screenPoint;
123    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
124
125    qreal angle = 0.0f;
126    if ([event deltaX] == 1)
127        angle = 180.0f;
128    else if ([event deltaX] == -1)
129        angle = 0.0f;
130    else if ([event deltaY] == 1)
131        angle = 90.0f;
132    else if ([event deltaY] == -1)
133        angle = 270.0f;
134
135    QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]),  timestamp, Qt::SwipeNativeGesture,
136                                                            angle, windowPoint, screenPoint);
137}
138
139- (void)beginGestureWithEvent:(NSEvent *)event
140{
141    if (!m_platformWindow)
142        return;
143
144    const NSTimeInterval timestamp = [event timestamp];
145    QPointF windowPoint;
146    QPointF screenPoint;
147    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
148    qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << Qt::hex << [event deviceID];
149    QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]),  timestamp, Qt::BeginNativeGesture,
150                                               windowPoint, screenPoint);
151}
152
153- (void)endGestureWithEvent:(NSEvent *)event
154{
155    if (!m_platformWindow)
156        return;
157
158    qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << Qt::hex << [event deviceID];
159    const NSTimeInterval timestamp = [event timestamp];
160    QPointF windowPoint;
161    QPointF screenPoint;
162    [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
163    QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]),  timestamp, Qt::EndNativeGesture,
164                                               windowPoint, screenPoint);
165}
166
167@end
168
169#endif // QT_NO_GESTURES
170