Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add portal wayland module #47

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading