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 | |
4 | #ifndef QGUIAPPLICATION_P_H |
5 | #define QGUIAPPLICATION_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtGui/private/qtguiglobal_p.h> |
19 | #include <QtGui/qguiapplication.h> |
20 | #include <QtGui/qicon.h> |
21 | |
22 | #include <QtCore/QHash> |
23 | #include <QtCore/QPointF> |
24 | #include <QtCore/private/qcoreapplication_p.h> |
25 | |
26 | #include <QtCore/qnativeinterface.h> |
27 | #include <QtCore/private/qnativeinterface_p.h> |
28 | #include <QtCore/private/qnumeric_p.h> |
29 | #include <QtCore/private/qthread_p.h> |
30 | |
31 | #include <qpa/qwindowsysteminterface.h> |
32 | #include <qpa/qwindowsysteminterface_p.h> |
33 | #if QT_CONFIG(shortcut) |
34 | # include "private/qshortcutmap_p.h" |
35 | #endif |
36 | |
37 | #include <memory> |
38 | |
39 | QT_BEGIN_NAMESPACE |
40 | |
41 | class QColorTrcLut; |
42 | class QPlatformIntegration; |
43 | class QPlatformTheme; |
44 | class QPlatformDragQtResponse; |
45 | #if QT_CONFIG(draganddrop) |
46 | class QDrag; |
47 | #endif // QT_CONFIG(draganddrop) |
48 | class QInputDeviceManager; |
49 | #ifndef QT_NO_ACTION |
50 | class QActionPrivate; |
51 | #endif |
52 | #if QT_CONFIG(shortcut) |
53 | class QShortcutPrivate; |
54 | #endif |
55 | |
56 | class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate |
57 | { |
58 | Q_DECLARE_PUBLIC(QGuiApplication) |
59 | public: |
60 | QGuiApplicationPrivate(int &argc, char **argv); |
61 | ~QGuiApplicationPrivate(); |
62 | |
63 | void init(); |
64 | |
65 | void createPlatformIntegration(); |
66 | void createEventDispatcher() override; |
67 | void eventDispatcherReady() override; |
68 | |
69 | virtual void notifyLayoutDirectionChange(); |
70 | virtual void notifyActiveWindowChange(QWindow *previous); |
71 | |
72 | #if QT_CONFIG(commandlineparser) |
73 | void addQtOptions(QList<QCommandLineOption> *options) override; |
74 | #endif |
75 | bool canQuitAutomatically() override; |
76 | void quit() override; |
77 | |
78 | void maybeLastWindowClosed(); |
79 | bool lastWindowClosed() const; |
80 | static bool quitOnLastWindowClosed; |
81 | |
82 | static void captureGlobalModifierState(QEvent *e); |
83 | static Qt::KeyboardModifiers modifier_buttons; |
84 | static Qt::MouseButtons mouse_buttons; |
85 | |
86 | static QPlatformIntegration *platform_integration; |
87 | |
88 | static QPlatformIntegration *platformIntegration() |
89 | { return platform_integration; } |
90 | |
91 | static QPlatformTheme *platform_theme; |
92 | |
93 | static QPlatformTheme *platformTheme() |
94 | { return platform_theme; } |
95 | |
96 | static QAbstractEventDispatcher *qt_qpa_core_dispatcher() |
97 | { |
98 | if (QCoreApplication::instance()) |
99 | return QCoreApplication::instance()->d_func()->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); |
100 | else |
101 | return nullptr; |
102 | } |
103 | |
104 | static void processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e); |
105 | static void processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e); |
106 | static void processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e); |
107 | static void processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e); |
108 | |
109 | static void processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e); |
110 | |
111 | static void processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e); |
112 | |
113 | static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e); |
114 | static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e); |
115 | |
116 | static void processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e); |
117 | static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e); |
118 | static void processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e); |
119 | static void processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *e); |
120 | |
121 | static void processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e); |
122 | |
123 | static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); |
124 | |
125 | static void processApplicationTermination(QWindowSystemInterfacePrivate::WindowSystemEvent *e); |
126 | |
127 | static void updateFilteredScreenOrientation(QScreen *screen); |
128 | static void processScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); |
129 | static void processScreenGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); |
130 | static void processScreenLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e); |
131 | static void processScreenRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e); |
132 | static void processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce); |
133 | |
134 | static void processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e); |
135 | static void processPaintEvent(QWindowSystemInterfacePrivate::PaintEvent *e); |
136 | |
137 | static void processFileOpenEvent(QWindowSystemInterfacePrivate::FileOpenEvent *e); |
138 | |
139 | static void processTabletEvent(QWindowSystemInterfacePrivate::TabletEvent *e); |
140 | static void processTabletEnterProximityEvent(QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e); |
141 | static void processTabletLeaveProximityEvent(QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e); |
142 | |
143 | #ifndef QT_NO_GESTURES |
144 | static void processGestureEvent(QWindowSystemInterfacePrivate::GestureEvent *e); |
145 | #endif |
146 | |
147 | static void processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e); |
148 | #ifndef QT_NO_CONTEXTMENU |
149 | static void (QWindowSystemInterfacePrivate::ContextMenuEvent *e); |
150 | #endif |
151 | |
152 | #if QT_CONFIG(draganddrop) |
153 | static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, |
154 | const QPoint &p, Qt::DropActions supportedActions, |
155 | Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); |
156 | static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, |
157 | const QPoint &p, Qt::DropActions supportedActions, |
158 | Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); |
159 | #endif |
160 | |
161 | static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result); |
162 | |
163 | static bool sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event); |
164 | |
165 | static inline Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment) |
166 | { |
167 | if (!(alignment & Qt::AlignHorizontal_Mask)) |
168 | alignment |= Qt::AlignLeft; |
169 | if (!(alignment & Qt::AlignAbsolute) && (alignment & (Qt::AlignLeft | Qt::AlignRight))) { |
170 | if (direction == Qt::RightToLeft) |
171 | alignment ^= (Qt::AlignLeft | Qt::AlignRight); |
172 | alignment |= Qt::AlignAbsolute; |
173 | } |
174 | return alignment; |
175 | } |
176 | |
177 | QPixmap getPixmapCursor(Qt::CursorShape cshape); |
178 | |
179 | void _q_updateFocusObject(QObject *object); |
180 | |
181 | static QGuiApplicationPrivate *instance() { return self; } |
182 | |
183 | static QIcon *app_icon; |
184 | static QString *platform_name; |
185 | static QString *displayName; |
186 | static QString *desktopFileName; |
187 | |
188 | QWindowList modalWindowList; |
189 | static void showModalWindow(QWindow *window); |
190 | static void hideModalWindow(QWindow *window); |
191 | static void updateBlockedStatus(QWindow *window); |
192 | |
193 | virtual Qt::WindowModality defaultModality() const; |
194 | virtual bool windowNeverBlocked(QWindow *window) const; |
195 | bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const; |
196 | virtual bool () { return false; } |
197 | virtual bool () { return false; } |
198 | |
199 | static Qt::MouseButton mousePressButton; |
200 | static struct QLastCursorPosition { |
201 | constexpr inline QLastCursorPosition() noexcept : thePoint(qt_inf(), qt_inf()) {} |
202 | constexpr inline Q_IMPLICIT QLastCursorPosition(QPointF p) noexcept : thePoint(p) {} |
203 | constexpr inline Q_IMPLICIT operator QPointF() const noexcept { return thePoint; } |
204 | constexpr inline qreal x() const noexcept{ return thePoint.x(); } |
205 | constexpr inline qreal y() const noexcept{ return thePoint.y(); } |
206 | Q_GUI_EXPORT QPoint toPoint() const noexcept; |
207 | |
208 | constexpr void reset() noexcept { *this = QLastCursorPosition{}; } |
209 | |
210 | // QGuiApplicationPrivate::lastCursorPosition is used for mouse-move detection |
211 | // but even QPointF's qFuzzCompare on doubles is too precise, and causes move-noise |
212 | // e.g. on macOS (see QTBUG-111170). So we specialize the equality operators here |
213 | // to use single-point precision. |
214 | friend constexpr bool operator==(const QLastCursorPosition &p1, const QPointF &p2) noexcept |
215 | { |
216 | return qFuzzyCompare(p1: float(p1.x()), p2: float(p2.x())) |
217 | && qFuzzyCompare(p1: float(p1.y()), p2: float(p2.y())); |
218 | } |
219 | friend constexpr bool operator!=(const QLastCursorPosition &p1, const QPointF &p2) noexcept |
220 | { |
221 | return !(p1 == p2); |
222 | } |
223 | friend constexpr bool operator==(const QPointF &p1, const QLastCursorPosition &p2) noexcept |
224 | { |
225 | return p2 == p1; |
226 | } |
227 | friend constexpr bool operator!=(const QPointF &p1, const QLastCursorPosition &p2) noexcept |
228 | { |
229 | return !(p2 == p1); |
230 | } |
231 | |
232 | private: |
233 | QPointF thePoint; |
234 | } lastCursorPosition; |
235 | static QWindow *currentMouseWindow; |
236 | static QWindow *currentMousePressWindow; |
237 | static Qt::ApplicationState applicationState; |
238 | static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy; |
239 | static QPointer<QWindow> currentDragWindow; |
240 | |
241 | // TODO remove this: QPointingDevice can store what we need directly |
242 | struct TabletPointData { |
243 | TabletPointData(qint64 devId = 0) : deviceId(devId), state(Qt::NoButton), target(nullptr) {} |
244 | qint64 deviceId; |
245 | Qt::MouseButtons state; |
246 | QWindow *target; |
247 | }; |
248 | static QList<TabletPointData> tabletDevicePoints; |
249 | static TabletPointData &tabletDevicePoint(qint64 deviceId); |
250 | |
251 | #ifndef QT_NO_CLIPBOARD |
252 | static QClipboard *qt_clipboard; |
253 | #endif |
254 | |
255 | static QPalette *app_pal; |
256 | |
257 | static QWindowList window_list; |
258 | static QWindow *focus_window; |
259 | |
260 | #ifndef QT_NO_CURSOR |
261 | QList<QCursor> cursor_list; |
262 | #endif |
263 | static QList<QScreen *> screen_list; |
264 | |
265 | static QFont *app_font; |
266 | |
267 | static QString styleOverride; |
268 | static QStyleHints *styleHints; |
269 | static bool obey_desktop_settings; |
270 | QInputMethod *inputMethod; |
271 | |
272 | QString firstWindowTitle; |
273 | QIcon forcedWindowIcon; |
274 | |
275 | static QList<QObject *> generic_plugin_list; |
276 | #if QT_CONFIG(shortcut) |
277 | QShortcutMap shortcutMap; |
278 | #endif |
279 | |
280 | #ifndef QT_NO_SESSIONMANAGER |
281 | QSessionManager *session_manager; |
282 | bool is_session_restored; |
283 | bool is_saving_session; |
284 | void commitData(); |
285 | void saveState(); |
286 | #endif |
287 | |
288 | QEvent::Type lastTouchType; |
289 | struct SynthesizedMouseData { |
290 | SynthesizedMouseData(const QPointF &p, const QPointF &sp, QWindow *w) |
291 | : pos(p), screenPos(sp), window(w) { } |
292 | QPointF pos; |
293 | QPointF screenPos; |
294 | QPointer<QWindow> window; |
295 | }; |
296 | QHash<QWindow *, SynthesizedMouseData> synthesizedMousePoints; |
297 | |
298 | static QInputDeviceManager *inputDeviceManager(); |
299 | |
300 | const QColorTrcLut *colorProfileForA8Text(); |
301 | const QColorTrcLut *colorProfileForA32Text(); |
302 | |
303 | // hook reimplemented in QApplication to apply the QStyle function on the QIcon |
304 | virtual QPixmap applyQIconStyleHelper(QIcon::Mode, const QPixmap &basePixmap) const { return basePixmap; } |
305 | |
306 | virtual void notifyWindowIconChanged(); |
307 | |
308 | static void applyWindowGeometrySpecificationTo(QWindow *window); |
309 | |
310 | static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false); |
311 | |
312 | static void resetCachedDevicePixelRatio(); |
313 | |
314 | #ifndef QT_NO_ACTION |
315 | virtual QActionPrivate *createActionPrivate() const; |
316 | #endif |
317 | #ifndef QT_NO_SHORTCUT |
318 | virtual QShortcutPrivate *createShortcutPrivate() const; |
319 | #endif |
320 | |
321 | static void updatePalette(); |
322 | |
323 | static Qt::ColorScheme colorScheme(); |
324 | |
325 | protected: |
326 | virtual void handleThemeChanged(); |
327 | |
328 | static bool setPalette(const QPalette &palette); |
329 | virtual QPalette basePalette() const; |
330 | virtual void handlePaletteChanged(const char *className = nullptr); |
331 | |
332 | #if QT_CONFIG(draganddrop) |
333 | virtual void notifyDragStarted(const QDrag *); |
334 | #endif // QT_CONFIG(draganddrop) |
335 | |
336 | private: |
337 | static void clearPalette(); |
338 | |
339 | friend class QDragManager; |
340 | |
341 | static QGuiApplicationPrivate *self; |
342 | static int m_fakeMouseSourcePointId; |
343 | #ifdef Q_OS_WIN |
344 | std::shared_ptr<QColorTrcLut> m_a8ColorProfile; |
345 | #endif |
346 | std::shared_ptr<QColorTrcLut> m_a32ColorProfile; |
347 | |
348 | bool ownGlobalShareContext; |
349 | |
350 | static QInputDeviceManager *m_inputDeviceManager; |
351 | |
352 | // Cache the maximum device pixel ratio, to iterate through the screen list |
353 | // only the first time it's required, or when devices are added or removed. |
354 | static qreal m_maxDevicePixelRatio; |
355 | }; |
356 | |
357 | // ----------------- QNativeInterface ----------------- |
358 | |
359 | class QWindowsMimeConverter; |
360 | |
361 | namespace QNativeInterface::Private { |
362 | |
363 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
364 | |
365 | |
366 | struct Q_GUI_EXPORT QWindowsApplication |
367 | { |
368 | QT_DECLARE_NATIVE_INTERFACE(QWindowsApplication, 1, QGuiApplication) |
369 | |
370 | enum WindowActivationBehavior { |
371 | DefaultActivateWindow, |
372 | AlwaysActivateWindow |
373 | }; |
374 | |
375 | enum TouchWindowTouchType { |
376 | NormalTouch = 0x00000000, |
377 | FineTouch = 0x00000001, |
378 | WantPalmTouch = 0x00000002 |
379 | }; |
380 | |
381 | Q_DECLARE_FLAGS(TouchWindowTouchTypes, TouchWindowTouchType) |
382 | |
383 | enum DarkModeHandlingFlag { |
384 | DarkModeWindowFrames = 0x1, |
385 | DarkModeStyle = 0x2 |
386 | }; |
387 | |
388 | Q_DECLARE_FLAGS(DarkModeHandling, DarkModeHandlingFlag) |
389 | |
390 | virtual void setTouchWindowTouchType(TouchWindowTouchTypes type) = 0; |
391 | virtual TouchWindowTouchTypes touchWindowTouchType() const = 0; |
392 | |
393 | virtual WindowActivationBehavior windowActivationBehavior() const = 0; |
394 | virtual void setWindowActivationBehavior(WindowActivationBehavior behavior) = 0; |
395 | |
396 | virtual void setHasBorderInFullScreenDefault(bool border) = 0; |
397 | |
398 | virtual bool isTabletMode() const = 0; |
399 | |
400 | virtual bool isWinTabEnabled() const = 0; |
401 | virtual bool setWinTabEnabled(bool enabled) = 0; |
402 | |
403 | virtual bool isDarkMode() const = 0; |
404 | |
405 | virtual DarkModeHandling darkModeHandling() const = 0; |
406 | virtual void setDarkModeHandling(DarkModeHandling handling) = 0; |
407 | |
408 | virtual void registerMime(QWindowsMimeConverter *mime) = 0; |
409 | virtual void unregisterMime(QWindowsMimeConverter *mime) = 0; |
410 | |
411 | virtual int registerMimeType(const QString &mime) = 0; |
412 | |
413 | virtual HWND createMessageWindow(const QString &classNameTemplate, |
414 | const QString &windowName, |
415 | QFunctionPointer eventProc = nullptr) const = 0; |
416 | |
417 | virtual bool asyncExpose() const = 0; // internal, used by Active Qt |
418 | virtual void setAsyncExpose(bool value) = 0; |
419 | |
420 | virtual QVariant gpu() const = 0; // internal, used by qtdiag |
421 | virtual QVariant gpuList() const = 0; |
422 | |
423 | virtual void populateLightSystemPalette(QPalette &pal) const = 0; |
424 | }; |
425 | #endif // Q_OS_WIN |
426 | |
427 | } // QNativeInterface::Private |
428 | |
429 | #if defined(Q_OS_WIN) |
430 | Q_DECLARE_OPERATORS_FOR_FLAGS(QNativeInterface::Private::QWindowsApplication::TouchWindowTouchTypes) |
431 | Q_DECLARE_OPERATORS_FOR_FLAGS(QNativeInterface::Private::QWindowsApplication::DarkModeHandling) |
432 | #endif |
433 | |
434 | QT_END_NAMESPACE |
435 | |
436 | #endif // QGUIAPPLICATION_P_H |
437 | |