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 #include "qwindowsnativeinterface.h"
41 #include "qwindowsclipboard.h"
42 #include "qwindowswindow.h"
43 #include "qwindowsscreen.h"
44 #include "qwindowscontext.h"
45 #include "qwindowscursor.h"
46 #include "qwindowsopenglcontext.h"
47 #include "qwindowsopengltester.h"
48 #include "qwindowsintegration.h"
49 #include "qwindowsmime.h"
50 #include "qwindowstheme.h"
51 #include "qwin10helpers.h"
52
53 #include <QtGui/qwindow.h>
54 #include <QtGui/qopenglcontext.h>
55 #include <QtGui/qscreen.h>
56 #include <qpa/qplatformscreen.h>
57 #include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
58
59 QT_BEGIN_NAMESPACE
60
61 enum ResourceType {
62 RenderingContextType,
63 EglContextType,
64 EglDisplayType,
65 EglConfigType,
66 HandleType,
67 GlHandleType,
68 GetDCType,
69 ReleaseDCType,
70 VkSurface
71 };
72
resourceType(const QByteArray & key)73 static int resourceType(const QByteArray &key)
74 {
75 static const char *names[] = { // match ResourceType
76 "renderingcontext",
77 "eglcontext",
78 "egldisplay",
79 "eglconfig",
80 "handle",
81 "glhandle",
82 "getdc",
83 "releasedc",
84 "vkSurface"
85 };
86 const char ** const end = names + sizeof(names) / sizeof(names[0]);
87 const char **result = std::find(names, end, key);
88 if (result == end)
89 result = std::find(names, end, key.toLower());
90 return int(result - names);
91 }
92
93 QWindowsWindowFunctions::WindowActivationBehavior QWindowsNativeInterface::m_windowActivationBehavior =
94 QWindowsWindowFunctions::DefaultActivateWindow;
95
nativeResourceForWindow(const QByteArray & resource,QWindow * window)96 void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
97 {
98 if (!window || !window->handle()) {
99 qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
100 return nullptr;
101 }
102 auto *bw = static_cast<QWindowsWindow *>(window->handle());
103 int type = resourceType(resource);
104 if (type == HandleType)
105 return bw->handle();
106 switch (window->surfaceType()) {
107 case QWindow::RasterSurface:
108 case QWindow::RasterGLSurface:
109 if (type == GetDCType)
110 return bw->getDC();
111 if (type == ReleaseDCType) {
112 bw->releaseDC();
113 return nullptr;
114 }
115 break;
116 case QWindow::VulkanSurface:
117 #if QT_CONFIG(vulkan)
118 if (type == VkSurface)
119 return bw->surface(nullptr, nullptr); // returns the address of the VkSurfaceKHR, not the value, as expected
120 #endif
121 break;
122 default:
123 break;
124 }
125 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
126 return nullptr;
127 }
128
nativeResourceForScreen(const QByteArray & resource,QScreen * screen)129 void *QWindowsNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
130 {
131 if (!screen || !screen->handle()) {
132 qWarning("%s: '%s' requested for null screen or screen without handle.", __FUNCTION__, resource.constData());
133 return nullptr;
134 }
135 auto *bs = static_cast<QWindowsScreen *>(screen->handle());
136 int type = resourceType(resource);
137 if (type == HandleType)
138 return bs->handle();
139
140 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
141 return nullptr;
142 }
143
144 #ifndef QT_NO_CURSOR
nativeResourceForCursor(const QByteArray & resource,const QCursor & cursor)145 void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor)
146 {
147 if (resource == QByteArrayLiteral("hcursor")) {
148 if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) {
149 if (const QPlatformCursor *pCursor= primaryScreen->handle()->cursor())
150 return static_cast<const QWindowsCursor *>(pCursor)->hCursor(cursor);
151 }
152 }
153 return nullptr;
154 }
155 #endif // !QT_NO_CURSOR
156
157 static const char customMarginPropertyC[] = "WindowsCustomMargins";
158
windowProperty(QPlatformWindow * window,const QString & name) const159 QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
160 {
161 auto *platformWindow = static_cast<QWindowsWindow *>(window);
162 if (name == QLatin1String(customMarginPropertyC))
163 return QVariant::fromValue(platformWindow->customMargins());
164 return QVariant();
165 }
166
windowProperty(QPlatformWindow * window,const QString & name,const QVariant & defaultValue) const167 QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
168 {
169 const QVariant result = windowProperty(window, name);
170 return result.isValid() ? result : defaultValue;
171 }
172
setWindowProperty(QPlatformWindow * window,const QString & name,const QVariant & value)173 void QWindowsNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
174 {
175 auto *platformWindow = static_cast<QWindowsWindow *>(window);
176 if (name == QLatin1String(customMarginPropertyC))
177 platformWindow->setCustomMargins(qvariant_cast<QMargins>(value));
178 }
179
windowProperties(QPlatformWindow * window) const180 QVariantMap QWindowsNativeInterface::windowProperties(QPlatformWindow *window) const
181 {
182 QVariantMap result;
183 const QString customMarginProperty = QLatin1String(customMarginPropertyC);
184 result.insert(customMarginProperty, windowProperty(window, customMarginProperty));
185 return result;
186 }
187
nativeResourceForIntegration(const QByteArray & resource)188 void *QWindowsNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
189 {
190 #ifdef QT_NO_OPENGL
191 Q_UNUSED(resource)
192 #else
193 if (resourceType(resource) == GlHandleType) {
194 if (const QWindowsStaticOpenGLContext *sc = QWindowsIntegration::staticOpenGLContext())
195 return sc->moduleHandle();
196 }
197 #endif
198
199 return nullptr;
200 }
201
202 #ifndef QT_NO_OPENGL
nativeResourceForContext(const QByteArray & resource,QOpenGLContext * context)203 void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
204 {
205 if (!context || !context->handle()) {
206 qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
207 return nullptr;
208 }
209
210 auto *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
211 switch (resourceType(resource)) {
212 case RenderingContextType: // Fall through.
213 case EglContextType:
214 return glcontext->nativeContext();
215 case EglDisplayType:
216 return glcontext->nativeDisplay();
217 case EglConfigType:
218 return glcontext->nativeConfig();
219 default:
220 break;
221 }
222
223 qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
224 return nullptr;
225 }
226 #endif // !QT_NO_OPENGL
227
228 /*!
229 \brief Creates a non-visible window handle for filtering messages.
230 */
231
createMessageWindow(const QString & classNameTemplate,const QString & windowName,void * eventProc) const232 void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
233 const QString &windowName,
234 void *eventProc) const
235 {
236 QWindowsContext *ctx = QWindowsContext::instance();
237 const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
238 (wchar_t*)windowName.utf16(),
239 (WNDPROC)eventProc);
240 return hwnd;
241 }
242
243 /*!
244 \brief Registers a unique window class with a callback function based on \a classNameIn.
245 */
246
registerWindowClass(const QString & classNameIn,void * eventProc) const247 QString QWindowsNativeInterface::registerWindowClass(const QString &classNameIn, void *eventProc) const
248 {
249 return QWindowsContext::instance()->registerWindowClass(classNameIn, (WNDPROC)eventProc);
250 }
251
asyncExpose() const252 bool QWindowsNativeInterface::asyncExpose() const
253 {
254 return QWindowsContext::instance()->asyncExpose();
255 }
256
setAsyncExpose(bool value)257 void QWindowsNativeInterface::setAsyncExpose(bool value)
258 {
259 QWindowsContext::instance()->setAsyncExpose(value);
260 }
261
registerWindowsMime(void * mimeIn)262 void QWindowsNativeInterface::registerWindowsMime(void *mimeIn)
263 {
264 QWindowsContext::instance()->mimeConverter().registerMime(reinterpret_cast<QWindowsMime *>(mimeIn));
265 }
266
unregisterWindowsMime(void * mimeIn)267 void QWindowsNativeInterface::unregisterWindowsMime(void *mimeIn)
268 {
269 QWindowsContext::instance()->mimeConverter().unregisterMime(reinterpret_cast<QWindowsMime *>(mimeIn));
270 }
271
registerMimeType(const QString & mimeType)272 int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
273 {
274 return QWindowsMime::registerMimeType(mimeType);
275 }
276
logFontToQFont(const void * logFont,int verticalDpi)277 QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi)
278 {
279 return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi);
280 }
281
isTabletMode()282 bool QWindowsNativeInterface::isTabletMode()
283 {
284 #if QT_CONFIG(clipboard)
285 if (const QWindowsClipboard *clipboard = QWindowsClipboard::instance())
286 return qt_windowsIsTabletMode(clipboard->clipboardViewer());
287 #endif
288 return false;
289 }
290
platformFunction(const QByteArray & function) const291 QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const
292 {
293 if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
294 return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
295 if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
296 return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
297 if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier())
298 return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault);
299 if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
300 return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior);
301 if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
302 return QFunctionPointer(QWindowsNativeInterface::isTabletMode);
303 return nullptr;
304 }
305
gpu() const306 QVariant QWindowsNativeInterface::gpu() const
307 {
308 return GpuDescription::detect().toVariant();
309 }
310
gpuList() const311 QVariant QWindowsNativeInterface::gpuList() const
312 {
313 QVariantList result;
314 const auto gpus = GpuDescription::detectAll();
315 for (const auto &gpu : gpus)
316 result.append(gpu.toVariant());
317 return result;
318 }
319
isDarkMode() const320 bool QWindowsNativeInterface::isDarkMode() const
321 {
322 return QWindowsContext::isDarkMode();
323 }
324
325 // Dark mode support level 2 (style)
isDarkModeStyle() const326 bool QWindowsNativeInterface::isDarkModeStyle() const
327 {
328 return (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeStyle) != 0;
329 }
330
331 QT_END_NAMESPACE
332