14#include "private/qabstractvideobuffer_p.h"
15#include "private/qcapturablewindow_p.h"
16#include "private/qmemoryvideobuffer_p.h"
17#include "private/qvideoframeconversionhelper_p.h"
21#include <X11/extensions/XShm.h>
23#include <X11/extensions/Xrandr.h>
33void destroyXImage(XImage*
image) {
37template <
typename T,
typename D>
38std::unique_ptr<T, D> makeXUptr(T*
ptr, D deleter) {
39 return std::unique_ptr<T, D>(
ptr, deleter);
49 auto found = std::find_if(
monitors.get(),
end, [&](
const XRRMonitorInfo &
info) {
50 auto atomName = makeXUptr(XGetAtomName(display, info.name), &XFree);
51 return atomName && name == QString::fromUtf8(atomName.get());
54 return found ==
end ? -1 : std::distance(
monitors.get(), found);
61 if (
image.red_mask == 0xff0000 &&
62 image.green_mask == 0xff00 &&
63 image.blue_mask == 0xff)
66 if (
image.red_mask == 0xff00 &&
67 image.green_mask == 0xff0000 &&
68 image.blue_mask == 0xff000000)
71 if (
image.blue_mask == 0xff0000 &&
72 image.green_mask == 0xff00 &&
73 image.red_mask == 0xff)
76 if (
image.red_mask == 0xff00 &&
77 image.green_mask == 0xff0000 &&
78 image.blue_mask == 0xff000000)
120 m_display.reset(XOpenDisplay(
nullptr));
126 return m_display !=
nullptr;
134 return createDisplay() && initWithXID(
static_cast<XID>(wid));
144 if (!createDisplay())
147 auto screenNumber = screenNumberByName(m_display.get(),
screen->
name());
149 if (screenNumber < 0)
154 return initWithXID(RootWindow(m_display.get(), screenNumber));
157 bool initWithXID(
XID xid)
171 if (std::exchange(m_attached,
false)) {
172 XShmDetach(m_display.get(), &m_shmInfo);
173 shmdt(m_shmInfo.shmaddr);
174 shmctl(m_shmInfo.shmid, IPC_RMID, 0);
183 shmget(IPC_PRIVATE, m_xImage->bytes_per_line * m_xImage->height, IPC_CREAT | 0777);
185 if (m_shmInfo.shmid == -1)
188 m_shmInfo.readOnly =
false;
189 m_shmInfo.shmaddr = m_xImage->data = (
char *)shmat(m_shmInfo.shmid, 0, 0);
191 m_attached = XShmAttach(m_display.get(), &m_shmInfo);
196 XWindowAttributes wndattr = {};
197 if (XGetWindowAttributes(m_display.get(), m_xid, &wndattr) == 0) {
210 if (!m_xImage || wndattr.width != m_xImage->width || wndattr.height != m_xImage->height
211 || wndattr.depth != m_xImage->depth || wndattr.visual->visualid != m_visualID) {
213 qCDebug(qLcX11SurfaceCapture) <<
"recreate ximage: " << wndattr.width << wndattr.height
214 << wndattr.depth << wndattr.visual->visualid;
219 m_visualID = wndattr.visual->visualid;
220 m_xImage.reset(XShmCreateImage(m_display.get(), wndattr.visual, wndattr.depth, ZPixmap,
221 nullptr, &m_shmInfo, wndattr.width, wndattr.height));
229 const auto pixelFormat = xImagePixelFormat(*m_xImage);
261 if (!XShmGetImage(m_display.get(), m_xid, m_xImage.get(), m_xOffset, m_yOffset,
265 "Cannot get ximage; the window may be out of the screen borders"));
271 const auto pixelSrc =
reinterpret_cast<const uint32_t *
>(m_xImage->data);
272 const auto pixelDst =
reinterpret_cast<uint32_t *
>(
data.data());
273 const auto pixelCount =
data.size() / 4;
274 const auto xImageAlphaVaries =
false;
284 std::optional<QPlatformSurfaceCapture::Error> m_prevGrabberError;
288 std::unique_ptr<
Display,
decltype(&XCloseDisplay)> m_display{
nullptr, &XCloseDisplay };
289 std::unique_ptr<XImage,
decltype(&destroyXImage)> m_xImage{
nullptr, &destroyXImage };
290 XShmSegmentInfo m_shmInfo;
291 bool m_attached =
false;
292 VisualID m_visualID =
None;
315 qCDebug(qLcX11SurfaceCapture) <<
"set active" << active;
322 return static_cast<bool>(m_grabber) == active;
325void QX11SurfaceCapture::activate(ScreenSource
screen)
331void QX11SurfaceCapture::activate(WindowSource
window)
static const QCapturableWindowPrivate * handle(const QCapturableWindow &window)
void setFrameRate(qreal rate)
void errorUpdated(QPlatformSurfaceCapture::Error error, const QString &description)
void addFrameCallback(Object &object, Method method)
void updateError(QPlatformSurfaceCapture::Error error, const QString &description={})
QScreen * primaryScreen
the primary (or default) screen of the application.
The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
The QScreen class is used to query screen properties. \inmodule QtGui.
qreal refreshRate
the approximate vertical refresh rate of the screen in Hz
QString name
a user presentable string representing the screen
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
The QVideoFrame class represents a frame of video data.
static std::unique_ptr< Grabber > create(QX11SurfaceCapture &capture, QScreen *screen)
const QVideoFrameFormat & format() const
QVideoFrame grabFrame() override
static std::unique_ptr< Grabber > create(QX11SurfaceCapture &capture, WId wid)
QVideoFrameFormat frameFormat() const override
~QX11SurfaceCapture() override
bool setActiveInternal(bool active) override
QX11SurfaceCapture(Source initialSource)
static bool isSupported()
struct wl_display * display
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
static ControlElement< T > * ptr(QWidget *widget)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLsizei GLsizei GLchar * source
QLatin1StringView QLatin1String
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
void Q_MULTIMEDIA_EXPORT qCopyPixelsWithAlphaMask(uint32_t *dst, const uint32_t *src, size_t pixCount, QVideoFrameFormat::PixelFormat format, bool srcAlphaVaries)