1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module 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 #include "qwindowsysteminterface.h"
40 #include <qpa/qplatformwindow.h>
41 #include "qwindowsysteminterface_p.h"
42 #include "private/qguiapplication_p.h"
43 #include "private/qevent_p.h"
44 #include "private/qtouchdevice_p.h"
45 #include <QAbstractEventDispatcher>
46 #include <qpa/qplatformintegration.h>
47 #include <qdebug.h>
48 #include "qhighdpiscaling_p.h"
49 
50 #include <QtCore/qscopedvaluerollback.h>
51 #include <QtCore/private/qlocking_p.h>
52 
53 #if QT_CONFIG(draganddrop)
54 #include <qpa/qplatformdrag.h>
55 #endif
56 
57 QT_BEGIN_NAMESPACE
58 
59 
60 QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
61 bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false;
62 bool QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse = true;
63 QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
64 QMutex QWindowSystemInterfacePrivate::flushEventMutex;
65 QAtomicInt QWindowSystemInterfacePrivate::eventAccepted;
66 QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler;
67 QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePrivate::windowSystemEventQueue;
68 
69 extern QPointer<QWindow> qt_last_mouse_receiver;
70 
71 
72 // ------------------- QWindowSystemInterfacePrivate -------------------
73 
74 /*
75     Handles a window system event asynchronously by posting the event to Qt Gui.
76 
77     This function posts the event on the window system event queue and wakes the
78     Gui event dispatcher. Qt Gui will then handle the event asynchonously at a
79     later point.
80 */
81 template<>
handleWindowSystemEvent(WindowSystemEvent * ev)82 bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(WindowSystemEvent *ev)
83 {
84     windowSystemEventQueue.append(ev);
85     if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher())
86         dispatcher->wakeUp();
87     return true;
88 }
89 
90 /*
91     Handles a window system event synchronously.
92 
93     Qt Gui will process the event immediately. The return value indicates if Qt
94     accepted the event.
95 
96     If the event is delivered from another thread than the Qt main thread the
97     window system event queue is flushed, which may deliver other events as
98     well.
99 */
100 template<>
handleWindowSystemEvent(WindowSystemEvent * ev)101 bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(WindowSystemEvent *ev)
102 {
103     bool accepted = true;
104     if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
105         // Process the event immediately on the current thread and return the accepted state.
106         QGuiApplicationPrivate::processWindowSystemEvent(ev);
107         accepted = ev->eventAccepted;
108         delete ev;
109     } else {
110         // Post the event on the Qt main thread queue and flush the queue.
111         // This will wake up the Gui thread which will process the event.
112         // Return the accepted state for the last event on the queue,
113         // which is the event posted by this function.
114         handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
115         accepted = QWindowSystemInterface::flushWindowSystemEvents();
116     }
117     return accepted;
118 }
119 
120 /*
121     Handles a window system event.
122 
123     By default this function posts the event on the window system event queue and
124     wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously
125     at a later point. The return value is not used in asynchronous mode and will
126     always be true.
127 
128     In synchronous mode Qt Gui will process the event immediately. The return value
129     indicates if Qt accepted the event. If the event is delivered from another thread
130     than the Qt main thread the window system event queue is flushed, which may deliver
131     other events as well.
132 
133     \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
134 */
135 template<>
handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * ev)136 bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::DefaultDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
137 {
138     if (synchronousWindowSystemEvents)
139         return handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(ev);
140     else
141         return handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
142 }
143 
windowSystemEventsQueued()144 int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
145 {
146     return windowSystemEventQueue.count();
147 }
148 
nonUserInputEventsQueued()149 bool QWindowSystemInterfacePrivate::nonUserInputEventsQueued()
150 {
151     return windowSystemEventQueue.nonUserInputEventsQueued();
152 }
153 
getWindowSystemEvent()154 QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent()
155 {
156     return windowSystemEventQueue.takeFirstOrReturnNull();
157 }
158 
getNonUserInputWindowSystemEvent()159 QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent()
160 {
161     return windowSystemEventQueue.takeFirstNonUserInputOrReturnNull();
162 }
163 
peekWindowSystemEvent(EventType t)164 QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::peekWindowSystemEvent(EventType t)
165 {
166     return windowSystemEventQueue.peekAtFirstOfType(t);
167 }
168 
removeWindowSystemEvent(WindowSystemEvent * event)169 void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *event)
170 {
171     windowSystemEventQueue.remove(event);
172 }
173 
installWindowSystemEventHandler(QWindowSystemEventHandler * handler)174 void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler)
175 {
176     if (!eventHandler)
177         eventHandler = handler;
178 }
179 
removeWindowSystemEventhandler(QWindowSystemEventHandler * handler)180 void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler)
181 {
182     if (eventHandler == handler)
183         eventHandler = nullptr;
184 }
185 
~QWindowSystemEventHandler()186 QWindowSystemEventHandler::~QWindowSystemEventHandler()
187 {
188     QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this);
189 }
190 
sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e)191 bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
192 {
193     QGuiApplicationPrivate::processWindowSystemEvent(e);
194     return true;
195 }
196 
197 //------------------------------------------------------------
198 //
199 // Callback functions for plugins:
200 //
201 
202 #define QT_DEFINE_QPA_EVENT_HANDLER(ReturnType, HandlerName, ...) \
203     template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::DefaultDelivery>(__VA_ARGS__); \
204     template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::SynchronousDelivery>(__VA_ARGS__); \
205     template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::AsynchronousDelivery>(__VA_ARGS__); \
206     template<typename Delivery> ReturnType QWindowSystemInterface::HandlerName(__VA_ARGS__)
207 
208 /*!
209     \class QWindowSystemInterface
210     \since 5.0
211     \internal
212     \preliminary
213     \ingroup qpa
214     \brief The QWindowSystemInterface provides an event queue for the QPA platform.
215 
216     The platform plugins call the various functions to notify about events. The events are queued
217     until sendWindowSystemEvents() is called by the event dispatcher.
218 */
219 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleEnterEvent,QWindow * window,const QPointF & local,const QPointF & global)220 QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *window, const QPointF &local, const QPointF &global)
221 {
222     if (window) {
223         QWindowSystemInterfacePrivate::EnterEvent *e
224                 = new QWindowSystemInterfacePrivate::EnterEvent(window, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window));
225         QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
226     }
227 }
228 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleLeaveEvent,QWindow * window)229 QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *window)
230 {
231     QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(window);
232     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
233 }
234 
235 /*!
236     This method can be used to ensure leave and enter events are both in queue when moving from
237     one QWindow to another. This allows QWindow subclasses to check for a queued enter event
238     when handling the leave event (\c QWindowSystemInterfacePrivate::peekWindowSystemEvent) to
239     determine where mouse went and act accordingly. E.g. QWidgetWindow needs to know if mouse
240     cursor moves between windows in same window hierarchy.
241 */
handleEnterLeaveEvent(QWindow * enter,QWindow * leave,const QPointF & local,const QPointF & global)242 void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local, const QPointF& global)
243 {
244     handleLeaveEvent<AsynchronousDelivery>(leave);
245     handleEnterEvent(enter, local, global);
246 }
247 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleWindowActivated,QWindow * window,Qt::FocusReason r)248 QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::FocusReason r)
249 {
250     QWindowSystemInterfacePrivate::ActivatedWindowEvent *e =
251         new QWindowSystemInterfacePrivate::ActivatedWindowEvent(window, r);
252     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
253 }
254 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleWindowStateChanged,QWindow * window,Qt::WindowStates newState,int oldState)255 QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
256 {
257     Q_ASSERT(window);
258     if (oldState < Qt::WindowNoState)
259         oldState = window->windowStates();
260 
261     QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
262         new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
263     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
264 }
265 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleWindowScreenChanged,QWindow * window,QScreen * screen)266 QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowScreenChanged, QWindow *window, QScreen *screen)
267 {
268 
269     QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e =
270         new QWindowSystemInterfacePrivate::WindowScreenChangedEvent(window, screen);
271     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
272 }
273 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleSafeAreaMarginsChanged,QWindow * window)274 QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window)
275 {
276     QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e =
277         new QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent(window);
278     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
279 }
280 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleApplicationStateChanged,Qt::ApplicationState newState,bool forcePropagate)281 QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate)
282 {
283     Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
284     QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
285         new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate);
286     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
287 }
288 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleApplicationTermination)289 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination)
290 {
291     auto *e = new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::ApplicationTermination);
292     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
293 }
294 
GeometryChangeEvent(QWindow * window,const QRect & newGeometry)295 QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)
296     : WindowSystemEvent(GeometryChange)
297     , window(window)
298     , newGeometry(newGeometry)
299 {
300     if (const QPlatformWindow *pw = window->handle()) {
301         const auto nativeGeometry = pw->QPlatformWindow::geometry();
302         requestedGeometry = window->isTopLevel()
303             ? QHighDpi::fromNativePixels(nativeGeometry, window)
304             : QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
305     }
306 }
307 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleGeometryChange,QWindow * window,const QRect & newRect)308 QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
309 {
310     Q_ASSERT(window);
311     const auto newRectDi = window->isTopLevel()
312         ? QHighDpi::fromNativePixels(newRect, window)
313         : QHighDpi::fromNativeLocalPosition(newRect, window);
314     auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
315     if (window->handle()) {
316         // Persist the new geometry so that QWindow::geometry() can be queried in the resize event
317         window->handle()->QPlatformWindow::setGeometry(newRect);
318         // FIXME: This does not work during platform window creation, where the QWindow does not
319         // have its handle set up yet. Platforms that deliver events during window creation need
320         // to handle the persistence manually, e.g. by overriding geometry().
321     }
322     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
323 }
324 
ExposeEvent(QWindow * window,const QRegion & region)325 QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const QRegion &region)
326     : WindowSystemEvent(Expose)
327     , window(window)
328     , isExposed(window && window->handle() ? window->handle()->isExposed() : false)
329     , region(region)
330 {
331 }
332 
333 /*! \internal
334     Handles an expose event.
335 
336     The platform plugin sends expose events when an area of the window
337     is invalidated or window exposure changes. \a region is in window
338     local coordinates. An empty region indicates that the window is
339     obscured, but note that the exposed property of the QWindow will be set
340     based on what QPlatformWindow::isExposed() returns at the time of this call,
341     not based on what the region is. // FIXME: this should probably be fixed.
342 
343     The platform plugin may omit sending expose events (or send obscure
344     events) for windows that are on screen but where the client area is
345     completely covered by other windows or otherwise not visible. Expose
346     event consumers can then use this to disable updates for such windows.
347     This is required behavior on platforms where OpenGL swapbuffers stops
348     blocking for obscured windows (like macOS).
349 */
QT_DEFINE_QPA_EVENT_HANDLER(void,handleExposeEvent,QWindow * window,const QRegion & region)350 QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QRegion &region)
351 {
352     QWindowSystemInterfacePrivate::ExposeEvent *e =
353         new QWindowSystemInterfacePrivate::ExposeEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window));
354     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
355 }
356 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleCloseEvent,QWindow * window)357 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window)
358 {
359     Q_ASSERT(window);
360     auto *event = new QWindowSystemInterfacePrivate::CloseEvent(window);
361     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(event);
362 }
363 
364 /*!
365 
366 \a w == 0 means that the event is in global coords only, \a local will be ignored in this case
367 
368 */
369 #if QT_DEPRECATED_SINCE(5, 11)
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleMouseEvent,QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)370 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
371                                               Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
372 {
373     return handleMouseEvent<Delivery>(window, local, global, b, Qt::NoButton, QEvent::None, mods, source);
374 }
375 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleMouseEvent,QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)376 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
377                                               Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
378 {
379     return handleMouseEvent<Delivery>(window, timestamp, local, global, b, Qt::NoButton, QEvent::None, mods, source);
380 }
381 
handleFrameStrutMouseEvent(QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)382 bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
383                                                         Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
384 {
385     return handleFrameStrutMouseEvent(window, local, global, b, Qt::NoButton, QEvent::None, mods, source);
386 }
387 
handleFrameStrutMouseEvent(QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)388 bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
389                                                         Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
390 {
391     return handleFrameStrutMouseEvent(window, timestamp, local, global, b, Qt::NoButton, QEvent::None, mods, source);
392 }
393 #endif // QT_DEPRECATED_SINCE(5, 11)
394 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleMouseEvent,QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons state,Qt::MouseButton button,QEvent::Type type,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)395 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window,
396                             const QPointF &local, const QPointF &global, Qt::MouseButtons state,
397                             Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
398                             Qt::MouseEventSource source)
399 {
400     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
401     return handleMouseEvent<Delivery>(window, time, local, global, state, button, type, mods, source);
402 }
403 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleMouseEvent,QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,Qt::MouseButtons state,Qt::MouseButton button,QEvent::Type type,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)404 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp,
405                             const QPointF &local, const QPointF &global, Qt::MouseButtons state,
406                             Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
407                             Qt::MouseEventSource source)
408 {
409     Q_ASSERT_X(type != QEvent::MouseButtonDblClick && type != QEvent::NonClientAreaMouseButtonDblClick,
410                "QWindowSystemInterface::handleMouseEvent",
411                "QTBUG-71263: Native double clicks are not implemented.");
412     auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
413     auto globalPos = QHighDpi::fromNativePixels(global, window);
414 
415     QWindowSystemInterfacePrivate::MouseEvent *e =
416         new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos,
417                                                       state, mods, button, type, source);
418     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
419 }
420 
handleFrameStrutMouseEvent(QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons state,Qt::MouseButton button,QEvent::Type type,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)421 bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window,
422                                                         const QPointF &local, const QPointF &global,
423                                                         Qt::MouseButtons state,
424                                                         Qt::MouseButton button, QEvent::Type type,
425                                                         Qt::KeyboardModifiers mods,
426                                                         Qt::MouseEventSource source)
427 {
428     const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
429     return handleFrameStrutMouseEvent(window, time, local, global, state, button, type, mods, source);
430 }
431 
handleFrameStrutMouseEvent(QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,Qt::MouseButtons state,Qt::MouseButton button,QEvent::Type type,Qt::KeyboardModifiers mods,Qt::MouseEventSource source)432 bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp,
433                                                         const QPointF &local, const QPointF &global,
434                                                         Qt::MouseButtons state,
435                                                         Qt::MouseButton button, QEvent::Type type,
436                                                         Qt::KeyboardModifiers mods,
437                                                         Qt::MouseEventSource source)
438 {
439     auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
440     auto globalPos = QHighDpi::fromNativePixels(global, window);
441 
442     QWindowSystemInterfacePrivate::MouseEvent *e =
443             new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos,
444                                                           state, mods, button, type, source, true);
445     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
446 }
447 
handleShortcutEvent(QWindow * window,ulong timestamp,int keyCode,Qt::KeyboardModifiers modifiers,quint32 nativeScanCode,quint32 nativeVirtualKey,quint32 nativeModifiers,const QString & text,bool autorepeat,ushort count)448 bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode,
449                                       quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text, bool autorepeat, ushort count)
450 {
451 #ifndef QT_NO_SHORTCUT
452     if (!window)
453         window = QGuiApplication::focusWindow();
454 
455     QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap;
456     if (shortcutMap.state() == QKeySequence::NoMatch) {
457         // Check if the shortcut is overridden by some object in the event delivery path (typically the focus object).
458         // If so, we should not look up the shortcut in the shortcut map, but instead deliver the event as a regular
459         // key event, so that the target that accepted the shortcut override event can handle it. Note that we only
460         // do this if the shortcut map hasn't found a partial shortcut match yet. If it has, the shortcut can not be
461         // overridden.
462         QWindowSystemInterfacePrivate::KeyEvent *shortcutOverrideEvent = new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp,
463             QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count);
464 
465         {
466             if (QWindowSystemInterfacePrivate::handleWindowSystemEvent<SynchronousDelivery>(shortcutOverrideEvent))
467                 return false;
468         }
469     }
470 
471     // The shortcut event is dispatched as a QShortcutEvent, not a QKeyEvent, but we use
472     // the QKeyEvent as a container for the various properties that the shortcut map needs
473     // to inspect to determine if a shortcut matched the keys that were pressed.
474     QKeyEvent keyEvent(QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode,
475         nativeVirtualKey, nativeModifiers, text, autorepeat, count);
476 
477     return shortcutMap.tryShortcut(&keyEvent);
478 #else
479     Q_UNUSED(window)
480     Q_UNUSED(timestamp)
481     Q_UNUSED(keyCode)
482     Q_UNUSED(modifiers)
483     Q_UNUSED(nativeScanCode)
484     Q_UNUSED(nativeVirtualKey)
485     Q_UNUSED(nativeModifiers)
486     Q_UNUSED(text)
487     Q_UNUSED(autorepeat)
488     Q_UNUSED(count)
489     return false;
490 #endif
491 }
492 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleKeyEvent,QWindow * window,QEvent::Type t,int k,Qt::KeyboardModifiers mods,const QString & text,bool autorep,ushort count)493 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
494     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
495     return handleKeyEvent<Delivery>(window, time, t, k, mods, text, autorep, count);
496 }
497 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleKeyEvent,QWindow * window,ulong timestamp,QEvent::Type t,int k,Qt::KeyboardModifiers mods,const QString & text,bool autorep,ushort count)498 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
499 {
500 #if defined(Q_OS_MACOS)
501     if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count))
502         return true;
503 #endif
504 
505     QWindowSystemInterfacePrivate::KeyEvent * e =
506             new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, t, k, mods, text, autorep, count);
507     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
508 }
509 
handleExtendedKeyEvent(QWindow * window,QEvent::Type type,int key,Qt::KeyboardModifiers modifiers,quint32 nativeScanCode,quint32 nativeVirtualKey,quint32 nativeModifiers,const QString & text,bool autorep,ushort count,bool tryShortcutOverride)510 bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
511                                                     quint32 nativeScanCode, quint32 nativeVirtualKey,
512                                                     quint32 nativeModifiers,
513                                                     const QString& text, bool autorep,
514                                                     ushort count, bool tryShortcutOverride)
515 {
516     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
517     return handleExtendedKeyEvent(window, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
518                            text, autorep, count, tryShortcutOverride);
519 }
520 
handleExtendedKeyEvent(QWindow * window,ulong timestamp,QEvent::Type type,int key,Qt::KeyboardModifiers modifiers,quint32 nativeScanCode,quint32 nativeVirtualKey,quint32 nativeModifiers,const QString & text,bool autorep,ushort count,bool tryShortcutOverride)521 bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key,
522                                                     Qt::KeyboardModifiers modifiers,
523                                                     quint32 nativeScanCode, quint32 nativeVirtualKey,
524                                                     quint32 nativeModifiers,
525                                                     const QString& text, bool autorep,
526                                                     ushort count, bool tryShortcutOverride)
527 {
528 #if defined(Q_OS_MACOS)
529     if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window,
530             timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) {
531         return true;
532     }
533 #else
534     Q_UNUSED(tryShortcutOverride)
535 #endif
536 
537     QWindowSystemInterfacePrivate::KeyEvent * e =
538             new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, type, key, modifiers,
539                 nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
540     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
541 }
542 
WheelEvent(QWindow * window,ulong time,const QPointF & local,const QPointF & global,QPoint pixelD,QPoint angleD,int qt4D,Qt::Orientation qt4O,Qt::KeyboardModifiers mods,Qt::ScrollPhase phase,Qt::MouseEventSource src,bool inverted)543 QWindowSystemInterfacePrivate::WheelEvent::WheelEvent(QWindow *window, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD,
544         QPoint angleD, int qt4D, Qt::Orientation qt4O, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource src, bool inverted)
545     : InputEvent(window, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D),
546       qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src), inverted(inverted)
547 {
548 }
549 
550 #if QT_DEPRECATED_SINCE(5, 10)
handleWheelEvent(QWindow * window,const QPointF & local,const QPointF & global,int d,Qt::Orientation o,Qt::KeyboardModifiers mods)551 bool QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) {
552     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
553 QT_WARNING_PUSH
554 QT_WARNING_DISABLE_DEPRECATED
555     return handleWheelEvent(window, time, local, global, d, o, mods);
556 QT_WARNING_POP
557 }
558 
handleWheelEvent(QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,int d,Qt::Orientation o,Qt::KeyboardModifiers mods)559 bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods)
560 {
561     QPoint point = (o == Qt::Vertical) ? QPoint(0, d) : QPoint(d, 0);
562     return handleWheelEvent(window, timestamp, local, global, QPoint(), point, mods);
563 }
564 #endif // QT_DEPRECATED_SINCE(5, 10)
565 
handleWheelEvent(QWindow * window,const QPointF & local,const QPointF & global,QPoint pixelDelta,QPoint angleDelta,Qt::KeyboardModifiers mods,Qt::ScrollPhase phase,Qt::MouseEventSource source)566 bool QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source)
567 {
568     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
569     return handleWheelEvent(window, time, local, global, pixelDelta, angleDelta, mods, phase, source);
570 }
571 
handleWheelEvent(QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,QPoint pixelDelta,QPoint angleDelta,Qt::KeyboardModifiers mods,Qt::ScrollPhase phase,Qt::MouseEventSource source,bool invertedScrolling)572 bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase,
573                                               Qt::MouseEventSource source, bool invertedScrolling)
574 {
575     // Qt 4 sends two separate wheel events for horizontal and vertical
576     // deltas. For Qt 5 we want to send the deltas in one event, but at the
577     // same time preserve source and behavior compatibility with Qt 4.
578     //
579     // In addition high-resolution pixel-based deltas are also supported.
580     // Platforms that does not support these may pass a null point here.
581     // Angle deltas must always be sent in addition to pixel deltas.
582     QWindowSystemInterfacePrivate::WheelEvent *e;
583 
584     // Pass Qt::ScrollBegin and Qt::ScrollEnd through
585     // even if the wheel delta is null.
586     if (angleDelta.isNull() && phase == Qt::ScrollUpdate)
587         return false;
588 
589     // Simple case: vertical deltas only:
590     if (angleDelta.y() != 0 && angleDelta.x() == 0) {
591         e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical,
592                                                           mods, phase, source, invertedScrolling);
593 
594         return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
595     }
596 
597     // Simple case: horizontal deltas only:
598     if (angleDelta.y() == 0 && angleDelta.x() != 0) {
599         e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
600         return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
601     }
602 
603     bool acceptVert;
604     bool acceptHorz;
605     // Both horizontal and vertical deltas: Send two wheel events.
606     // The first event contains the Qt 5 pixel and angle delta as points,
607     // and in addition the Qt 4 compatibility vertical angle delta.
608     e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling);
609     acceptVert = QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
610 
611     // The second event contains null pixel and angle points and the
612     // Qt 4 compatibility horizontal angle delta.
613     e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
614     acceptHorz = QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
615     return acceptVert || acceptHorz;
616 }
617 
registerTouchDevice(const QTouchDevice * device)618 void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device)
619 {
620     QTouchDevicePrivate::registerDevice(device);
621 }
622 
unregisterTouchDevice(const QTouchDevice * device)623 void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device)
624 {
625     QTouchDevicePrivate::unregisterDevice(device);
626 }
627 
isTouchDeviceRegistered(const QTouchDevice * device)628 bool QWindowSystemInterface::isTouchDeviceRegistered(const QTouchDevice *device)
629 {
630     return QTouchDevicePrivate::isRegistered(device);
631 }
632 
633 static int g_nextPointId = 1;
634 
635 // map from device-independent point id (arbitrary) to "Qt point" ids
636 static QBasicMutex pointIdMapMutex;
637 typedef QMap<quint64, int> PointIdMap;
Q_GLOBAL_STATIC(PointIdMap,g_pointIdMap)638 Q_GLOBAL_STATIC(PointIdMap, g_pointIdMap)
639 
640 /*!
641     \internal
642     This function maps potentially arbitrary point ids \a pointId in the 32 bit
643     value space to start from 1 and increase incrementally for each touch point
644     held down. If all touch points are released it will reset the id back to 1
645     for the following touch point.
646 
647     We can then assume that the touch points ids will never become too large,
648     and it will then put the device identifier \a deviceId in the upper 8 bits.
649     This leaves us with max 255 devices, and 16.7M taps without full release
650     before we run out of value space.
651 */
652 static int acquireCombinedPointId(quint8 deviceId, int pointId)
653 {
654     const auto locker = qt_scoped_lock(pointIdMapMutex);
655 
656     quint64 combinedId64 = (quint64(deviceId) << 32) + pointId;
657     auto it = g_pointIdMap->constFind(combinedId64);
658     int uid;
659     if (it == g_pointIdMap->constEnd()) {
660         uid = g_nextPointId++;
661         g_pointIdMap->insert(combinedId64, uid);
662     } else {
663         uid = *it;
664     }
665     return (deviceId << 24) + uid;
666 }
667 
668 QList<QTouchEvent::TouchPoint>
fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> & points,const QWindow * window,quint8 deviceId,QEvent::Type * type)669     QWindowSystemInterfacePrivate::fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
670                                                          const QWindow *window, quint8 deviceId,
671                                                          QEvent::Type *type)
672 {
673     QList<QTouchEvent::TouchPoint> touchPoints;
674     Qt::TouchPointStates states;
675     QTouchEvent::TouchPoint p;
676 
677     touchPoints.reserve(points.count());
678     QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin();
679     QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd();
680     while (point != end) {
681         p.setId(acquireCombinedPointId(deviceId, point->id));
682         if (point->uniqueId >= 0)
683             p.setUniqueId(point->uniqueId);
684         p.setPressure(point->pressure);
685         p.setRotation(point->rotation);
686         states |= point->state;
687         p.setState(point->state);
688 
689         p.setScreenPos(QHighDpi::fromNativePixels(point->area.center(), window));
690         p.setEllipseDiameters(point->area.size());
691 
692         // The local pos and rect are not set, they will be calculated
693         // when the event gets processed by QGuiApplication.
694 
695         p.setNormalizedPos(QHighDpi::fromNativePixels(point->normalPosition, window));
696         p.setVelocity(QHighDpi::fromNativePixels(point->velocity, window));
697         p.setFlags(point->flags);
698         p.setRawScreenPositions(QHighDpi::fromNativePixels(point->rawPositions, window));
699 
700         touchPoints.append(p);
701         ++point;
702     }
703 
704     // Determine the event type based on the combined point states.
705     if (type) {
706         *type = QEvent::TouchUpdate;
707         if (states == Qt::TouchPointPressed)
708             *type = QEvent::TouchBegin;
709         else if (states == Qt::TouchPointReleased)
710             *type = QEvent::TouchEnd;
711     }
712 
713     if (states == Qt::TouchPointReleased) {
714         const auto locker = qt_scoped_lock(pointIdMapMutex);
715 
716         // All points on deviceId have been released.
717         // Remove all points associated with that device from g_pointIdMap.
718         // (On other devices, some touchpoints might still be pressed.
719         // But this function is only called with points from one device at a time.)
720         for (auto it = g_pointIdMap->begin(); it != g_pointIdMap->end();) {
721             if (it.key() >> 32 == quint64(deviceId))
722                 it = g_pointIdMap->erase(it);
723             else
724                 ++it;
725         }
726         if (g_pointIdMap->isEmpty())
727             g_nextPointId = 1;
728     }
729 
730     return touchPoints;
731 }
732 
clearPointIdMap()733 void QWindowSystemInterfacePrivate::clearPointIdMap()
734 {
735     const auto locker = qt_scoped_lock(pointIdMapMutex);
736     g_pointIdMap->clear();
737     g_nextPointId = 1;
738 }
739 
740 QList<QWindowSystemInterface::TouchPoint>
toNativeTouchPoints(const QList<QTouchEvent::TouchPoint> & pointList,const QWindow * window)741     QWindowSystemInterfacePrivate::toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
742                                                        const QWindow *window)
743 {
744     QList<QWindowSystemInterface::TouchPoint> newList;
745     newList.reserve(pointList.size());
746     for (const QTouchEvent::TouchPoint &pt : pointList) {
747         QWindowSystemInterface::TouchPoint p;
748         p.id = pt.id();
749         p.flags = pt.flags();
750         p.normalPosition = QHighDpi::toNativeLocalPosition(pt.normalizedPos(), window);
751         QRectF area(QPointF(), pt.ellipseDiameters());
752         area.moveCenter(pt.screenPos());
753         p.area = QHighDpi::toNativePixels(area, window);
754         p.pressure = pt.pressure();
755         p.state = pt.state();
756         p.velocity = QHighDpi::toNativePixels(pt.velocity(), window);
757         p.rawPositions = QHighDpi::toNativePixels(pt.rawScreenPositions(), window);
758         newList.append(p);
759     }
760     return newList;
761 }
762 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleTouchEvent,QWindow * window,QTouchDevice * device,const QList<TouchPoint> & points,Qt::KeyboardModifiers mods)763 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, QTouchDevice *device,
764                                               const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
765 {
766     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
767     return handleTouchEvent<Delivery>(window, time, device, points, mods);
768 }
769 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleTouchEvent,QWindow * window,ulong timestamp,QTouchDevice * device,const QList<TouchPoint> & points,Qt::KeyboardModifiers mods)770 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong timestamp, QTouchDevice *device,
771                                               const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
772 {
773     if (!points.size()) // Touch events must have at least one point
774         return false;
775 
776     if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices.
777         return false;
778 
779     QEvent::Type type;
780     QList<QTouchEvent::TouchPoint> touchPoints =
781             QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, QTouchDevicePrivate::get(device)->id, &type);
782 
783     QWindowSystemInterfacePrivate::TouchEvent *e =
784             new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods);
785     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
786 }
787 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleTouchCancelEvent,QWindow * window,QTouchDevice * device,Qt::KeyboardModifiers mods)788 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, QTouchDevice *device,
789                                                     Qt::KeyboardModifiers mods)
790 {
791     unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
792     return handleTouchCancelEvent<Delivery>(window, time, device, mods);
793 }
794 
QT_DEFINE_QPA_EVENT_HANDLER(bool,handleTouchCancelEvent,QWindow * window,ulong timestamp,QTouchDevice * device,Qt::KeyboardModifiers mods)795 QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, ulong timestamp, QTouchDevice *device,
796                                                     Qt::KeyboardModifiers mods)
797 {
798     QWindowSystemInterfacePrivate::TouchEvent *e =
799             new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, QEvent::TouchCancel, device,
800                                                          QList<QTouchEvent::TouchPoint>(), mods);
801     return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
802 }
803 
804 /*!
805     Should be called by the implementation whenever a new screen is added.
806 
807     The first screen added will be the primary screen, used for default-created
808     windows, GL contexts, and other resources unless otherwise specified.
809 
810     This adds the screen to QGuiApplication::screens(), and emits the
811     QGuiApplication::screenAdded() signal.
812 
813     The screen should be deleted by calling QWindowSystemInterface::handleScreenRemoved().
814 */
handleScreenAdded(QPlatformScreen * ps,bool isPrimary)815 void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrimary)
816 {
817     QScreen *screen = new QScreen(ps);
818 
819     if (isPrimary)
820         QGuiApplicationPrivate::screen_list.prepend(screen);
821     else
822         QGuiApplicationPrivate::screen_list.append(screen);
823 
824     QGuiApplicationPrivate::resetCachedDevicePixelRatio();
825 
826     emit qGuiApp->screenAdded(screen);
827 
828     if (isPrimary)
829         emit qGuiApp->primaryScreenChanged(screen);
830 }
831 
832 /*!
833     Should be called by the implementation whenever a screen is removed.
834 
835     This removes the screen from QGuiApplication::screens(), and deletes it.
836 
837     Failing to call this and manually deleting the QPlatformScreen instead may
838     lead to a crash due to a pure virtual call.
839 */
handleScreenRemoved(QPlatformScreen * platformScreen)840 void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen)
841 {
842     // Important to keep this order since the QSceen doesn't own the platform screen.
843     // The QScreen destructor will take care changing the primary screen, so no need here.
844     delete platformScreen->screen();
845     delete platformScreen;
846 }
847 
848 /*!
849     Should be called whenever the primary screen changes.
850 
851     When the screen specified as primary changes, this method will notify
852     QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
853  */
handlePrimaryScreenChanged(QPlatformScreen * newPrimary)854 void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrimary)
855 {
856     QScreen *newPrimaryScreen = newPrimary->screen();
857     int indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
858     Q_ASSERT(indexOfScreen >= 0);
859     if (indexOfScreen == 0)
860         return;
861 
862     QGuiApplicationPrivate::screen_list.swapItemsAt(0, indexOfScreen);
863     emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
864 }
865 
handleScreenOrientationChange(QScreen * screen,Qt::ScreenOrientation orientation)866 void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation)
867 {
868     QWindowSystemInterfacePrivate::ScreenOrientationEvent *e =
869             new QWindowSystemInterfacePrivate::ScreenOrientationEvent(screen, orientation);
870     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
871 }
872 
handleScreenGeometryChange(QScreen * screen,const QRect & geometry,const QRect & availableGeometry)873 void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry, const QRect &availableGeometry)
874 {
875     QWindowSystemInterfacePrivate::ScreenGeometryEvent *e =
876         new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, QHighDpi::fromNativeScreenGeometry(geometry, screen), QHighDpi::fromNative(availableGeometry, screen, geometry.topLeft()));
877     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
878 }
879 
handleScreenLogicalDotsPerInchChange(QScreen * screen,qreal dpiX,qreal dpiY)880 void QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal dpiX, qreal dpiY)
881 {
882     const QDpi effectiveDpi = QPlatformScreen::overrideDpi(QDpi{dpiX, dpiY});
883     auto e = new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, effectiveDpi.first, effectiveDpi.second);
884     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
885 }
886 
handleScreenRefreshRateChange(QScreen * screen,qreal newRefreshRate)887 void QWindowSystemInterface::handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate)
888 {
889     QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e =
890             new QWindowSystemInterfacePrivate::ScreenRefreshRateEvent(screen, newRefreshRate);
891     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
892 }
893 
QT_DEFINE_QPA_EVENT_HANDLER(void,handleThemeChange,QWindow * window)894 QT_DEFINE_QPA_EVENT_HANDLER(void, handleThemeChange, QWindow *window)
895 {
896     QWindowSystemInterfacePrivate::ThemeChangeEvent *e = new QWindowSystemInterfacePrivate::ThemeChangeEvent(window);
897     QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
898 }
899 
900 #if QT_CONFIG(draganddrop)
901 #if QT_DEPRECATED_SINCE(5, 11)
handleDrag(QWindow * window,const QMimeData * dropData,const QPoint & p,Qt::DropActions supportedActions)902 QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData,
903                                                            const QPoint &p, Qt::DropActions supportedActions)
904 {
905     return QGuiApplicationPrivate::processDrag(window, dropData, p, supportedActions,
906                                                QGuiApplication::mouseButtons(),
907                                                QGuiApplication::keyboardModifiers());
908 }
909 
handleDrop(QWindow * window,const QMimeData * dropData,const QPoint & p,Qt::DropActions supportedActions)910 QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData,
911                                                            const QPoint &p, Qt::DropActions supportedActions)
912 {
913     return QGuiApplicationPrivate::processDrop(window, dropData, p, supportedActions,
914                                                QGuiApplication::mouseButtons(),
915                                                QGuiApplication::keyboardModifiers());
916 }
917 #endif // QT_DEPRECATED_SINCE(5, 11)
918 /*!
919     Drag and drop events are sent immediately.
920 
921     ### FIXME? Perhaps DnD API should add some convenience APIs that are more
922     intuitive for the possible DND operations. Here passing nullptr as drop data is used to
923     indicate that drop was canceled and QDragLeaveEvent should be sent as a result.
924 */
handleDrag(QWindow * window,const QMimeData * dropData,const QPoint & p,Qt::DropActions supportedActions,Qt::MouseButtons buttons,Qt::KeyboardModifiers modifiers)925 QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData,
926                                                            const QPoint &p, Qt::DropActions supportedActions,
927                                                            Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
928 {
929     auto pos = QHighDpi::fromNativeLocalPosition(p, window);
930     return QGuiApplicationPrivate::processDrag(window, dropData, pos, supportedActions, buttons, modifiers);
931 }
932 
handleDrop(QWindow * window,const QMimeData * dropData,const QPoint & p,Qt::DropActions supportedActions,Qt::MouseButtons buttons,Qt::KeyboardModifiers modifiers)933 QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData,
934                                                            const QPoint &p, Qt::DropActions supportedActions,
935                                                            Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
936 {
937     auto pos = QHighDpi::fromNativeLocalPosition(p, window);
938     return QGuiApplicationPrivate::processDrop(window, dropData, pos, supportedActions, buttons, modifiers);
939 }
940 #endif // QT_CONFIG(draganddrop)
941 
942 /*!
943     \fn static QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
944     \brief Passes a native event identified by \a eventType to the \a window.
945 
946     \note This function can only be called from the GUI thread.
947 */
948 
949 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
handleNativeEvent(QWindow * window,const QByteArray & eventType,void * message,qintptr * result)950 bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result)
951 #else
952 bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
953 #endif
954 {
955     return QGuiApplicationPrivate::processNativeEvent(window, eventType, message, result);
956 }
957 
handleFileOpenEvent(const QString & fileName)958 void QWindowSystemInterface::handleFileOpenEvent(const QString& fileName)
959 {
960     QWindowSystemInterfacePrivate::FileOpenEvent e(fileName);
961     QGuiApplicationPrivate::processWindowSystemEvent(&e);
962 }
963 
handleFileOpenEvent(const QUrl & url)964 void QWindowSystemInterface::handleFileOpenEvent(const QUrl &url)
965 {
966     QWindowSystemInterfacePrivate::FileOpenEvent e(url);
967     QGuiApplicationPrivate::processWindowSystemEvent(&e);
968 }
969 
setPlatformSynthesizesMouse(bool v)970 void QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(bool v)
971 {
972     platformSynthesizesMouse = v;
973 }
974 
handleTabletEvent(QWindow * window,ulong timestamp,const QPointF & local,const QPointF & global,int device,int pointerType,Qt::MouseButtons buttons,qreal pressure,int xTilt,int yTilt,qreal tangentialPressure,qreal rotation,int z,qint64 uid,Qt::KeyboardModifiers modifiers)975 bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global,
976                                                int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
977                                                qreal tangentialPressure, qreal rotation, int z, qint64 uid,
978                                                Qt::KeyboardModifiers modifiers)
979 {
980     QWindowSystemInterfacePrivate::TabletEvent *e =
981         new QWindowSystemInterfacePrivate::TabletEvent(window, timestamp,
982                                                        QHighDpi::fromNativeLocalPosition(local, window),
983                                                        QHighDpi::fromNativePixels(global, window),
984                                                        device, pointerType, buttons, pressure,
985                                                        xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
986     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
987 }
988 
handleTabletEvent(QWindow * window,const QPointF & local,const QPointF & global,int device,int pointerType,Qt::MouseButtons buttons,qreal pressure,int xTilt,int yTilt,qreal tangentialPressure,qreal rotation,int z,qint64 uid,Qt::KeyboardModifiers modifiers)989 bool QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global,
990                                                int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
991                                                qreal tangentialPressure, qreal rotation, int z, qint64 uid,
992                                                Qt::KeyboardModifiers modifiers)
993 {
994     ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
995     return handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure,
996                       xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
997 }
998 
999 #if QT_DEPRECATED_SINCE(5, 10)
handleTabletEvent(QWindow * window,ulong timestamp,bool down,const QPointF & local,const QPointF & global,int device,int pointerType,qreal pressure,int xTilt,int yTilt,qreal tangentialPressure,qreal rotation,int z,qint64 uid,Qt::KeyboardModifiers modifiers)1000 void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
1001                                                int device, int pointerType, qreal pressure, int xTilt, int yTilt,
1002                                                qreal tangentialPressure, qreal rotation, int z, qint64 uid,
1003                                                Qt::KeyboardModifiers modifiers)
1004 {
1005     handleTabletEvent(window, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
1006                       xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
1007 }
1008 
handleTabletEvent(QWindow * window,bool down,const QPointF & local,const QPointF & global,int device,int pointerType,qreal pressure,int xTilt,int yTilt,qreal tangentialPressure,qreal rotation,int z,qint64 uid,Qt::KeyboardModifiers modifiers)1009 void QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global,
1010                                                int device, int pointerType, qreal pressure, int xTilt, int yTilt,
1011                                                qreal tangentialPressure, qreal rotation, int z, qint64 uid,
1012                                                Qt::KeyboardModifiers modifiers)
1013 {
1014     handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
1015                       xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
1016 }
1017 #endif // QT_DEPRECATED_SINCE(5, 10)
1018 
handleTabletEnterProximityEvent(ulong timestamp,int device,int pointerType,qint64 uid)1019 bool QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid)
1020 {
1021     QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e =
1022             new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device, pointerType, uid);
1023     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1024 }
1025 
handleTabletEnterProximityEvent(int device,int pointerType,qint64 uid)1026 void QWindowSystemInterface::handleTabletEnterProximityEvent(int device, int pointerType, qint64 uid)
1027 {
1028     ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
1029     handleTabletEnterProximityEvent(time, device, pointerType, uid);
1030 }
1031 
handleTabletLeaveProximityEvent(ulong timestamp,int device,int pointerType,qint64 uid)1032 bool QWindowSystemInterface::handleTabletLeaveProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid)
1033 {
1034     QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e =
1035             new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device, pointerType, uid);
1036     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1037 }
1038 
handleTabletLeaveProximityEvent(int device,int pointerType,qint64 uid)1039 void QWindowSystemInterface::handleTabletLeaveProximityEvent(int device, int pointerType, qint64 uid)
1040 {
1041     ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
1042     handleTabletLeaveProximityEvent(time, device, pointerType, uid);
1043 }
1044 
1045 #ifndef QT_NO_GESTURES
handleGestureEvent(QWindow * window,QTouchDevice * device,ulong timestamp,Qt::NativeGestureType type,QPointF & local,QPointF & global)1046 bool QWindowSystemInterface::handleGestureEvent(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type,
1047                                                 QPointF &local, QPointF &global)
1048 {
1049     QWindowSystemInterfacePrivate::GestureEvent *e =
1050         new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global);
1051        return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1052 }
1053 
handleGestureEventWithRealValue(QWindow * window,QTouchDevice * device,ulong timestamp,Qt::NativeGestureType type,qreal value,QPointF & local,QPointF & global)1054 bool QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type,
1055                                                                 qreal value, QPointF &local, QPointF &global)
1056 {
1057     QWindowSystemInterfacePrivate::GestureEvent *e =
1058         new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global);
1059     e->realValue = value;
1060     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1061 }
1062 
handleGestureEventWithSequenceIdAndValue(QWindow * window,QTouchDevice * device,ulong timestamp,Qt::NativeGestureType type,ulong sequenceId,quint64 value,QPointF & local,QPointF & global)1063 bool QWindowSystemInterface::handleGestureEventWithSequenceIdAndValue(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type,
1064                                                                          ulong sequenceId, quint64 value, QPointF &local, QPointF &global)
1065 {
1066     QWindowSystemInterfacePrivate::GestureEvent *e =
1067         new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global);
1068     e->sequenceId = sequenceId;
1069     e->intValue = value;
1070     return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1071 }
1072 #endif // QT_NO_GESTURES
1073 
handlePlatformPanelEvent(QWindow * w)1074 void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w)
1075 {
1076     QWindowSystemInterfacePrivate::PlatformPanelEvent *e =
1077             new QWindowSystemInterfacePrivate::PlatformPanelEvent(w);
1078     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1079 }
1080 
1081 #ifndef QT_NO_CONTEXTMENU
handleContextMenuEvent(QWindow * window,bool mouseTriggered,const QPoint & pos,const QPoint & globalPos,Qt::KeyboardModifiers modifiers)1082 void QWindowSystemInterface::handleContextMenuEvent(QWindow *window, bool mouseTriggered,
1083                                                     const QPoint &pos, const QPoint &globalPos,
1084                                                     Qt::KeyboardModifiers modifiers)
1085 {
1086     QWindowSystemInterfacePrivate::ContextMenuEvent *e =
1087             new QWindowSystemInterfacePrivate::ContextMenuEvent(window, mouseTriggered, pos,
1088                                                                 globalPos, modifiers);
1089     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1090 }
1091 #endif
1092 
1093 #if QT_CONFIG(whatsthis)
handleEnterWhatsThisEvent()1094 void QWindowSystemInterface::handleEnterWhatsThisEvent()
1095 {
1096     QWindowSystemInterfacePrivate::WindowSystemEvent *e =
1097             new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::EnterWhatsThisMode);
1098     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
1099 }
1100 #endif
1101 
1102 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QWindowSystemInterface::TouchPoint & p)1103 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPoint &p)
1104 {
1105     QDebugStateSaver saver(dbg);
1106     dbg.nospace() << "TouchPoint(" << p.id << " @" << p.area << " normalized " << p.normalPosition
1107                   << " press " << p.pressure << " vel " << p.velocity << " state " << (int)p.state;
1108     return dbg;
1109 }
1110 #endif
1111 
1112 // ------------------ Event dispatcher functionality ------------------
1113 
1114 /*!
1115     Make Qt Gui process all events on the event queue immediately. Return the
1116     accepted state for the last event on the queue.
1117 */
flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)1118 bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
1119 {
1120     const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
1121     if (!count)
1122         return false;
1123     if (!QGuiApplication::instance()) {
1124         qWarning().nospace()
1125             << "QWindowSystemInterface::flushWindowSystemEvents() invoked after "
1126                "QGuiApplication destruction, discarding " << count << " events.";
1127         QWindowSystemInterfacePrivate::windowSystemEventQueue.clear();
1128         return false;
1129     }
1130     if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
1131         // Post a FlushEvents event which will trigger a call back to
1132         // deferredFlushWindowSystemEvents from the Gui thread.
1133         QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
1134         QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
1135         QWindowSystemInterfacePrivate::handleWindowSystemEvent<AsynchronousDelivery>(e);
1136         QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
1137     } else {
1138         sendWindowSystemEvents(flags);
1139     }
1140     return QWindowSystemInterfacePrivate::eventAccepted.loadRelaxed() > 0;
1141 }
1142 
deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)1143 void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
1144 {
1145     Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
1146 
1147     QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
1148     sendWindowSystemEvents(flags);
1149     QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
1150 }
1151 
sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)1152 bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
1153 {
1154     int nevents = 0;
1155 
1156     while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
1157         QWindowSystemInterfacePrivate::WindowSystemEvent *event =
1158                 flags & QEventLoop::ExcludeUserInputEvents ?
1159                         QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
1160                         QWindowSystemInterfacePrivate::getWindowSystemEvent();
1161         if (!event)
1162             break;
1163 
1164         if (QWindowSystemInterfacePrivate::eventHandler) {
1165             if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event))
1166                 nevents++;
1167         } else {
1168             nevents++;
1169             QGuiApplicationPrivate::processWindowSystemEvent(event);
1170         }
1171 
1172         // Record the accepted state for the processed event
1173         // (excluding flush events). This state can then be
1174         // returned by flushWindowSystemEvents().
1175         if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
1176             QWindowSystemInterfacePrivate::eventAccepted.storeRelaxed(event->eventAccepted);
1177 
1178         delete event;
1179     }
1180 
1181     return (nevents > 0);
1182 }
1183 
setSynchronousWindowSystemEvents(bool enable)1184 void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable)
1185 {
1186     QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable;
1187 }
1188 
windowSystemEventsQueued()1189 int QWindowSystemInterface::windowSystemEventsQueued()
1190 {
1191     return QWindowSystemInterfacePrivate::windowSystemEventsQueued();
1192 }
1193 
nonUserInputEventsQueued()1194 bool QWindowSystemInterface::nonUserInputEventsQueued()
1195 {
1196     return QWindowSystemInterfacePrivate::nonUserInputEventsQueued();
1197 }
1198 
1199 // --------------------- QtTestLib support ---------------------
1200 
1201 // The following functions are used by testlib, and need to be synchronous to avoid
1202 // race conditions with plugins delivering native events from secondary threads.
1203 // FIXME: It seems unnecessary to export these wrapper functions, when qtestlib could access
1204 // QWindowSystemInterface directly (by adding dependency to gui-private), see QTBUG-63146.
1205 
qt_handleMouseEvent(QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons state,Qt::MouseButton button,QEvent::Type type,Qt::KeyboardModifiers mods,int timestamp)1206 Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global,
1207                                       Qt::MouseButtons state, Qt::MouseButton button,
1208                                       QEvent::Type type, Qt::KeyboardModifiers mods, int timestamp)
1209 {
1210     const qreal factor = QHighDpiScaling::factor(window);
1211     QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(window,
1212                 timestamp, local * factor, global * factor, state, button, type, mods);
1213 }
1214 
1215 // Wrapper for compatibility with Qt < 5.11
1216 // ### Qt6: Remove
qt_handleMouseEvent(QWindow * window,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods,int timestamp)1217 Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global,
1218                                       Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
1219 {
1220     const qreal factor = QHighDpiScaling::factor(window);
1221     QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(window,
1222                 timestamp, local * factor, global * factor, b, Qt::NoButton, QEvent::None, mods);
1223 }
1224 
1225 // Wrapper for compatibility with Qt < 5.6
1226 // ### Qt6: Remove
qt_handleMouseEvent(QWindow * w,const QPointF & local,const QPointF & global,Qt::MouseButtons b,Qt::KeyboardModifiers mods=Qt::NoModifier)1227 Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier)
1228 {
1229     qt_handleMouseEvent(w, local, global, b, mods, QWindowSystemInterfacePrivate::eventTime.elapsed());
1230 }
1231 
qt_handleKeyEvent(QWindow * window,QEvent::Type t,int k,Qt::KeyboardModifiers mods,const QString & text=QString (),bool autorep=false,ushort count=1)1232 Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
1233 {
1234     QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(window, t, k, mods, text, autorep, count);
1235 }
1236 
qt_sendShortcutOverrideEvent(QObject * o,ulong timestamp,int k,Qt::KeyboardModifiers mods,const QString & text=QString (),bool autorep=false,ushort count=1)1237 Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1)
1238 {
1239 #ifndef QT_NO_SHORTCUT
1240 
1241     // FIXME: This method should not allow targeting a specific object, but should
1242     // instead forward the event to a window, which then takes care of normal event
1243     // propagation. We need to fix a lot of tests before we can refactor this (the
1244     // window needs to be exposed and active and have a focus object), so we leave
1245     // it as is for now. See QTBUG-48577.
1246 
1247     QGuiApplicationPrivate::modifier_buttons = mods;
1248 
1249     QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count);
1250     qevent.setTimestamp(timestamp);
1251 
1252     QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap;
1253     if (shortcutMap.state() == QKeySequence::NoMatch) {
1254         // Try sending as QKeyEvent::ShortcutOverride first
1255         QCoreApplication::sendEvent(o, &qevent);
1256         if (qevent.isAccepted())
1257             return false;
1258     }
1259 
1260     // Then as QShortcutEvent
1261     return shortcutMap.tryShortcut(&qevent);
1262 #else
1263     Q_UNUSED(o)
1264     Q_UNUSED(timestamp)
1265     Q_UNUSED(k)
1266     Q_UNUSED(mods)
1267     Q_UNUSED(text)
1268     Q_UNUSED(autorep)
1269     Q_UNUSED(count)
1270     return false;
1271 #endif
1272 }
1273 
1274 namespace QTest
1275 {
createTouchDevice(QTouchDevice::DeviceType devType=QTouchDevice::TouchScreen)1276     Q_GUI_EXPORT QTouchDevice * createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen)
1277     {
1278         QTouchDevice *ret = new QTouchDevice();
1279         ret->setType(devType);
1280         QWindowSystemInterface::registerTouchDevice(ret);
1281         return ret;
1282     }
1283 }
1284 
qt_handleTouchEvent(QWindow * window,QTouchDevice * device,const QList<QTouchEvent::TouchPoint> & points,Qt::KeyboardModifiers mods=Qt::NoModifier)1285 Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, QTouchDevice *device,
1286                                 const QList<QTouchEvent::TouchPoint> &points,
1287                                 Qt::KeyboardModifiers mods = Qt::NoModifier)
1288 {
1289     QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device,
1290         QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window), mods);
1291 }
1292 
1293 
1294 QT_END_NAMESPACE
1295