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 FocusWindow = 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 FocusWindowEvent : public WindowSystemEvent {
129 public:
130 explicit FocusWindowEvent(QWindow *focusedWindow, Qt::FocusReason r)
131 : WindowSystemEvent(FocusWindow), focused(focusedWindow), reason(r)
132 { }
133 QPointer<QWindow> focused;
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 int evPtId = -1)
229 : PointerEvent(w, time, Mouse, mods, device), localPos(local), globalPos(global),
230 buttons(state), source(src), nonClientArea(frame), button(b), buttonType(type),
231 eventPointId(evPtId) { }
232
233 QPointF localPos;
234 QPointF globalPos;
235 Qt::MouseButtons buttons;
236 Qt::MouseEventSource source;
237 bool nonClientArea;
238 Qt::MouseButton button;
239 QEvent::Type buttonType;
240 int eventPointId; // from the original device if synth-mouse, otherwise -1
241 };
242
243 class WheelEvent : public PointerEvent {
244 public:
245 WheelEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O,
246 Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized,
247 bool inverted = false, const QPointingDevice *device = QPointingDevice::primaryPointingDevice())
248 : PointerEvent(w, time, Wheel, mods, device), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D),
249 qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src), inverted(inverted) { }
250 QPoint pixelDelta;
251 QPoint angleDelta;
252 int qt4Delta;
253 Qt::Orientation qt4Orientation;
254 QPointF localPos;
255 QPointF globalPos;
256 Qt::ScrollPhase phase;
257 Qt::MouseEventSource source;
258 bool inverted;
259 };
260
261 class KeyEvent : public InputEvent {
262 public:
263 KeyEvent(QWindow *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods,
264 const QString & text = QString(), bool autorep = false, ushort count = 1,
265 const QInputDevice *device = QInputDevice::primaryKeyboard())
266 : InputEvent(w, time, Key, mods, device), source(nullptr), key(k), unicode(text),
267 repeat(autorep), repeatCount(count), keyType(t),
268 nativeScanCode(0), nativeVirtualKey(0), nativeModifiers(0) { }
269 KeyEvent(QWindow *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods,
270 quint32 nativeSC, quint32 nativeVK, quint32 nativeMods,
271 const QString & text = QString(), bool autorep = false, ushort count = 1,
272 const QInputDevice *device = QInputDevice::primaryKeyboard())
273 : InputEvent(w, time, Key, mods, device), source(nullptr), key(k), unicode(text),
274 repeat(autorep), repeatCount(count), keyType(t),
275 nativeScanCode(nativeSC), nativeVirtualKey(nativeVK), nativeModifiers(nativeMods) { }
276 const QInputDevice *source;
277 int key;
278 QString unicode;
279 bool repeat;
280 ushort repeatCount;
281 QEvent::Type keyType;
282 quint32 nativeScanCode;
283 quint32 nativeVirtualKey;
284 quint32 nativeModifiers;
285 };
286
287 class TouchEvent : public PointerEvent {
288 public:
289 TouchEvent(QWindow *w, ulong time, QEvent::Type t, const QPointingDevice *device,
290 const QList<QEventPoint> &p, Qt::KeyboardModifiers mods)
291 : PointerEvent(w, time, Touch, mods, device), points(p), touchType(t) { }
292 QList<QEventPoint> points;
293 QEvent::Type touchType;
294 };
295
296 class ScreenOrientationEvent : public WindowSystemEvent {
297 public:
298 ScreenOrientationEvent(QScreen *s, Qt::ScreenOrientation o)
299 : WindowSystemEvent(ScreenOrientation), screen(s), orientation(o) { }
300 QPointer<QScreen> screen;
301 Qt::ScreenOrientation orientation;
302 };
303
304 class ScreenGeometryEvent : public WindowSystemEvent {
305 public:
306 ScreenGeometryEvent(QScreen *s, const QRect &g, const QRect &ag)
307 : WindowSystemEvent(ScreenGeometry), screen(s), geometry(g), availableGeometry(ag) { }
308 QPointer<QScreen> screen;
309 QRect geometry;
310 QRect availableGeometry;
311 };
312
313 class ScreenLogicalDotsPerInchEvent : public WindowSystemEvent {
314 public:
315 ScreenLogicalDotsPerInchEvent(QScreen *s, qreal dx, qreal dy)
316 : WindowSystemEvent(ScreenLogicalDotsPerInch), screen(s), dpiX(dx), dpiY(dy) { }
317 QPointer<QScreen> screen;
318 qreal dpiX;
319 qreal dpiY;
320 };
321
322 class ScreenRefreshRateEvent : public WindowSystemEvent {
323 public:
324 ScreenRefreshRateEvent(QScreen *s, qreal r)
325 : WindowSystemEvent(ScreenRefreshRate), screen(s), rate(r) { }
326 QPointer<QScreen> screen;
327 qreal rate;
328 };
329
330 class ThemeChangeEvent : public WindowSystemEvent {
331 public:
332 explicit ThemeChangeEvent(QWindow * w)
333 : WindowSystemEvent(ThemeChange), window(w) { }
334 QPointer<QWindow> window;
335 };
336
337 class ExposeEvent : public WindowSystemEvent {
338 public:
339 ExposeEvent(QWindow *window, const QRegion &region);
340 QPointer<QWindow> window;
341 bool isExposed;
342 QRegion region;
343 };
344
345 class PaintEvent : public WindowSystemEvent {
346 public:
347 PaintEvent(QWindow *window, const QRegion &region)
348 : WindowSystemEvent(Paint), window(window), region(region) {}
349 QPointer<QWindow> window;
350 QRegion region;
351 };
352
353 class FileOpenEvent : public WindowSystemEvent {
354 public:
355 FileOpenEvent(const QString& fileName)
356 : WindowSystemEvent(FileOpen), url(QUrl::fromLocalFile(localfile: fileName))
357 { }
358 FileOpenEvent(const QUrl &url)
359 : WindowSystemEvent(FileOpen), url(url)
360 { }
361 QUrl url;
362 };
363
364 class Q_GUI_EXPORT TabletEvent : public PointerEvent {
365 public:
366 // TODO take QPointingDevice* instead of types and IDs
367 static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
368 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
369 qreal tangentialPressure, qreal rotation, int z, qint64 uid,
370 Qt::KeyboardModifiers modifiers = Qt::NoModifier);
371 static void setPlatformSynthesizesMouse(bool v);
372
373 TabletEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global,
374 const QPointingDevice *device, Qt::MouseButtons b, qreal pressure, int xTilt, int yTilt, qreal tpressure,
375 qreal rotation, int z, Qt::KeyboardModifiers mods)
376 : PointerEvent(w, time, Tablet, mods, device),
377 buttons(b), local(local), global(global),
378 pressure(pressure), xTilt(xTilt), yTilt(yTilt), tangentialPressure(tpressure),
379 rotation(rotation), z(z) { }
380 Qt::MouseButtons buttons;
381 QPointF local;
382 QPointF global;
383 qreal pressure;
384 int xTilt;
385 int yTilt;
386 qreal tangentialPressure;
387 qreal rotation;
388 int z;
389 static bool platformSynthesizesMouse;
390 };
391
392 class TabletEnterProximityEvent : public PointerEvent {
393 public:
394 // TODO store more info: position and whatever else we can get on most platforms
395 TabletEnterProximityEvent(ulong time, const QPointingDevice *device)
396 : PointerEvent(nullptr, time, TabletEnterProximity, Qt::NoModifier, device) { }
397 };
398
399 class TabletLeaveProximityEvent : public PointerEvent {
400 public:
401 // TODO store more info: position and whatever else we can get on most platforms
402 TabletLeaveProximityEvent(ulong time, const QPointingDevice *device)
403 : PointerEvent(nullptr, time, TabletLeaveProximity, Qt::NoModifier, device) { }
404 };
405
406 class PlatformPanelEvent : public WindowSystemEvent {
407 public:
408 explicit PlatformPanelEvent(QWindow *w)
409 : WindowSystemEvent(PlatformPanel), window(w) { }
410 QPointer<QWindow> window;
411 };
412
413#ifndef QT_NO_CONTEXTMENU
414 class ContextMenuEvent : public WindowSystemEvent {
415 public:
416 explicit ContextMenuEvent(QWindow *w, bool mouseTriggered, const QPoint &pos,
417 const QPoint &globalPos, Qt::KeyboardModifiers modifiers)
418 : WindowSystemEvent(ContextMenu), window(w), mouseTriggered(mouseTriggered), pos(pos),
419 globalPos(globalPos), modifiers(modifiers) { }
420 QPointer<QWindow> window;
421 bool mouseTriggered;
422 QPoint pos; // Only valid if triggered by mouse
423 QPoint globalPos; // Only valid if triggered by mouse
424 Qt::KeyboardModifiers modifiers;
425 };
426#endif
427
428#ifndef QT_NO_GESTURES
429 class GestureEvent : public PointerEvent {
430 public:
431 GestureEvent(QWindow *window, ulong time, Qt::NativeGestureType type, const QPointingDevice *dev,
432 int fingerCount, QPointF pos, QPointF globalPos, qreal realValue, QPointF delta)
433 : PointerEvent(window, time, Gesture, Qt::NoModifier, dev), type(type), pos(pos), globalPos(globalPos),
434 delta(delta), fingerCount(fingerCount), realValue(realValue), sequenceId(0), intValue(0) { }
435 Qt::NativeGestureType type;
436 QPointF pos;
437 QPointF globalPos;
438 QPointF delta;
439 int fingerCount;
440 // Mac
441 qreal realValue;
442 // Windows
443 ulong sequenceId;
444 quint64 intValue;
445 };
446#endif
447
448 class WindowSystemEventList {
449 QList<WindowSystemEvent *> impl;
450 mutable QMutex mutex;
451 public:
452 WindowSystemEventList() : impl(), mutex() {}
453 ~WindowSystemEventList() { clear(); }
454
455 void clear()
456 { const QMutexLocker locker(&mutex); qDeleteAll(c: impl); impl.clear(); }
457 void prepend(WindowSystemEvent *e)
458 { const QMutexLocker locker(&mutex); impl.prepend(t: e); }
459 WindowSystemEvent *takeFirstOrReturnNull()
460 { const QMutexLocker locker(&mutex); return impl.empty() ? nullptr : impl.takeFirst(); }
461 WindowSystemEvent *takeFirstNonUserInputOrReturnNull()
462 {
463 const QMutexLocker locker(&mutex);
464 for (int i = 0; i < impl.size(); ++i)
465 if (!(impl.at(i)->type & QWindowSystemInterfacePrivate::UserInputEvent))
466 return impl.takeAt(i);
467 return nullptr;
468 }
469 bool nonUserInputEventsQueued()
470 {
471 const QMutexLocker locker(&mutex);
472 for (int i = 0; i < impl.size(); ++i)
473 if (!(impl.at(i)->type & QWindowSystemInterfacePrivate::UserInputEvent))
474 return true;
475 return false;
476 }
477 void append(WindowSystemEvent *e)
478 { const QMutexLocker locker(&mutex); impl.append(t: e); }
479 qsizetype count() const
480 { const QMutexLocker locker(&mutex); return impl.size(); }
481 WindowSystemEvent *peekAtFirstOfType(EventType t) const
482 {
483 const QMutexLocker locker(&mutex);
484 for (int i = 0; i < impl.size(); ++i) {
485 if (impl.at(i)->type == t)
486 return impl.at(i);
487 }
488 return nullptr;
489 }
490 void remove(const WindowSystemEvent *e)
491 {
492 const QMutexLocker locker(&mutex);
493 for (int i = 0; i < impl.size(); ++i) {
494 if (impl.at(i) == e) {
495 delete impl.takeAt(i);
496 break;
497 }
498 }
499 }
500 private:
501 Q_DISABLE_COPY_MOVE(WindowSystemEventList)
502 };
503
504 static WindowSystemEventList windowSystemEventQueue;
505
506 static qsizetype windowSystemEventsQueued();
507 static bool nonUserInputEventsQueued();
508 static WindowSystemEvent *getWindowSystemEvent();
509 static WindowSystemEvent *getNonUserInputWindowSystemEvent();
510 static WindowSystemEvent *peekWindowSystemEvent(EventType t);
511 static void removeWindowSystemEvent(WindowSystemEvent *event);
512
513public:
514 static QElapsedTimer eventTime;
515 static bool synchronousWindowSystemEvents;
516 static bool platformFiltersEvents;
517
518 static QWaitCondition eventsFlushed;
519 static QMutex flushEventMutex;
520 static QAtomicInt eventAccepted;
521
522 static QList<QEventPoint>
523 fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
524 const QWindow *window, QEvent::Type *type = nullptr);
525 template<class EventPointList>
526 static QList<QWindowSystemInterface::TouchPoint>
527 toNativeTouchPoints(const EventPointList &pointList, const QWindow *window)
528 {
529 QList<QWindowSystemInterface::TouchPoint> newList;
530 newList.reserve(size: pointList.size());
531 for (const auto &point : pointList) {
532 newList.append(toNativeTouchPoint(point, window));
533 }
534 return newList;
535 }
536 static QWindowSystemInterface::TouchPoint
537 toNativeTouchPoint(const QEventPoint &point, const QWindow *window);
538
539 static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler);
540 static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler);
541 static QWindowSystemEventHandler *eventHandler;
542};
543
544class Q_GUI_EXPORT QWindowSystemEventHandler
545{
546public:
547 virtual ~QWindowSystemEventHandler();
548 virtual bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *event);
549};
550
551QT_END_NAMESPACE
552
553#endif // QWINDOWSYSTEMINTERFACE_P_H
554

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