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 plugins 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 
40 #ifndef QWINDOWSCONTEXT_H
41 #define QWINDOWSCONTEXT_H
42 
43 #include "qtwindowsglobal.h"
44 #include <QtCore/qt_windows.h>
45 
46 #include <QtCore/qscopedpointer.h>
47 #include <QtCore/qsharedpointer.h>
48 #include <QtCore/qloggingcategory.h>
49 
50 #define STRICT_TYPED_ITEMIDS
51 #include <shlobj.h>
52 #include <shlwapi.h>
53 
54 struct IBindCtx;
55 struct _SHSTOCKICONINFO;
56 
57 QT_BEGIN_NAMESPACE
58 
59 Q_DECLARE_LOGGING_CATEGORY(lcQpaWindows)
60 Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
61 Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
62 Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
63 Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods)
64 Q_DECLARE_LOGGING_CATEGORY(lcQpaDialogs)
65 Q_DECLARE_LOGGING_CATEGORY(lcQpaMenus)
66 Q_DECLARE_LOGGING_CATEGORY(lcQpaTablet)
67 Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility)
68 Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation)
69 Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon)
70 
71 class QWindow;
72 class QPlatformScreen;
73 class QPlatformWindow;
74 class QWindowsMenuBar;
75 class QWindowsScreenManager;
76 class QWindowsTabletSupport;
77 class QWindowsWindow;
78 class QWindowsMimeConverter;
79 struct QWindowCreationContext;
80 struct QWindowsContextPrivate;
81 class QPoint;
82 class QKeyEvent;
83 class QTouchDevice;
84 
85 struct QWindowsUser32DLL
86 {
87     inline void init();
88     inline bool supportsPointerApi();
89 
90     typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
91     typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
92     typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
93     typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
94     typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
95     typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
96     typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
97     typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
98     typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
99     typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
100     typedef BOOL (WINAPI *SetProcessDPIAware)();
101     typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
102     typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
103     typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
104     typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
105     typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
106     typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
107     typedef int  (WINAPI *GetWindowDpiAwarenessContext)(HWND);
108     typedef int  (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
109     typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
110 
111     // Windows pointer functions (Windows 8 or later).
112     EnableMouseInPointer enableMouseInPointer = nullptr;
113     GetPointerType getPointerType = nullptr;
114     GetPointerInfo getPointerInfo = nullptr;
115     GetPointerDeviceRects getPointerDeviceRects = nullptr;
116     GetPointerTouchInfo getPointerTouchInfo = nullptr;
117     GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
118     GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
119     GetPointerPenInfo getPointerPenInfo = nullptr;
120     GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
121     SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
122 
123     // Windows Vista onwards
124     SetProcessDPIAware setProcessDPIAware = nullptr;
125 
126     // Clipboard listeners are present on Windows Vista onwards
127     // but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
128     AddClipboardFormatListener addClipboardFormatListener = nullptr;
129     RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
130 
131     // Rotation API
132     GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
133     SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
134 
135     AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
136     EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
137     GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
138     GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
139     SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
140 };
141 
142 // Shell scaling library (Windows 8.1 onwards)
143 struct QWindowsShcoreDLL {
144     void init();
isValidQWindowsShcoreDLL145     inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
146 
147     typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int *);
148     typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
149     typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
150 
151     GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
152     SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
153     GetDpiForMonitor getDpiForMonitor = nullptr;
154 };
155 
156 class QWindowsContext
157 {
158     Q_DISABLE_COPY_MOVE(QWindowsContext)
159 public:
160 
161     enum SystemInfoFlags
162     {
163         SI_RTL_Extensions = 0x1,
164         SI_SupportsTouch = 0x2,
165         SI_SupportsPointer = 0x4,
166     };
167 
168     // Verbose flag set by environment variable QT_QPA_VERBOSE
169     static int verbose;
170 
171     explicit QWindowsContext();
172     ~QWindowsContext();
173 
174     bool initTouch();
175     bool initTouch(unsigned integrationOptions); // For calls from QWindowsIntegration::QWindowsIntegration() only.
176     bool initTablet(unsigned integrationOptions);
177     bool initPointer(unsigned integrationOptions);
178 
179     bool initPowerNotificationHandler();
180 
181     int defaultDPI() const;
182 
183     static QString classNamePrefix();
184     QString registerWindowClass(const QWindow *w);
185     QString registerWindowClass(QString cname, WNDPROC proc,
186                                 unsigned style = 0, HBRUSH brush = nullptr,
187                                 bool icon = false);
188     HWND createDummyWindow(const QString &classNameIn,
189                            const wchar_t *windowName,
190                            WNDPROC wndProc = nullptr, DWORD style = WS_OVERLAPPED);
191 
192     HDC displayContext() const;
193     int screenDepth() const;
194 
195     static QWindowsContext *instance();
196 
197     static QString windowsErrorMessage(unsigned long errorCode);
198 
199     void addWindow(HWND, QWindowsWindow *w);
200     void removeWindow(HWND);
201 
202     QWindowsWindow *findClosestPlatformWindow(HWND) const;
203     QWindowsWindow *findPlatformWindow(HWND) const;
204     QWindowsWindow *findPlatformWindow(const QWindowsMenuBar *mb) const;
205     QWindow *findWindow(HWND) const;
206     QWindowsWindow *findPlatformWindowAt(HWND parent, const QPoint &screenPoint,
207                                              unsigned cwex_flags) const;
208 
209     static bool shouldHaveNonClientDpiScaling(const QWindow *window);
210 
211     QWindow *windowUnderMouse() const;
212     void clearWindowUnderMouse();
213 
214     inline bool windowsProc(HWND hwnd, UINT message,
215                             QtWindows::WindowsEventType et,
216                             WPARAM wParam, LPARAM lParam, LRESULT *result,
217                             QWindowsWindow **platformWindowPtr);
218 
219     QWindow *keyGrabber() const;
220     void setKeyGrabber(QWindow *hwnd);
221 
222     QSharedPointer<QWindowCreationContext> setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
223     QSharedPointer<QWindowCreationContext> windowCreationContext() const;
224 
225     void setTabletAbsoluteRange(int a);
226     void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
227     static int processDpiAwareness();
228 
229     static bool isDarkMode();
230 
231     void setDetectAltGrModifier(bool a);
232 
233     // Returns a combination of SystemInfoFlags
234     unsigned systemInfo() const;
235 
236     bool useRTLExtensions() const;
237     QList<int> possibleKeys(const QKeyEvent *e) const;
238 
239     static bool isSessionLocked();
240 
241     QWindowsMimeConverter &mimeConverter() const;
242     QWindowsScreenManager &screenManager();
243     QWindowsTabletSupport *tabletSupport() const;
244 
245     static QWindowsUser32DLL user32dll;
246     static QWindowsShcoreDLL shcoredll;
247 
248     static QByteArray comErrorString(HRESULT hr);
249     bool asyncExpose() const;
250     void setAsyncExpose(bool value);
251 
252     static void forceNcCalcSize(HWND hwnd);
253 
254     static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0);
255     static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
256                                               const QPlatformScreen *screen = nullptr);
257     static bool systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
258                                               const QPlatformWindow *win = nullptr);
259     static bool nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi = 0);
260     static bool nonClientMetricsForScreen(NONCLIENTMETRICS *ncm,
261                                           const QPlatformScreen *screen = nullptr);
262     static bool nonClientMetricsForWindow(NONCLIENTMETRICS *ncm,
263                                           const QPlatformWindow *win = nullptr);
264 
265     static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue);
266 
267     QTouchDevice *touchDevice() const;
268 
269     static bool filterNativeEvent(MSG *msg, LRESULT *result);
270     static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result);
271 
272 private:
273     void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w);
274 #ifndef QT_NO_CONTEXTMENU
275     bool handleContextMenuEvent(QWindow *window, const MSG &msg);
276 #endif
277     void handleExitSizeMove(QWindow *window);
278     void unregisterWindowClasses();
279 
280     QScopedPointer<QWindowsContextPrivate> d;
281     static QWindowsContext *m_instance;
282 };
283 
284 extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND, UINT, WPARAM, LPARAM);
285 
286 QT_END_NAMESPACE
287 
288 #endif // QWINDOWSCONTEXT_H
289