Format project

Command used to format: git ls-files | grep -E '\.(cpp|h|hpp|c)$' | xargs clang-format -i --style file
This commit is contained in:
Antti Savolainen
2026-04-24 11:36:02 +03:00
parent 88f1636fef
commit c521740404
48 changed files with 704 additions and 679 deletions

View File

@@ -8,16 +8,16 @@
#include "config-krfb.h"
// system
#include <sys/mman.h>
#include <cstring>
#include <sys/mman.h>
// Qt
#include <QCoreApplication>
#include <QDebug>
#include <QGuiApplication>
#include <QRandomGenerator>
#include <QScreen>
#include <QSocketNotifier>
#include <QDebug>
#include <QRandomGenerator>
#include <KConfigGroup>
#include <KSharedConfig>
@@ -28,13 +28,13 @@
// pipewire
#include <climits>
#include "pw_framebuffer.h"
#include "xdp_dbus_screencast_interface.h"
#include "xdp_dbus_remotedesktop_interface.h"
#include "krfb_fb_pipewire_debug.h"
#include "pw_framebuffer.h"
#include "screencasting.h"
#include <PipeWireSourceStream>
#include "xdp_dbus_remotedesktop_interface.h"
#include "xdp_dbus_screencast_interface.h"
#include <DmaBufHandler>
#include <PipeWireSourceStream>
static const int BYTES_PER_PIXEL = 4;
static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
@@ -42,7 +42,7 @@ static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
Q_DECLARE_METATYPE(PWFrameBuffer::Stream);
Q_DECLARE_METATYPE(PWFrameBuffer::Streams);
const QDBusArgument &operator >> (const QDBusArgument &arg, PWFrameBuffer::Stream &stream)
const QDBusArgument &operator>>(const QDBusArgument &arg, PWFrameBuffer::Stream &stream)
{
arg.beginStructure();
arg >> stream.nodeId;
@@ -66,7 +66,8 @@ const QDBusArgument &operator >> (const QDBusArgument &arg, PWFrameBuffer::Strea
* @brief The PWFrameBuffer::Private class - private counterpart of PWFramebuffer class. This is the entity where
* whole logic resides, for more info search for "d-pointer pattern" information.
*/
class PWFrameBuffer::Private {
class PWFrameBuffer::Private
{
public:
Private(PWFrameBuffer *q);
~Private();
@@ -111,7 +112,7 @@ PWFrameBuffer::Private::Private(PWFrameBuffer *q)
: q(q)
, stream(new PipeWireSourceStream(q))
{
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this] (const PipeWireFrame &frame) {
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this](const PipeWireFrame &frame) {
handleFrame(frame);
});
}
@@ -125,11 +126,11 @@ void PWFrameBuffer::Private::initDbus()
{
qInfo() << "Initializing D-Bus connectivity with XDG Desktop Portal";
dbusXdpScreenCastService.reset(new OrgFreedesktopPortalScreenCastInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
QStringLiteral("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
QStringLiteral("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
QStringLiteral("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
QStringLiteral("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
auto version = dbusXdpScreenCastService->version();
if (version < MIN_SUPPORTED_XDP_KDE_SC_VERSION) {
qCWarning(KRFB_FB_PIPEWIRE) << "Unsupported XDG Portal screencast interface version:" << version;
@@ -138,10 +139,9 @@ void PWFrameBuffer::Private::initDbus()
}
// create session
auto sessionParameters = QVariantMap {
{ QStringLiteral("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) },
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
};
auto sessionParameters = QVariantMap{
{QStringLiteral("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
auto sessionReply = dbusXdpRemoteDesktopService->CreateSession(sessionParameters);
sessionReply.waitForFinished();
if (!sessionReply.isValid()) {
@@ -182,11 +182,11 @@ void PWFrameBuffer::Private::handleSessionCreated(quint32 code, const QVariantMa
sessionPath = QDBusObjectPath(results.value(QStringLiteral("session_handle")).toString());
// select sources for the session
auto selectionOptions = QVariantMap {
auto selectionOptions = QVariantMap{
// We have to specify it's an uint, otherwise xdg-desktop-portal will not forward it to backend implementation
{ QStringLiteral("types"), QVariant::fromValue<uint>(7) }, // request all (KeyBoard, Pointer, TouchScreen)
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) },
{ QStringLiteral("persist_mode"), QVariant::fromValue<uint>(2) }, // Persist permission until explicitly revoked by user
{QStringLiteral("types"), QVariant::fromValue<uint>(7)}, // request all (KeyBoard, Pointer, TouchScreen)
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
{QStringLiteral("persist_mode"), QVariant::fromValue<uint>(2)}, // Persist permission until explicitly revoked by user
};
KConfigGroup stateConfig = KSharedConfig::openStateConfig()->group(QStringLiteral("XdgPortal"));
@@ -231,11 +231,10 @@ void PWFrameBuffer::Private::handleDevicesSelected(quint32 code, const QVariantM
}
// select sources for the session
auto selectionOptions = QVariantMap {
{ QStringLiteral("types"), QVariant::fromValue<uint>(1) }, // only MONITOR is supported
{ QStringLiteral("multiple"), false },
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
};
auto selectionOptions = QVariantMap{
{QStringLiteral("types"), QVariant::fromValue<uint>(1)}, // only MONITOR is supported
{QStringLiteral("multiple"), false},
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
auto selectorReply = dbusXdpScreenCastService->SelectSources(sessionPath, selectionOptions);
selectorReply.waitForFinished();
if (!selectorReply.isValid()) {
@@ -273,9 +272,8 @@ void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantM
}
// start session
auto startParameters = QVariantMap {
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
};
auto startParameters = QVariantMap{
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
auto startReply = dbusXdpRemoteDesktopService->Start(sessionPath, QString(), startParameters);
startReply.waitForFinished();
QDBusConnection::sessionBus().connect(QString(),
@@ -286,7 +284,6 @@ void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantM
SLOT(handleXdpRemoteDesktopStarted(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results)
{
d->handleRemoteDesktopStarted(code, results);
@@ -376,9 +373,9 @@ void PWFrameBuffer::Private::handleFrame(const PipeWireFrame &frame)
#endif
else if (frame.dmabuf) {
// FIXME: Assuming stride == width * 4, not sure to which extent this holds
const QSize size = { frame.dmabuf->width, frame.dmabuf->height };
const QSize size = {frame.dmabuf->width, frame.dmabuf->height};
setVideoSize(size);
QImage src(reinterpret_cast<uchar*>(q->fb), size.width(), size.height(), QImage::Format_RGB32);
QImage src(reinterpret_cast<uchar *>(q->fb), size.width(), size.height(), QImage::Format_RGB32);
if (!m_dmabufHandler.downloadFrame(src, frame)) {
stream->renegotiateModifierFailed(frame.format, frame.dmabuf->modifier);
qCDebug(KRFB_FB_PIPEWIRE) << "Failed to download frame.";
@@ -404,7 +401,7 @@ void PWFrameBuffer::Private::setVideoSize(const QSize &size)
}
free(q->fb);
q->fb = static_cast<char*>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
q->fb = static_cast<char *>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
if (!q->fb) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
isValid = false;
@@ -420,8 +417,8 @@ PWFrameBuffer::Private::~Private()
}
PWFrameBuffer::PWFrameBuffer(QObject *parent)
: FrameBuffer (parent),
d(new Private(this))
: FrameBuffer(parent)
, d(new Private(this))
{
}
@@ -436,7 +433,7 @@ void PWFrameBuffer::initDBus()
d->initDbus();
}
void PWFrameBuffer::startVirtualMonitor(const QString& name, const QSize& resolution, qreal dpr)
void PWFrameBuffer::startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr)
{
d->videoSize = resolution * dpr;
using namespace KWayland::Client;
@@ -448,13 +445,14 @@ void PWFrameBuffer::startVirtualMonitor(const QString& name, const QSize& resolu
}
auto registry = new Registry(this);
connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry, name, dpr, resolution] (const QByteArray &interfaceName, quint32 wlname, quint32 version) {
if (interfaceName != "zkde_screencast_unstable_v1")
connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry, name, dpr, resolution](const QByteArray &interfaceName, quint32 wlname, quint32 version) {
if (interfaceName != "zkde_screencast_unstable_v1") {
return;
}
auto screencasting = new Screencasting(registry, wlname, version, this);
auto r = screencasting->createVirtualMonitorStream(name, resolution, dpr, Screencasting::Metadata);
connect(r, &ScreencastingStream::created, this, [this] (quint32 nodeId) {
connect(r, &ScreencastingStream::created, this, [this](quint32 nodeId) {
d->stream->createStream(nodeId, 0);
});
});
@@ -498,19 +496,18 @@ void PWFrameBuffer::getServerFormat(rfbPixelFormat &format)
void PWFrameBuffer::startMonitor()
{
}
void PWFrameBuffer::stopMonitor()
{
}
QVariant PWFrameBuffer::customProperty(const QString &property) const
{
if (property == QLatin1String("stream_node_id")) {
return QVariant::fromValue<uint>(d->stream->nodeId());
} if (property == QLatin1String("session_handle")) {
}
if (property == QLatin1String("session_handle")) {
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
}

View File

@@ -8,8 +8,8 @@
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
#include "framebuffer.h"
#include <QWidget>
#include <QVariantMap>
#include <QWidget>
/**
* @brief The PWFrameBuffer class - framebuffer implementation based on XDG Desktop Portal ScreenCast interface.
@@ -17,11 +17,13 @@
*
* @author Oleg Chernovskiy <kanedias@xaker.ru>
*/
class PWFrameBuffer: public FrameBuffer
class PWFrameBuffer : public FrameBuffer
{
Q_OBJECT
public:
using Stream = struct {
using Stream = struct
{
uint nodeId;
QVariantMap map;
};
@@ -33,10 +35,10 @@ public:
void initDBus();
void startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr);
int depth() override;
int height() override;
int width() override;
int paddedWidth() override;
int depth() override;
int height() override;
int width() override;
int paddedWidth() override;
void getServerFormat(rfbPixelFormat &format) override;
void startMonitor() override;
void stopMonitor() override;

View File

@@ -4,7 +4,6 @@
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "pw_framebufferplugin.h"
#include "pw_framebuffer.h"
#include <KPluginFactory>
@@ -16,7 +15,6 @@ PWFrameBufferPlugin::PWFrameBufferPlugin(QObject *parent, const QVariantList &ar
{
}
FrameBuffer *PWFrameBufferPlugin::frameBuffer(const QVariantMap &args)
{
auto pwfb = new PWFrameBuffer;

View File

@@ -1,29 +1,27 @@
/* This file is part of the KDE project
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
/* This file is part of the KDE project
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
#define KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
#include "framebufferplugin.h"
class FrameBuffer;
class PWFrameBufferPlugin: public FrameBufferPlugin
class PWFrameBufferPlugin : public FrameBufferPlugin
{
Q_OBJECT
Q_OBJECT
public:
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
FrameBuffer *frameBuffer(const QVariantMap &args) override;
FrameBuffer *frameBuffer(const QVariantMap &args) override;
private:
Q_DISABLE_COPY(PWFrameBufferPlugin)
Q_DISABLE_COPY(PWFrameBufferPlugin)
};
#endif // Header guard
#endif // Header guard

View File

@@ -12,8 +12,8 @@
#endif
#include <KWayland/Client/registry.h>
#include <QDebug>
#include <QRect>
#include <QPointer>
#include <QRect>
using namespace KWayland::Client;
@@ -99,7 +99,7 @@ Screencasting::Screencasting(Registry *registry, int id, int version, QObject *p
Screencasting::~Screencasting() = default;
ScreencastingStream * Screencasting::createVirtualMonitorStream(const QString& name, const QSize& resolution, qreal dpr, Screencasting::CursorMode mode)
ScreencastingStream *Screencasting::createVirtualMonitorStream(const QString &name, const QSize &resolution, qreal dpr, Screencasting::CursorMode mode)
{
auto stream = new ScreencastingStream(this);
stream->d->init(d->stream_virtual_output(name, resolution.width(), resolution.height(), wl_fixed_from_double(dpr), mode));

View File

@@ -6,9 +6,9 @@
#pragma once
#include <QList>
#include <QObject>
#include <QSharedPointer>
#include <QList>
#include <optional>
struct zkde_screencast_unstable_v1;
@@ -17,9 +17,11 @@ namespace KWayland
{
namespace Client
{
class PlasmaWindow;
class Registry;
class Output;
}
}
@@ -29,6 +31,7 @@ class ScreencastingStreamPrivate;
class ScreencastingStream : public QObject
{
Q_OBJECT
public:
ScreencastingStream(QObject *parent);
~ScreencastingStream() override;
@@ -48,6 +51,7 @@ private:
class Screencasting : public QObject
{
Q_OBJECT
public:
explicit Screencasting(QObject *parent = nullptr);
explicit Screencasting(KWayland::Client::Registry *registry, int id, int version, QObject *parent = nullptr);

View File

@@ -7,22 +7,22 @@
#include "xcb_framebuffer.h"
#include "krfb_fb_xcb_debug.h"
#include <xcb/xproto.h>
#include <xcb/damage.h>
#include <xcb/shm.h>
#include <xcb/xcb_image.h>
#include <xcb/xproto.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <QAbstractNativeEventFilter>
#include <QApplication>
#include <QGuiApplication>
#include <QScreen>
#include <QAbstractNativeEventFilter>
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/private/qtx11extras_p.h>
#include <qpa/qplatformnativeinterface.h>
class KrfbXCBEventFilter: public QAbstractNativeEventFilter
class KrfbXCBEventFilter : public QAbstractNativeEventFilter
{
public:
KrfbXCBEventFilter(XCBFrameBuffer *owner);
@@ -39,33 +39,33 @@ public:
XCBFrameBuffer *fb_owner;
};
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
xdamageBaseEvent(0), xdamageBaseError(0),
xshmBaseEvent(0), xshmBaseError(0), xshmAvail(false),
fb_owner(owner)
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner)
: xdamageBaseEvent(0)
, xdamageBaseError(0)
, xshmBaseEvent(0)
, xshmBaseError(0)
, xshmAvail(false)
, fb_owner(owner)
{
const xcb_query_extension_reply_t *xdamage_data = xcb_get_extension_data(
QX11Info::connection(), &xcb_damage_id);
QX11Info::connection(), &xcb_damage_id);
if (xdamage_data) {
// also query extension version!
// ATTENTION: if we don't do that, xcb_damage_create() will always FAIL!
xcb_damage_query_version_reply_t *xdamage_version = xcb_damage_query_version_reply(
QX11Info::connection(),
xcb_damage_query_version(
QX11Info::connection(),
XCB_DAMAGE_MAJOR_VERSION,
XCB_DAMAGE_MINOR_VERSION),
nullptr);
QX11Info::connection(),
xcb_damage_query_version(
QX11Info::connection(),
XCB_DAMAGE_MAJOR_VERSION,
XCB_DAMAGE_MINOR_VERSION),
nullptr);
if (!xdamage_version) {
qWarning() << "xcb framebuffer: ERROR: Failed to get XDamage extension version!\n";
return;
}
#ifdef _DEBUG
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XDamage extension version:" <<
xdamage_version->major_version << "." << xdamage_version->minor_version;
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XDamage extension version:" << xdamage_version->major_version << "." << xdamage_version->minor_version;
#endif
free(xdamage_version);
@@ -76,7 +76,7 @@ KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
// XShm presence is optional. If it is present, all image getting
// operations will be faster, without XShm it will only be slower.
const xcb_query_extension_reply_t *xshm_data = xcb_get_extension_data(
QX11Info::connection(), &xcb_shm_id);
QX11Info::connection(), &xcb_shm_id);
if (xshm_data) {
xshmAvail = true;
xshmBaseEvent = xshm_data->first_event;
@@ -93,19 +93,21 @@ KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
}
}
bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
void *message, qintptr *result) {
Q_UNUSED(result); // "result" is only used on windows
void *message, qintptr *result)
{
Q_UNUSED(result); // "result" is only used on windows
if (xdamageBaseEvent == 0) return false; // no xdamage extension
if (xdamageBaseEvent == 0) {
return false; // no xdamage extension
}
if (eventType == "xcb_generic_event_t") {
auto ev = static_cast<xcb_generic_event_t *>(message);
if ((ev->response_type & 0x7F) == (xdamageBaseEvent + XCB_DAMAGE_NOTIFY)) {
// this is xdamage notification
this->fb_owner->handleXDamageNotify(ev);
return true; // filter out this event, stop its processing
return true; // filter out this event, stop its processing
}
}
@@ -113,37 +115,38 @@ bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
return false;
}
class XCBFrameBuffer::P {
class XCBFrameBuffer::P
{
public:
xcb_damage_damage_t damage;
xcb_shm_segment_info_t shminfo;
xcb_screen_t *rootScreen; // X screen info (all monitors)
xcb_image_t *framebufferImage;
xcb_image_t *updateTile;
xcb_damage_damage_t damage;
xcb_shm_segment_info_t shminfo;
xcb_screen_t *rootScreen; // X screen info (all monitors)
xcb_image_t *framebufferImage;
xcb_image_t *updateTile;
KrfbXCBEventFilter *x11EvtFilter;
KrfbXCBEventFilter *x11EvtFilter;
bool running;
bool running;
QRect area; // capture area, primary monitor coordinates
WId win;
QRect area; // capture area, primary monitor coordinates
WId win;
};
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num) {
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num)
{
xcb_screen_t *screen = nullptr;
xcb_screen_iterator_t screens_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter))
if (screen_num == 0)
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter)) {
if (screen_num == 0) {
screen = screens_iter.data;
}
}
return screen;
}
XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
FrameBuffer(parent), d(new XCBFrameBuffer::P)
XCBFrameBuffer::XCBFrameBuffer(QObject *parent)
: FrameBuffer(parent)
, d(new XCBFrameBuffer::P)
{
d->running = false;
d->damage = XCB_NONE;
@@ -160,17 +163,17 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
QScreen *primaryScreen = QGuiApplication::primaryScreen();
if (primaryScreen) {
QPlatformNativeInterface* native = qApp->platformNativeInterface();
QPlatformNativeInterface *native = qApp->platformNativeInterface();
d->win = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), primaryScreen));
qreal scaleFactor = primaryScreen->devicePixelRatio();
d->area = { primaryScreen->geometry().topLeft() * scaleFactor,
primaryScreen->geometry().bottomRight() * scaleFactor };
d->area = {primaryScreen->geometry().topLeft() * scaleFactor,
primaryScreen->geometry().bottomRight() * scaleFactor};
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Primary screen: " << primaryScreen->name()
<< ", geometry: " << primaryScreen->geometry()
<< ", device scaling: " << scaleFactor
<< ", native size: " << d->area
<< ", depth: " << primaryScreen->depth();
<< ", geometry: " << primaryScreen->geometry()
<< ", device scaling: " << scaleFactor
<< ", native size: " << d->area
<< ", depth: " << primaryScreen->depth();
} else {
qWarning() << "xcb framebuffer: ERROR: Failed to get application's primary screen info!";
return;
@@ -187,9 +190,9 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
if (d->framebufferImage) {
#ifdef _DEBUG
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Got primary screen image. bpp: " << d->framebufferImage->bpp
<< ", size (" << d->framebufferImage->width << d->framebufferImage->height << ")"
<< ", depth: " << d->framebufferImage->depth
<< ", padded width: " << d->framebufferImage->stride;
<< ", size (" << d->framebufferImage->width << d->framebufferImage->height << ")"
<< ", depth: " << d->framebufferImage->depth
<< ", padded width: " << d->framebufferImage->stride;
#endif
this->fb = (char *)d->framebufferImage->data;
} else {
@@ -204,25 +207,25 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
// "If base == 0 and bytes == ~0 and data == 0, no storage will be auto-allocated."
// Width and height of the image = size of the capture area.
d->updateTile = xcb_image_create_native(
QX11Info::connection(),
d->area.width(), // width
d->area.height(), // height
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
d->rootScreen->root_depth, // depth
nullptr, // base address = 0
(uint32_t)~0, // bytes = 0xffffffff
nullptr); // data = 0
QX11Info::connection(),
d->area.width(), // width
d->area.height(), // height
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
d->rootScreen->root_depth, // depth
nullptr, // base address = 0
(uint32_t)~0, // bytes = 0xffffffff
nullptr); // data = 0
if (d->updateTile) {
#ifdef _DEBUG
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Successfully created new empty image in native format"
<< "\n size: " << d->updateTile->width << "x" << d->updateTile->height
<< "(stride: " << d->updateTile->stride << ")"
<< "\n bpp, depth: " << d->updateTile->bpp << d->updateTile->depth // 32, 24
<< "\n addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data
<< "\n size: " << d->updateTile->size
<< "\n image byte order = " << d->updateTile->byte_order // == 0 .._LSB_FIRST
<< "\n image bit order = " << d->updateTile->bit_order // == 1 .._MSB_FIRST
<< "\n image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
<< "\n size: " << d->updateTile->width << "x" << d->updateTile->height
<< "(stride: " << d->updateTile->stride << ")"
<< "\n bpp, depth: " << d->updateTile->bpp << d->updateTile->depth // 32, 24
<< "\n addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data
<< "\n size: " << d->updateTile->size
<< "\n image byte order = " << d->updateTile->byte_order // == 0 .._LSB_FIRST
<< "\n image bit order = " << d->updateTile->bit_order // == 1 .._MSB_FIRST
<< "\n image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
#endif
// allocate shared memory block only once, make its size large enough
@@ -245,13 +248,13 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
// will return 1 on success (yes!)
int shmget_res = xcb_image_shm_get(
QX11Info::connection(),
d->win,
d->updateTile,
d->shminfo,
d->area.left(), // x
d->area.top(), // y (size taken from image structure itself)?
0xFFFFFFFF);
QX11Info::connection(),
d->win,
d->updateTile,
d->shminfo,
d->area.left(), // x
d->area.top(), // y (size taken from image structure itself)?
0xFFFFFFFF);
if (shmget_res == 0) {
// error! shared mem not working?
@@ -277,31 +280,34 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
#ifdef _DEBUG
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XCBFrameBuffer(), xshm base event = " << d->x11EvtFilter->xshmBaseEvent
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError
<< ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError
<< ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
#endif
QCoreApplication::instance()->installNativeEventFilter(d->x11EvtFilter);
}
XCBFrameBuffer::~XCBFrameBuffer() {
XCBFrameBuffer::~XCBFrameBuffer()
{
// first - uninstall x11 event filter
QCoreApplication::instance()->removeNativeEventFilter(d->x11EvtFilter);
//
if (d->framebufferImage) {
xcb_image_destroy(d->framebufferImage);
fb = nullptr; // image data was already destroyed by above call
fb = nullptr; // image data was already destroyed by above call
}
if (d->x11EvtFilter->xshmAvail) {
// detach shared memory
if (d->shminfo.shmseg != XCB_NONE)
if (d->shminfo.shmseg != XCB_NONE) {
xcb_shm_detach(QX11Info::connection(), d->shminfo.shmseg); // detach from X server
if (d->shminfo.shmaddr)
}
if (d->shminfo.shmaddr) {
shmdt(d->shminfo.shmaddr); // detach addr from our address space
if (d->shminfo.shmid != XCB_NONE)
}
if (d->shminfo.shmid != XCB_NONE) {
shmctl(d->shminfo.shmid, IPC_RMID, nullptr); // mark shm segment as removed
}
}
// and delete image used for shared mem
if (d->updateTile) {
@@ -316,43 +322,46 @@ XCBFrameBuffer::~XCBFrameBuffer() {
delete d;
}
int XCBFrameBuffer::depth() {
int XCBFrameBuffer::depth()
{
if (d->framebufferImage) {
return d->framebufferImage->depth;
}
return 0;
}
int XCBFrameBuffer::height() {
int XCBFrameBuffer::height()
{
if (d->framebufferImage) {
return d->framebufferImage->height;
}
return 0;
}
int XCBFrameBuffer::width() {
int XCBFrameBuffer::width()
{
if (d->framebufferImage) {
return d->framebufferImage->width;
}
return 0;
}
int XCBFrameBuffer::paddedWidth() {
int XCBFrameBuffer::paddedWidth()
{
if (d->framebufferImage) {
return d->framebufferImage->stride;
}
return 0;
}
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
if (!d->framebufferImage) return;
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format)
{
if (!d->framebufferImage) {
return;
}
// get information about XCB visual params
xcb_visualtype_t *root_visualtype = nullptr; // visual info
xcb_visualtype_t *root_visualtype = nullptr; // visual info
if (d->rootScreen) {
xcb_visualid_t root_visual = d->rootScreen->root_visual;
xcb_depth_iterator_t depth_iter;
@@ -374,12 +383,11 @@ void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
}
}
// fill in format common info
format.bitsPerPixel = d->framebufferImage->bpp;
format.depth = d->framebufferImage->depth;
format.trueColour = true; // not using color palettes
format.bigEndian = false; // always false for ZPIXMAP format!
format.trueColour = true; // not using color palettes
format.bigEndian = false; // always false for ZPIXMAP format!
// information about pixels layout
@@ -418,57 +426,56 @@ void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
// calculate pixel max value.
// NOTE: bits_per_rgb_value is unreliable, thus should be avoided.
format.redMax = root_visualtype->red_mask >> format.redShift;
format.redMax = root_visualtype->red_mask >> format.redShift;
format.greenMax = root_visualtype->green_mask >> format.greenShift;
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
#ifdef _DEBUG
qCDebug(KRFB_FB_XCB,
" Calculated redShift = %d\n"
" Calculated greenShift = %d\n"
" Calculated blueShift = %d\n"
" Calculated max values: R%d G%d B%d",
format.redShift, format.greenShift, format.blueShift
format.redMax, format.greenMax, format.blueMax);
" Calculated redShift = %d\n"
" Calculated greenShift = %d\n"
" Calculated blueShift = %d\n"
" Calculated max values: R%d G%d B%d",
format.redShift, format.greenShift, format.blueShift format.redMax, format.greenMax, format.blueMax);
#endif
} else {
// some kind of fallback (unlikely code execution will go this way)
// idea taken from qt framefuffer sources
if (format.bitsPerPixel == 8) {
format.redShift = 0;
format.redShift = 0;
format.greenShift = 3;
format.blueShift = 6;
format.redMax = 7;
format.blueShift = 6;
format.redMax = 7;
format.greenMax = 7;
format.blueMax = 3;
format.blueMax = 3;
} else if (format.bitsPerPixel == 16) {
// TODO: 16 bits per pixel format ??
// what format of pixels does X server use for 16-bpp?
} else if (format.bitsPerPixel == 32) {
format.redMax = 0xff;
format.redMax = 0xff;
format.greenMax = 0xff;
format.blueMax = 0xff;
format.blueMax = 0xff;
if (format.bigEndian) {
format.redShift = 0;
format.redShift = 0;
format.greenShift = 8;
format.blueShift = 16;
format.blueShift = 16;
} else {
format.redShift = 16;
format.redShift = 16;
format.greenShift = 8;
format.blueShift = 0;
format.blueShift = 0;
}
}
}
}
/**
* This function contents was taken from X11 framebuffer source code.
* It simply several intersecting rectangles into one bigger rect.
* Non-intersecting rects are treated as different rects and exist
* separately in this->tiles QList.
*/
void XCBFrameBuffer::cleanupRects() {
void XCBFrameBuffer::cleanupRects()
{
QList<QRect> cpy = tiles;
bool inserted = false;
tiles.clear();
@@ -477,7 +484,9 @@ void XCBFrameBuffer::cleanupRects() {
while (iter.hasNext()) {
const QRect &r = iter.next();
// skip rects not intersecting with primary monitor
if (!r.intersects(d->area)) continue;
if (!r.intersects(d->area)) {
continue;
}
// only take intersection of this rect with primary monitor rect
QRect ri = r.intersected(d->area);
@@ -525,13 +534,13 @@ void XCBFrameBuffer::cleanupRects() {
}
}
/**
* This function is called by RfbServerManager::updateScreens()
* approximately every 50ms (!!), driven by QTimer to get all
* modified rectangles on the screen
*/
QList<QRect> XCBFrameBuffer::modifiedTiles() {
QList<QRect> XCBFrameBuffer::modifiedTiles()
{
QList<QRect> ret;
if (!d->running) {
return ret;
@@ -541,10 +550,9 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
if (tiles.size() > 0) {
if (d->x11EvtFilter->xshmAvail) {
// loop over all damage rectangles gathered up to this time
QListIterator<QRect> iter(tiles);
//foreach(const QRect &r, tiles) {
// foreach(const QRect &r, tiles) {
while (iter.hasNext()) {
const QRect &r = iter.next();
@@ -553,41 +561,41 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
// but we need to get image from the whole screen, so
// translate the coordinates
xcb_shm_get_image_cookie_t sgi_cookie = xcb_shm_get_image(
QX11Info::connection(),
d->win,
d->area.left() + r.left(),
d->area.top() + r.top(),
r.width(),
r.height(),
0xFFFFFFFF,
XCB_IMAGE_FORMAT_Z_PIXMAP,
d->shminfo.shmseg,
0);
QX11Info::connection(),
d->win,
d->area.left() + r.left(),
d->area.top() + r.top(),
r.width(),
r.height(),
0xFFFFFFFF,
XCB_IMAGE_FORMAT_Z_PIXMAP,
d->shminfo.shmseg,
0);
xcb_shm_get_image_reply_t *sgi_reply = xcb_shm_get_image_reply(
QX11Info::connection(), sgi_cookie, nullptr);
QX11Info::connection(), sgi_cookie, nullptr);
if (sgi_reply) {
// create temporary image to get update rect contents into
d->updateTile = xcb_image_create_native(
QX11Info::connection(),
r.width(),
r.height(),
XCB_IMAGE_FORMAT_Z_PIXMAP,
d->rootScreen->root_depth,
nullptr, // base == 0
(uint32_t)~0, // bytes == ~0
nullptr);
QX11Info::connection(),
r.width(),
r.height(),
XCB_IMAGE_FORMAT_Z_PIXMAP,
d->rootScreen->root_depth,
nullptr, // base == 0
(uint32_t)~0, // bytes == ~0
nullptr);
if (d->updateTile) {
d->updateTile->data = d->shminfo.shmaddr;
// copy pixels from this damage rectangle image
// to our total framebuffer image
int pxsize = d->framebufferImage->bpp / 8;
int pxsize = d->framebufferImage->bpp / 8;
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
char *src = (char *)d->updateTile->data;
for (int i = 0; i < d->updateTile->height; i++) {
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
dest += d->framebufferImage->stride;
src += d->updateTile->stride;
}
@@ -604,28 +612,28 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
} else {
// not using shared memory
// will use just xcb_image_get() and copy pixels
for (const QRect& r : std::as_const(tiles)) {
for (const QRect &r : std::as_const(tiles)) {
// I did not find XGetSubImage() analog in XCB!!
// need function that copies pixels from one image to another
xcb_image_t *damagedImage = xcb_image_get(
QX11Info::connection(),
d->win,
r.left(),
r.top(),
r.width(),
r.height(),
0xFFFFFFFF, // AllPlanes
XCB_IMAGE_FORMAT_Z_PIXMAP);
QX11Info::connection(),
d->win,
r.left(),
r.top(),
r.width(),
r.height(),
0xFFFFFFFF, // AllPlanes
XCB_IMAGE_FORMAT_Z_PIXMAP);
// manually copy pixels
int pxsize = d->framebufferImage->bpp / 8;
int pxsize = d->framebufferImage->bpp / 8;
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
char *src = (char *)damagedImage->data;
// loop every row in damaged image
for (int i = 0; i < damagedImage->height; i++) {
// copy whole row of pixels from src image to dest
memcpy(dest, src, damagedImage->stride);
dest += d->framebufferImage->stride; // move 1 row down in dest
src += damagedImage->stride; // move 1 row down in src
dest += d->framebufferImage->stride; // move 1 row down in dest
src += damagedImage->stride; // move 1 row down in src
}
//
xcb_image_destroy(damagedImage);
@@ -638,34 +646,37 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
// ^^ If we clear here all our known "damage areas", then we can also clear
// damaged area for xdamage? No, we don't need to in our case
// (XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES report mode)
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
return ret;
}
void XCBFrameBuffer::startMonitor() {
if (d->running) return;
void XCBFrameBuffer::startMonitor()
{
if (d->running) {
return;
}
d->running = true;
d->damage = xcb_generate_id(QX11Info::connection());
xcb_damage_create(QX11Info::connection(), d->damage, d->win,
XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
// (currently) we do not call xcb_damage_subtract() EVER, because
// RAW rectangles are reported. every time some area of the screen
// was changed, we get only that rectangle
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
}
void XCBFrameBuffer::stopMonitor() {
if (!d->running) return;
void XCBFrameBuffer::stopMonitor()
{
if (!d->running) {
return;
}
d->running = false;
xcb_damage_destroy(QX11Info::connection(), d->damage);
}
// void XCBFrameBuffer::acquireEvents() {} // this function was totally unused
// in X11 framebuffer, but it was the only function where XDamageSubtract() was called?
// Also it had a blocking event loop like:
@@ -679,12 +690,11 @@ void XCBFrameBuffer::stopMonitor() {
// This loop takes all available Xdamage events from queue, and ends if there are no
// more such events in input queue.
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent) {
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent)
{
auto xdevt = (xcb_damage_notify_event_t *)xevent;
QRect r((int)xdevt->area.x, (int)xdevt->area.y,
QRect r((int)xdevt->area.x, (int)xdevt->area.y,
(int)xdevt->area.width, (int)xdevt->area.height);
this->tiles.append(r);
}

View File

@@ -10,24 +10,23 @@
#include <QWidget>
#include <xcb/xcb.h>
/**
@author Alexey Min <alexey.min@gmail.com>
*/
class XCBFrameBuffer: public FrameBuffer
class XCBFrameBuffer : public FrameBuffer
{
Q_OBJECT
public:
explicit XCBFrameBuffer(QObject *parent = nullptr);
~XCBFrameBuffer() override;
public:
QList<QRect> modifiedTiles() override;
int depth() override;
int height() override;
int width() override;
int paddedWidth() override;
int depth() override;
int height() override;
int width() override;
int paddedWidth() override;
void getServerFormat(rfbPixelFormat &format) override;
void startMonitor() override;
void stopMonitor() override;

View File

@@ -4,7 +4,6 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "xcb_framebufferplugin.h"
#include "xcb_framebuffer.h"
#include <KPluginFactory>
@@ -23,4 +22,3 @@ FrameBuffer *XCBFrameBufferPlugin::frameBuffer(const QVariantMap &args)
}
#include "xcb_framebufferplugin.moc"

View File

@@ -1,31 +1,28 @@
/* This file is part of the KDE project
SPDX-FileCopyrightText: Alexey Min <alexey.min@gmail.com>
/* This file is part of the KDE project
SPDX-FileCopyrightText: Alexey Min <alexey.min@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
#define KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
#include "framebufferplugin.h"
#include <QWidget>
class FrameBuffer;
class XCBFrameBufferPlugin: public FrameBufferPlugin
class XCBFrameBufferPlugin : public FrameBufferPlugin
{
Q_OBJECT
Q_OBJECT
public:
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
FrameBuffer *frameBuffer(const QVariantMap &args) override;
FrameBuffer *frameBuffer(const QVariantMap &args) override;
private:
Q_DISABLE_COPY(XCBFrameBufferPlugin)
Q_DISABLE_COPY(XCBFrameBufferPlugin)
};
#endif // Header guard
#endif // Header guard