Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwincapturablewindows.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 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
5#include "private/qcapturablewindow_p.h"
6
7#include <QtGui/qwindow.h>
8
9#include <qt_windows.h>
10#include <dwmapi.h>
11
13
14static bool isTopLevelWindow(HWND hwnd)
15{
16 return hwnd && ::GetAncestor(hwnd, GA_ROOT) == hwnd;
17}
18
19static bool canCaptureWindow(HWND hwnd)
20{
21 Q_ASSERT(hwnd);
22
23 if (!::IsWindowVisible(hwnd))
24 return false;
25
26 // Minimized windows are not rendered, so capturing them never delivers a frame
27 if (::IsIconic(hwnd))
28 return false;
29
30 // The desktop is not a window that can be captured
31 if (hwnd == ::GetShellWindow())
32 return false;
33
34 // Windows without a class name are not real windows
35 wchar_t className[2] = {};
36 if (::GetClassNameW(hwnd, className, 2) == 0)
37 return false;
38
39 if (::GetWindowLongPtrW(hwnd, GWL_STYLE) & WS_DISABLED)
40 return false;
41
42 // Tool windows are helpers like the taskbar, tooltips and message windows
43 if (::GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
44 return false;
45
46 // Cloaked windows are visible according to IsWindowVisible, but are not shown on screen
47 // (e.g. suspended UWP apps, windows on other virtual desktops, or system helper windows)
48 DWORD cloaked = 0;
49 if (SUCCEEDED(::DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &cloaked, sizeof(cloaked)))
50 && cloaked != 0)
51 return false;
52
53 RECT rect{};
54 if (!::GetWindowRect(hwnd, &rect))
55 return false;
56
57 if (rect.left >= rect.right || rect.top >= rect.bottom)
58 return false;
59
60 return true;
61}
62
63static QString windowTitle(HWND hwnd) {
64 // QTBUG-114890
65 // TODO: investigate the case when hwnd is inner and belows to another thread.
66 // It might causes deadlocks in specific cases.
67 auto titleLength = ::GetWindowTextLengthW(hwnd);
68 std::wstring buffer(titleLength + 1, L'\0');
69 titleLength = ::GetWindowTextW(hwnd, buffer.data(), titleLength + 1);
70 buffer.resize(titleLength);
71
72 return QString::fromStdWString(buffer);
73}
74
75static BOOL CALLBACK windowHandler(HWND hwnd, LPARAM lParam) {
76 if (!canCaptureWindow(hwnd))
77 return TRUE; // Ignore window and continue enumerating
78
79 auto &windows = *reinterpret_cast<QList<QCapturableWindow> *>(lParam);
80
81 windows.push_back(QCapturableWindowPrivate::create(
82 reinterpret_cast<QCapturableWindowPrivate::Id>(hwnd),
83 windowTitle(hwnd)));
84
85 return TRUE;
86}
87
88QList<QCapturableWindow> QWinCapturableWindows::windows() const
89{
90 QList<QCapturableWindow> result;
91
92 ::EnumWindows(windowHandler, reinterpret_cast<LPARAM>(&result));
93
94 return result;
95}
96
97bool QWinCapturableWindows::isWindowValid(const QCapturableWindowPrivate &window) const
98{
99 const auto hwnd = reinterpret_cast<HWND>(window.id);
100 return isTopLevelWindow(hwnd) && canCaptureWindow(hwnd);
101}
102
103q23::expected<QCapturableWindow, QString> QWinCapturableWindows::fromQWindow(QWindow *window) const
104{
105 const auto hwnd = reinterpret_cast<HWND>(window->winId());
106 return QCapturableWindowPrivate::create(
107 reinterpret_cast<QCapturableWindowPrivate::Id>(hwnd),
108 windowTitle(hwnd));
109}
110QT_END_NAMESPACE
Combined button and popup list for selecting options.
static bool canCaptureWindow(HWND hwnd)
static QT_BEGIN_NAMESPACE bool isTopLevelWindow(HWND hwnd)
static QString windowTitle(HWND hwnd)