Skip to content

Commit

Permalink
feat: add portal wayland module
Browse files Browse the repository at this point in the history
 * Add portal wayland context.
 * Implement Screenshot.Screenshot.

Log: add portal wayland module
  • Loading branch information
asterwyx authored and justforlxz committed Jun 26, 2024
1 parent 8633f76 commit d911b90
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 553 deletions.
468 changes: 0 additions & 468 deletions LICENSES/LGPL-2.1-or-later.txt

This file was deleted.

2 changes: 1 addition & 1 deletion archlinux/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ arch=('x86_64' 'aarch64')
url='https://github.com/linuxdeepin/xdg-desktop-portal-dde'
license=('LGPL3')
depends=('qt6-base' 'qt6-wayland' 'wayland')
makedepends=('git' 'ninja' 'cmake' 'qt6-tools' 'wayland-protocols')
makedepends=('git' 'ninja' 'cmake' 'qt6-tools' 'wlr-protocols')
provides=('xdg-desktop-portal-impl')
groups=('deepin-git')
source=("${sourcetars[@]}")
Expand Down
8 changes: 6 additions & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ Build-Depends:
cmake (>= 3.0~),
dbus-x11,
debhelper (>= 11~),
pkgconf,
qt6-base-dev,
qt6-base-private-dev,
qt6-wayland,
qt6-wayland-dev,
qt6-wayland-private-dev,
qt6-wayland-dev-tools,
libpipewire-0.3-dev,
libwayland-dev,
wlr-protocols,
Standards-Version: 4.5.0

Package: xdg-desktop-portal-dde
Architecture: any
Depends:
${shlibs:Depends},
Depends:
${shlibs:Depends},
${misc:Depends}
Description: Dtk poortal backend for xdg-desktop-portal
xdg-desktop-portal-dde provide a DTK implementation for the
Expand Down
77 changes: 0 additions & 77 deletions misc/zkde-screencast-unstable-v1.xml

This file was deleted.

6 changes: 5 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
Qt::Gui
Qt::DBus
Qt::Concurrent
Qt::WaylandClient)
Qt::WaylandClient
xdg-desktop-portal-dde-wayland
)

install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})

add_subdirectory(wayland)
34 changes: 34 additions & 0 deletions src/wayland/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
find_package(PkgConfig REQUIRED)
pkg_get_variable(WlrProtocols_PKGDATADIR wlr-protocols pkgdatadir)
find_package(Qt6 COMPONENTS REQUIRED Core DBus WaylandClient WaylandScannerTools)

add_library(xdg-desktop-portal-dde-wayland SHARED
portalwaylandcontext.h
portalwaylandcontext.cpp
screenshotportal.h
screenshotportal.cpp
abstractwaylandportal.h
protocols/screencopy.h
protocols/screencopy.cpp
protocols/common.h
)

qt_generate_wayland_protocol_client_sources(xdg-desktop-portal-dde-wayland FILES
${WlrProtocols_PKGDATADIR}/unstable/wlr-screencopy-unstable-v1.xml
)

target_include_directories(xdg-desktop-portal-dde-wayland
PUBLIC
${PROJECT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
)

target_link_libraries(xdg-desktop-portal-dde-wayland
PUBLIC
Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::DBus
Qt6::GuiPrivate
Qt6::WaylandClientPrivate
)
21 changes: 21 additions & 0 deletions src/wayland/abstractwaylandportal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include "portalwaylandcontext.h"

#include <QObject>
#include <QPointer>
#include <QDBusAbstractAdaptor>

class AbstractWaylandPortal : public QDBusAbstractAdaptor
{
public:
AbstractWaylandPortal(PortalWaylandContext *context) : QDBusAbstractAdaptor(context), m_context(context) { }
QPointer<PortalWaylandContext> context() { return m_context; }

private:
QPointer<PortalWaylandContext> m_context;
};
22 changes: 22 additions & 0 deletions src/wayland/portalwaylandcontext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "portalwaylandcontext.h"
#include "screenshotportal.h"

#include <QGuiApplication>
#include <qpa/qplatformintegration.h>
#include <private/qwaylandintegration_p.h>
#include <private/qguiapplication_p.h>
#include <QTimer>

using namespace QtWaylandClient;

PortalWaylandContext::PortalWaylandContext(QObject *parent)
: QObject(parent)
, QDBusContext()
, m_screenCopyManager(new ScreenCopyManager(this))
{
auto screenShotPortal = new ScreenshotPortalWayland(this);
}
21 changes: 21 additions & 0 deletions src/wayland/portalwaylandcontext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include "protocols/screencopy.h"

#include <QDBusContext>
#include <private/qwaylanddisplay_p.h>

class PortalWaylandContext : public QObject, public QDBusContext
{
Q_OBJECT

public:
PortalWaylandContext(QObject *parent = nullptr);
inline QPointer<ScreenCopyManager> screenCopyManager() { return m_screenCopyManager; }
private:
ScreenCopyManager *m_screenCopyManager;
};
20 changes: 20 additions & 0 deletions src/wayland/protocols/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <private/qguiapplication_p.h>
#include <private/qwaylanddisplay_p.h>
#include <private/qwaylandintegration_p.h>
#include <QPointer>

inline QtWaylandClient::QWaylandIntegration *waylandIntegration()
{
return dynamic_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration());
}

inline QPointer<QtWaylandClient::QWaylandDisplay> waylandDisplay()
{
return waylandIntegration()->display();
}
81 changes: 81 additions & 0 deletions src/wayland/protocols/screencopy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "screencopy.h"
#include "common.h"


Q_LOGGING_CATEGORY(portalWaylandProtocol, "dde.portal.wayland.protocol");
ScreenCopyManager::ScreenCopyManager(QObject *parent)
: QWaylandClientExtensionTemplate<ScreenCopyManager, destruct_screen_copy_manager>(1)
, QtWayland::zwlr_screencopy_manager_v1()
{ }

ScreenCopyFrame::ScreenCopyFrame(struct ::zwlr_screencopy_frame_v1 *object)
: QObject(nullptr)
, QtWayland::zwlr_screencopy_frame_v1(object)
, m_shmBuffer(nullptr)
, m_pendingShmBuffer(nullptr)
{ }

QPointer<ScreenCopyFrame> ScreenCopyManager::captureOutput(int32_t overlay_cursor, struct ::wl_output *output)
{
auto screen_copy_frame = capture_output(overlay_cursor, output);
auto screenCopyFrame = new ScreenCopyFrame(screen_copy_frame);
m_screenCopyFrames.append(screenCopyFrame);
return screenCopyFrame;
}

QPointer<ScreenCopyFrame> ScreenCopyManager::captureOutputRegion(int32_t overlay_cursor, struct ::wl_output *output, int32_t x, int32_t y, int32_t width, int32_t height)
{
auto screen_copy_frame = capture_output_region(overlay_cursor, output, x, y, width, height);
auto screenCopyFrame = new ScreenCopyFrame(screen_copy_frame);
m_screenCopyFrames.append(screenCopyFrame);
return screenCopyFrame;
}

void ScreenCopyFrame::zwlr_screencopy_frame_v1_buffer(uint32_t format, uint32_t width, uint32_t height, uint32_t stride)
{
// Create a new wl_buffer for reception
// For some reason, Qt regards stride == width * 4, and it creates buffer likewise, we must check this
if (stride != width * 4) {
qCDebug(portalWaylandProtocol)
<< "Receive a buffer format which is not compatible with QWaylandShmBuffer."
<< "format:" << format << "width:" << width << "height:" << height
<< "stride:" << stride;
return;
}
if (m_pendingShmBuffer)
return; // We only need one supported format
m_pendingShmBuffer = new QtWaylandClient::QWaylandShmBuffer(waylandDisplay(), QSize(width, height), QtWaylandClient::QWaylandShm::formatFrom(static_cast<::wl_shm_format>(format)));
copy(m_pendingShmBuffer->buffer());
}

void ScreenCopyFrame::zwlr_screencopy_frame_v1_flags(uint32_t flags)
{
m_flags = static_cast<QtWayland::zwlr_screencopy_frame_v1::flags>(flags);
}

void ScreenCopyFrame::zwlr_screencopy_frame_v1_failed()
{
Q_EMIT failed();
}

void ScreenCopyFrame::zwlr_screencopy_frame_v1_ready(uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec)
{
Q_UNUSED(tv_sec_hi);
Q_UNUSED(tv_sec_lo);
Q_UNUSED(tv_nsec);
if (m_shmBuffer)
delete m_shmBuffer;
m_shmBuffer = m_pendingShmBuffer;
m_pendingShmBuffer = nullptr;
Q_EMIT ready(*m_shmBuffer->image());
}

void destruct_screen_copy_manager(ScreenCopyManager *screenCopyManager)
{
qDeleteAll(screenCopyManager->m_screenCopyFrames);
screenCopyManager->m_screenCopyFrames.clear();
}
50 changes: 50 additions & 0 deletions src/wayland/protocols/screencopy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <private/qwaylandclientextension_p.h>
#include <qwayland-wlr-screencopy-unstable-v1.h>
#include <QList>
#include <QPointer>
#include <private/qwaylandshmbackingstore_p.h>

class ScreenCopyFrame : public QObject, public QtWayland::zwlr_screencopy_frame_v1
{
Q_OBJECT
public:
ScreenCopyFrame(struct ::zwlr_screencopy_frame_v1 *object);
QtWayland::zwlr_screencopy_frame_v1::flags flags();

Q_SIGNALS:
void ready(QImage image);
void failed();

protected:
void zwlr_screencopy_frame_v1_buffer(uint32_t format, uint32_t width, uint32_t height, uint32_t stride) override;
void zwlr_screencopy_frame_v1_flags(uint32_t flags) override;
void zwlr_screencopy_frame_v1_ready(uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) override;
void zwlr_screencopy_frame_v1_failed() override;

private:
QtWaylandClient::QWaylandShmBuffer *m_shmBuffer;
QtWaylandClient::QWaylandShmBuffer *m_pendingShmBuffer;
QtWayland::zwlr_screencopy_frame_v1::flags m_flags;
};

class ScreenCopyManager;
void destruct_screen_copy_manager(ScreenCopyManager *screenCopyManager);
class ScreenCopyManager : public QWaylandClientExtensionTemplate<ScreenCopyManager, destruct_screen_copy_manager>, public QtWayland::zwlr_screencopy_manager_v1
{
Q_OBJECT
public:
ScreenCopyManager(QObject *parent = nullptr);

QPointer<ScreenCopyFrame> captureOutput(int32_t overlay_cursor, struct ::wl_output *output);
QPointer<ScreenCopyFrame> captureOutputRegion(int32_t overlay_cursor, struct ::wl_output *output, int32_t x, int32_t y, int32_t width, int32_t height);

private:
QList<ScreenCopyFrame *> m_screenCopyFrames;
friend void destruct_screen_copy_manager(ScreenCopyManager *screenCopyManager);
};
Loading

0 comments on commit d911b90

Please sign in to comment.