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
qx11capturablewindows.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
6#include <QtCore/qdebug.h>
7#include <QtGui/qwindow.h>
8#include <QtMultimedia/private/qcapturablewindow_p.h>
9
10#include <X11/Xlib.h>
11
12#include <optional>
13
14QT_BEGIN_NAMESPACE
15
16namespace { // Anonymous namespace start
17
18[[nodiscard]] bool qIsX11WindowValid(Display *display, Window window)
19{
20 XWindowAttributes windowAttributes = {};
21 return display
22 && XGetWindowAttributes(display, window, &windowAttributes) != 0
23 && windowAttributes.depth > 0;
24}
25
26[[nodiscard]] std::optional<QString> qGetX11WindowTitle(Display *display, Window window)
27{
28 if (!display)
29 return std::nullopt;
30
31 char *windowTitle = nullptr;
32 if (XFetchName(display, window, &windowTitle) && windowTitle) {
33 QString out = QString::fromUtf8(windowTitle);
34 XFree(windowTitle);
35 return out;
36 }
37
38 return std::nullopt;
39}
40
41} // Anonymous namespace end
42
43QX11CapturableWindows::~QX11CapturableWindows()
44{
45 if (m_display)
46 XCloseDisplay(m_display);
47}
48
49QList<QCapturableWindow> QX11CapturableWindows::windows() const
50{
51 auto display = this->display();
52
53 if (!display)
54 return {};
55
56 Atom atom = XInternAtom(display, "_NET_CLIENT_LIST", true);
57 Atom actualType = 0;
58 int format = 0;
59 unsigned long windowsCount = 0;
60 unsigned long bytesAfter = 0;
61 unsigned char *data = nullptr;
62 const int status = XGetWindowProperty(display, XDefaultRootWindow(display), atom, 0L, (~0L),
63 false, AnyPropertyType, &actualType, &format,
64 &windowsCount, &bytesAfter, &data);
65
66 if (status < Success || !data)
67 return {};
68
69 QList<QCapturableWindow> result;
70
71 auto freeDataGuard = qScopeGuard([data]() { XFree(data); });
72 auto windows = reinterpret_cast<XID *>(data);
73 for (unsigned long i = 0; i < windowsCount; i++) {
74 XID windowId = windows[i];
75 if (!qIsX11WindowValid(display, windowId))
76 continue;
77
78 result.push_back(QCapturableWindowPrivate::create(
79 static_cast<QCapturableWindowPrivate::Id>(windowId),
80 qGetX11WindowTitle(display, windowId).value_or(QString())));
81 }
82
83 return result;
84}
85
86bool QX11CapturableWindows::isWindowValid(const QCapturableWindowPrivate &window) const
87{
88 return qIsX11WindowValid(this->display(), static_cast<Window>(window.id));
89}
90
91Display *QX11CapturableWindows::display() const
92{
93 std::call_once(m_displayOnceFlag, [this]() { m_display = XOpenDisplay(nullptr); });
94 return m_display;
95}
96
97q23::expected<QCapturableWindow, QString> QX11CapturableWindows::fromQWindow(QWindow *window) const
98{
99 const auto xId = static_cast<XID>(window->winId());
100 return QCapturableWindowPrivate::create(
101 static_cast<QCapturableWindowPrivate::Id>(xId),
102 window->title());
103}
104
105QT_END_NAMESPACE
std::optional< QString > qGetX11WindowTitle(Display *display, Window window)
bool qIsX11WindowValid(Display *display, Window window)