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

source code of qtbase/src/gui/kernel/qwindowsysteminterface_p.h