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#ifndef QWINDOWSYSTEMINTERFACE_P_H
40#define QWINDOWSYSTEMINTERFACE_P_H
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists purely as an
47// implementation detail. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include <QtGui/private/qtguiglobal_p.h>
54#include "qwindowsysteminterface.h"
55
56#include <QElapsedTimer>
57#include <QPointer>
58#include <QMutex>
59#include <QList>
60#include <QWaitCondition>
61#include <QAtomicInt>
62
63QT_BEGIN_NAMESPACE
64
65class QWindowSystemEventHandler;
66
67class Q_GUI_EXPORT QWindowSystemInterfacePrivate {
68public:
69 enum EventType {
70 UserInputEvent = 0x100,
71 Close = UserInputEvent | 0x01,
72 GeometryChange = 0x02,
73 Enter = UserInputEvent | 0x03,
74 Leave = UserInputEvent | 0x04,
75 ActivatedWindow = 0x05,
76 WindowStateChanged = 0x06,
77 Mouse = UserInputEvent | 0x07,
78 FrameStrutMouse = UserInputEvent | 0x08, // ### Qt6 remove
79 Wheel = UserInputEvent | 0x09,
80 Key = UserInputEvent | 0x0a,
81 Touch = UserInputEvent | 0x0b,
82 ScreenOrientation = 0x0c,
83 ScreenGeometry = 0x0d,
84 ScreenAvailableGeometry = 0x0e,
85 ScreenLogicalDotsPerInch = 0x0f,
86 ScreenRefreshRate = 0x10,
87 ThemeChange = 0x11,
88 Expose = 0x12,
89 FileOpen = UserInputEvent | 0x13,
90 Tablet = UserInputEvent | 0x14,
91 TabletEnterProximity = UserInputEvent | 0x15,
92 TabletLeaveProximity = UserInputEvent | 0x16,
93 PlatformPanel = UserInputEvent | 0x17,
94 ContextMenu = UserInputEvent | 0x18,
95 EnterWhatsThisMode = UserInputEvent | 0x19,
96#ifndef QT_NO_GESTURES
97 Gesture = UserInputEvent | 0x1a,
98#endif
99 ApplicationStateChanged = 0x19,
100 FlushEvents = 0x20,
101 WindowScreenChanged = 0x21,
102 SafeAreaMarginsChanged = 0x22
103 };
104
105 class WindowSystemEvent {
106 public:
107 enum {
108 Synthetic = 0x1,
109 NullWindow = 0x2
110 };
111
112 explicit WindowSystemEvent(EventType t)
113 : type(t), flags(0), eventAccepted(true) { }
114 virtual ~WindowSystemEvent() { }
115
116 bool synthetic() const { return flags & Synthetic; }
117 bool nullWindow() const { return flags & NullWindow; }
118
119 EventType type;
120 int flags;
121 bool eventAccepted;
122 };
123
124 class CloseEvent : public WindowSystemEvent {
125 public:
126 explicit CloseEvent(QWindow *w, bool *a = nullptr)
127 : WindowSystemEvent(Close), window(w), accepted(a)
128 { }
129 QPointer<QWindow> window;
130 bool *accepted;
131 };
132
133 class GeometryChangeEvent : public WindowSystemEvent {
134 public:
135 GeometryChangeEvent(QWindow *window, const QRect &newGeometry);
136 QPointer<QWindow> window;
137 QRect requestedGeometry;
138 QRect newGeometry;
139 };
140
141 class EnterEvent : public WindowSystemEvent {
142 public:
143 explicit EnterEvent(QWindow *enter, const QPointF &local, const QPointF &global)
144 : WindowSystemEvent(Enter), enter(enter), localPos(local), globalPos(global)
145 { }
146 QPointer<QWindow> enter;
147 const QPointF localPos;
148 const QPointF globalPos;
149 };
150
151 class LeaveEvent : public WindowSystemEvent {
152 public:
153 explicit LeaveEvent(QWindow *leave)
154 : WindowSystemEvent(Leave), leave(leave)
155 { }
156 QPointer<QWindow> leave;
157 };
158
159 class ActivatedWindowEvent : public WindowSystemEvent {
160 public:
161 explicit ActivatedWindowEvent(QWindow *activatedWindow, Qt::FocusReason r)
162 : WindowSystemEvent(ActivatedWindow), activated(activatedWindow), reason(r)
163 { }
164 QPointer<QWindow> activated;
165 Qt::FocusReason reason;
166 };
167
168 class WindowStateChangedEvent : public WindowSystemEvent {
169 public:
170 WindowStateChangedEvent(QWindow *_window, Qt::WindowStates _newState, Qt::WindowStates _oldState)
171 : WindowSystemEvent(WindowStateChanged), window(_window), newState(_newState), oldState(_oldState)
172 { }
173
174 QPointer<QWindow> window;
175 Qt::WindowStates newState;
176 Qt::WindowStates oldState;
177 };
178
179 class WindowScreenChangedEvent : public WindowSystemEvent {
180 public:
181 WindowScreenChangedEvent(QWindow *w, QScreen *s)
182 : WindowSystemEvent(WindowScreenChanged), window(w), screen(s)
183 { }
184
185 QPointer<QWindow> window;
186 QPointer<QScreen> screen;
187 };
188
189 class SafeAreaMarginsChangedEvent : public WindowSystemEvent {
190 public:
191 SafeAreaMarginsChangedEvent(QWindow *w)
192 : WindowSystemEvent(SafeAreaMarginsChanged), window(w)
193 { }
194
195 QPointer<QWindow> window;
196 };
197
198 class ApplicationStateChangedEvent : public WindowSystemEvent {
199 public:
200 ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false)
201 : WindowSystemEvent(ApplicationStateChanged), newState(newState), forcePropagate(forcePropagate)
202 { }
203
204 Qt::ApplicationState newState;
205 bool forcePropagate;
206 };
207
208 class FlushEventsEvent : public WindowSystemEvent {
209 public:
210 FlushEventsEvent(QEventLoop::ProcessEventsFlags f = QEventLoop::AllEvents)
211 : WindowSystemEvent(FlushEvents)
212 , flags(f)
213 { }
214 QEventLoop::ProcessEventsFlags flags;
215 };
216
217 class UserEvent : public WindowSystemEvent {
218 public:
219 UserEvent(QWindow * w, ulong time, EventType t)
220 : WindowSystemEvent(t), window(w), timestamp(time)
221 {
222 if (!w)
223 flags |= NullWindow;
224 }
225 QPointer<QWindow> window;
226 unsigned long timestamp;
227 };
228
229 class InputEvent: public UserEvent {
230 public:
231 InputEvent(QWindow * w, ulong time, EventType t, Qt::KeyboardModifiers mods)
232 : UserEvent(w, time, t), modifiers(mods) {}
233 Qt::KeyboardModifiers modifiers;
234 };
235
236 class MouseEvent : public InputEvent {
237 public:
238 MouseEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global,
239 Qt::MouseButtons state, Qt::KeyboardModifiers mods,
240 Qt::MouseButton b, QEvent::Type type,
241 Qt::MouseEventSource src = Qt::MouseEventNotSynthesized, bool frame = false)
242 : InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(state),
243 source(src), nonClientArea(frame), button(b), buttonType(type) { }
244
245 // ### In Qt6 this method can be removed as there won't be need for compatibility code path
246 bool enhancedMouseEvent() const
247 {
248 static const bool disableEnhanced = qEnvironmentVariableIsSet("QT_QPA_DISABLE_ENHANCED_MOUSE");
249 return !disableEnhanced && buttonType != QEvent::None;
250 }
251
252 QPointF localPos;
253 QPointF globalPos;
254 Qt::MouseButtons buttons;
255 Qt::MouseEventSource source;
256 bool nonClientArea;
257 Qt::MouseButton button;
258 QEvent::Type buttonType;
259 };
260
261 class WheelEvent : public InputEvent {
262 public:
263 WheelEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O,
264 Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized, bool inverted = false);
265 QPoint pixelDelta;
266 QPoint angleDelta;
267 int qt4Delta;
268 Qt::Orientation qt4Orientation;
269 QPointF localPos;
270 QPointF globalPos;
271 Qt::ScrollPhase phase;
272 Qt::MouseEventSource source;
273 bool inverted;
274 };
275
276 class KeyEvent : public InputEvent {
277 public:
278 KeyEvent(QWindow *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
279 :InputEvent(w, time, Key, mods), key(k), unicode(text), repeat(autorep),
280 repeatCount(count), keyType(t),
281 nativeScanCode(0), nativeVirtualKey(0), nativeModifiers(0) { }
282 KeyEvent(QWindow *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods,
283 quint32 nativeSC, quint32 nativeVK, quint32 nativeMods,
284 const QString & text = QString(), bool autorep = false, ushort count = 1)
285 :InputEvent(w, time, Key, mods), key(k), unicode(text), repeat(autorep),
286 repeatCount(count), keyType(t),
287 nativeScanCode(nativeSC), nativeVirtualKey(nativeVK), nativeModifiers(nativeMods) { }
288 int key;
289 QString unicode;
290 bool repeat;
291 ushort repeatCount;
292 QEvent::Type keyType;
293 quint32 nativeScanCode;
294 quint32 nativeVirtualKey;
295 quint32 nativeModifiers;
296 };
297
298 class TouchEvent : public InputEvent {
299 public:
300 TouchEvent(QWindow *w, ulong time, QEvent::Type t, QTouchDevice *dev,
301 const QList<QTouchEvent::TouchPoint> &p, Qt::KeyboardModifiers mods)
302 :InputEvent(w, time, Touch, mods), device(dev), points(p), touchType(t) { }
303 QTouchDevice *device;
304 QList<QTouchEvent::TouchPoint> points;
305 QEvent::Type touchType;
306 };
307
308 class ScreenOrientationEvent : public WindowSystemEvent {
309 public:
310 ScreenOrientationEvent(QScreen *s, Qt::ScreenOrientation o)
311 : WindowSystemEvent(ScreenOrientation), screen(s), orientation(o) { }
312 QPointer<QScreen> screen;
313 Qt::ScreenOrientation orientation;
314 };
315
316 class ScreenGeometryEvent : public WindowSystemEvent {
317 public:
318 ScreenGeometryEvent(QScreen *s, const QRect &g, const QRect &ag)
319 : WindowSystemEvent(ScreenGeometry), screen(s), geometry(g), availableGeometry(ag) { }
320 QPointer<QScreen> screen;
321 QRect geometry;
322 QRect availableGeometry;
323 };
324
325 class ScreenLogicalDotsPerInchEvent : public WindowSystemEvent {
326 public:
327 ScreenLogicalDotsPerInchEvent(QScreen *s, qreal dx, qreal dy)
328 : WindowSystemEvent(ScreenLogicalDotsPerInch), screen(s), dpiX(dx), dpiY(dy) { }
329 QPointer<QScreen> screen;
330 qreal dpiX;
331 qreal dpiY;
332 };
333
334 class ScreenRefreshRateEvent : public WindowSystemEvent {
335 public:
336 ScreenRefreshRateEvent(QScreen *s, qreal r)
337 : WindowSystemEvent(ScreenRefreshRate), screen(s), rate(r) { }
338 QPointer<QScreen> screen;
339 qreal rate;
340 };
341
342 class ThemeChangeEvent : public WindowSystemEvent {
343 public:
344 explicit ThemeChangeEvent(QWindow * w)
345 : WindowSystemEvent(ThemeChange), window(w) { }
346 QPointer<QWindow> window;
347 };
348
349 class ExposeEvent : public WindowSystemEvent {
350 public:
351 ExposeEvent(QWindow *window, const QRegion &region);
352 QPointer<QWindow> window;
353 bool isExposed;
354 QRegion region;
355 };
356
357 class FileOpenEvent : public WindowSystemEvent {
358 public:
359 FileOpenEvent(const QString& fileName)
360 : WindowSystemEvent(FileOpen), url(QUrl::fromLocalFile(fileName))
361 { }
362 FileOpenEvent(const QUrl &url)
363 : WindowSystemEvent(FileOpen), url(url)
364 { }
365 QUrl url;
366 };
367
368 class Q_GUI_EXPORT TabletEvent : public InputEvent {
369 public:
370 static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
371 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
372 qreal tangentialPressure, qreal rotation, int z, qint64 uid,
373 Qt::KeyboardModifiers modifiers = Qt::NoModifier);
374 static void setPlatformSynthesizesMouse(bool v);
375
376 TabletEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global,
377 int device, int pointerType, Qt::MouseButtons b, qreal pressure, int xTilt, int yTilt, qreal tpressure,
378 qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers mods)
379 : InputEvent(w, time, Tablet, mods),
380 buttons(b), local(local), global(global), device(device), pointerType(pointerType),
381 pressure(pressure), xTilt(xTilt), yTilt(yTilt), tangentialPressure(tpressure),
382 rotation(rotation), z(z), uid(uid) { }
383 Qt::MouseButtons buttons;
384 QPointF local;
385 QPointF global;
386 int device;
387 int pointerType;
388 qreal pressure;
389 int xTilt;
390 int yTilt;
391 qreal tangentialPressure;
392 qreal rotation;
393 int z;
394 qint64 uid;
395 static bool platformSynthesizesMouse;
396 };
397
398 class TabletEnterProximityEvent : public InputEvent {
399 public:
400 TabletEnterProximityEvent(ulong time, int device, int pointerType, qint64 uid)
401 : InputEvent(nullptr, time, TabletEnterProximity, Qt::NoModifier),
402 device(device), pointerType(pointerType), uid(uid) { }
403 int device;
404 int pointerType;
405 qint64 uid;
406 };
407
408 class TabletLeaveProximityEvent : public InputEvent {
409 public:
410 TabletLeaveProximityEvent(ulong time, int device, int pointerType, qint64 uid)
411 : InputEvent(nullptr, time, TabletLeaveProximity, Qt::NoModifier),
412 device(device), pointerType(pointerType), uid(uid) { }
413 int device;
414 int pointerType;
415 qint64 uid;
416 };
417
418 class PlatformPanelEvent : public WindowSystemEvent {
419 public:
420 explicit PlatformPanelEvent(QWindow *w)
421 : WindowSystemEvent(PlatformPanel), window(w) { }
422 QPointer<QWindow> window;
423 };
424
425#ifndef QT_NO_CONTEXTMENU
426 class ContextMenuEvent : public WindowSystemEvent {
427 public:
428 explicit ContextMenuEvent(QWindow *w, bool mouseTriggered, const QPoint &pos,
429 const QPoint &globalPos, Qt::KeyboardModifiers modifiers)
430 : WindowSystemEvent(ContextMenu), window(w), mouseTriggered(mouseTriggered), pos(pos),
431 globalPos(globalPos), modifiers(modifiers) { }
432 QPointer<QWindow> window;
433 bool mouseTriggered;
434 QPoint pos; // Only valid if triggered by mouse
435 QPoint globalPos; // Only valid if triggered by mouse
436 Qt::KeyboardModifiers modifiers;
437 };
438#endif
439
440#ifndef QT_NO_GESTURES
441 class GestureEvent : public InputEvent {
442 public:
443 GestureEvent(QWindow *window, ulong time, Qt::NativeGestureType type, QTouchDevice *dev, QPointF pos, QPointF globalPos)
444 : InputEvent(window, time, Gesture, Qt::NoModifier), type(type), pos(pos), globalPos(globalPos),
445 realValue(0), sequenceId(0), intValue(0), device(dev) { }
446 Qt::NativeGestureType type;
447 QPointF pos;
448 QPointF globalPos;
449 // Mac
450 qreal realValue;
451 // Windows
452 ulong sequenceId;
453 quint64 intValue;
454 QTouchDevice *device;
455 };
456#endif
457
458 class WindowSystemEventList {
459 QList<WindowSystemEvent *> impl;
460 mutable QMutex mutex;
461 public:
462 WindowSystemEventList() : impl(), mutex() {}
463 ~WindowSystemEventList() { clear(); }
464
465 void clear()
466 { const QMutexLocker locker(&mutex); qDeleteAll(impl); impl.clear(); }
467 void prepend(WindowSystemEvent *e)
468 { const QMutexLocker locker(&mutex); impl.prepend(e); }
469 WindowSystemEvent *takeFirstOrReturnNull()
470 { const QMutexLocker locker(&mutex); return impl.empty() ? 0 : impl.takeFirst(); }
471 WindowSystemEvent *takeFirstNonUserInputOrReturnNull()
472 {
473 const QMutexLocker locker(&mutex);
474 for (int i = 0; i < impl.size(); ++i)
475 if (!(impl.at(i)->type & QWindowSystemInterfacePrivate::UserInputEvent))
476 return impl.takeAt(i);
477 return nullptr;
478 }
479 bool nonUserInputEventsQueued()
480 {
481 const QMutexLocker locker(&mutex);
482 for (int i = 0; i < impl.size(); ++i)
483 if (!(impl.at(i)->type & QWindowSystemInterfacePrivate::UserInputEvent))
484 return true;
485 return false;
486 }
487 void append(WindowSystemEvent *e)
488 { const QMutexLocker locker(&mutex); impl.append(e); }
489 int count() const
490 { const QMutexLocker locker(&mutex); return impl.count(); }
491 WindowSystemEvent *peekAtFirstOfType(EventType t) const
492 {
493 const QMutexLocker locker(&mutex);
494 for (int i = 0; i < impl.size(); ++i) {
495 if (impl.at(i)->type == t)
496 return impl.at(i);
497 }
498 return nullptr;
499 }
500 void remove(const WindowSystemEvent *e)
501 {
502 const QMutexLocker locker(&mutex);
503 for (int i = 0; i < impl.size(); ++i) {
504 if (impl.at(i) == e) {
505 delete impl.takeAt(i);
506 break;
507 }
508 }
509 }
510 private:
511 Q_DISABLE_COPY_MOVE(WindowSystemEventList)
512 };
513
514 static WindowSystemEventList windowSystemEventQueue;
515
516 static int windowSystemEventsQueued();
517 static bool nonUserInputEventsQueued();
518 static WindowSystemEvent *getWindowSystemEvent();
519 static WindowSystemEvent *getNonUserInputWindowSystemEvent();
520 static WindowSystemEvent *peekWindowSystemEvent(EventType t);
521 static void removeWindowSystemEvent(WindowSystemEvent *event);
522 template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
523 static bool handleWindowSystemEvent(WindowSystemEvent *ev);
524
525public:
526 static QElapsedTimer eventTime;
527 static bool synchronousWindowSystemEvents;
528 static bool platformFiltersEvents;
529
530 static QWaitCondition eventsFlushed;
531 static QMutex flushEventMutex;
532 static QAtomicInt eventAccepted;
533
534 static QList<QTouchEvent::TouchPoint>
535 fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
536 const QWindow *window, quint8 deviceId, QEvent::Type *type = nullptr);
537 static QList<QWindowSystemInterface::TouchPoint>
538 toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
539 const QWindow *window);
540 static void clearPointIdMap();
541
542 static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler);
543 static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler);
544 static QWindowSystemEventHandler *eventHandler;
545};
546
547class Q_GUI_EXPORT QWindowSystemEventHandler
548{
549public:
550 virtual ~QWindowSystemEventHandler();
551 virtual bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *event);
552};
553
554QT_END_NAMESPACE
555
556#endif // QWINDOWSYSTEMINTERFACE_P_H
557