Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit cd513b72 authored by Jan Grulich's avatar Jan Grulich

Initial work on remote desktop

parent ddd12bc7
[portal]
DBusName=org.freedesktop.impl.portal.desktop.kde
Interfaces=org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.AppChooser;org.freedesktop.impl.portal.Email;org.freedesktop.impl.portal.FileChooser;org.freedesktop.impl.portal.Inhibit;org.freedesktop.impl.portal.Notification;org.freedesktop.impl.portal.Print;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.Screenshot
Interfaces=org.freedesktop.impl.portal.Access;org.freedesktop.impl.portal.AppChooser;org.freedesktop.impl.portal.Email;org.freedesktop.impl.portal.FileChooser;org.freedesktop.impl.portal.Inhibit;org.freedesktop.impl.portal.Notification;org.freedesktop.impl.portal.Print;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.RemoteDesktop
UseIn=KDE
......@@ -26,10 +26,13 @@ if (SCREENCAST_ENABLED)
${xdg_desktop_portal_kde_SRCS}
screencast.cpp
screencaststream.cpp
screenchooserdialog.cpp)
screenchooserdialog.cpp
remotedesktop.cpp
remotedesktopdialog.cpp)
ki18n_wrap_ui(xdg_desktop_portal_kde_SRCS
screenchooserdialog.ui)
screenchooserdialog.ui
remotedesktopdialog.ui)
endif()
ki18n_wrap_ui(xdg_desktop_portal_kde_SRCS
......
......@@ -39,6 +39,7 @@ DesktopPortal::DesktopPortal(QObject *parent)
, m_print(new PrintPortal(this))
#if SCREENCAST_ENABLED
, m_screenCast(new ScreenCastPortal(this))
, m_remoteDesktop(new RemoteDesktopPortal(this))
#endif
, m_screenshot(new ScreenshotPortal(this))
{
......
......@@ -33,6 +33,7 @@
#include "print.h"
#if SCREENCAST_ENABLED
#include "screencast.h"
#include "remotedesktop.h"
#endif
#include "screenshot.h"
......@@ -53,6 +54,7 @@ private:
PrintPortal *m_print;
#if SCREENCAST_ENABLED
ScreenCastPortal *m_screenCast;
RemoteDesktopPortal *m_remoteDesktop;
#endif
ScreenshotPortal *m_screenshot;
};
......
/*
* Copyright © 2018 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jan Grulich <jgrulich@redhat.com>
*/
#include "remotedesktop.h"
#include "session.h"
#include <QDateTime>
#include <QtDBus/QtDBus>
#include <QDBusArgument>
#include <QDBusReply>
#include <QLoggingCategory>
#include <QStandardPaths>
#include <QPointer>
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeRemoteDesktop, "xdp-kde-remotedesktop")
RemoteDesktopPortal::RemoteDesktopPortal(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
}
RemoteDesktopPortal::~RemoteDesktopPortal()
{
}
uint RemoteDesktopPortal::CreateSession(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << "CreateSession called with parameters:";
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " session_handle: " << session_handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " options: " << options;
Session *session = Session::createSession(this, Session::RemoteDesktop, app_id, session_handle.path());
if (!session) {
return 2;
}
connect(session, &Session::closed, [this] () {
// TODO
});
return 0;
}
uint RemoteDesktopPortal::SelectDevices(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << "SelectDevices called with parameters:";
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " session_handle: " << session_handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " options: " << options;
RemoteDesktopPortal::DeviceTypes types = RemoteDesktopPortal::All;
RemoteDesktopSession *session = qobject_cast<RemoteDesktopSession*>(Session::getSession(session_handle.path()));
if (!session) {
qCWarning(XdgDesktopPortalKdeRemoteDesktop) << "Tried to select sources on non-existing session " << session_handle.path();
return 2;
}
if (options.contains(QLatin1String("types"))) {
types = (DeviceTypes)(options.value(QLatin1String("types")).toUInt());
}
session->setDeviceTypes(types);
return 0;
}
uint RemoteDesktopPortal::Start(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QString &parent_window,
const QVariantMap &options,
QVariantMap &results)
{
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << "Start called with parameters:";
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " handle: " << handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " session_handle: " << session_handle.path();
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeRemoteDesktop) << " options: " << options;
return 0;
}
void RemoteDesktopPortal::NotifyPointerMotion(const QDBusObjectPath &session_handle,
const QVariantMap &options,
double dx,
double dy)
{
}
void RemoteDesktopPortal::NotifyPointerMotionAbsolute(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
double dx,
double dy)
{
}
void RemoteDesktopPortal::NotifyPointerButton(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int button,
uint state)
{
}
void RemoteDesktopPortal::NotifyPointerAxis(const QDBusObjectPath &session_handle,
const QVariantMap &options,
double dx,
double dy)
{
}
void RemoteDesktopPortal::NotifyPointerAxisDiscrete(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint axis,
int steps)
{
}
void RemoteDesktopPortal::NotifyKeyboardKeysym(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int keysym,
uint state)
{
}
void RemoteDesktopPortal::NotifyKeyboardKeycode(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int keycode,
uint state)
{
}
void RemoteDesktopPortal::NotifyTouchDown(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
uint slot,
int x,
int y)
{
}
void RemoteDesktopPortal::NotifyTouchMotion(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
uint slot,
int x,
int y)
{
}
void RemoteDesktopPortal::NotifyTouchUp(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint slot)
{
}
/*
* Copyright © 2018 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Jan Grulich <jgrulich@redhat.com>
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_H
#define XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_H
#include <QDBusAbstractAdaptor>
#include <QDBusObjectPath>
class Session;
class RemoteDesktopPortal : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.impl.portal.RemoteDesktop")
public:
explicit RemoteDesktopPortal(QObject *parent);
~RemoteDesktopPortal();
enum DeviceType {
None = 0x0,
Keyboard = 0x1,
Pointer = 0x2,
TouchScreen = 0x4,
All = (Keyboard | Pointer | TouchScreen)
};
Q_DECLARE_FLAGS(DeviceTypes, DeviceType)
uint version() const { return 1; }
uint AvailableDeviceTypes() const { return All; };
public Q_SLOTS:
uint CreateSession(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QVariantMap &options,
QVariantMap &results);
uint SelectDevices(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QVariantMap &options,
QVariantMap &results);
uint Start(const QDBusObjectPath &handle,
const QDBusObjectPath &session_handle,
const QString &app_id,
const QString &parent_window,
const QVariantMap &options,
QVariantMap &results);
void NotifyPointerMotion(const QDBusObjectPath &session_handle,
const QVariantMap &options,
double dx,
double dy);
void NotifyPointerMotionAbsolute(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
double dx,
double dy);
void NotifyPointerButton(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int button,
uint state);
void NotifyPointerAxis(const QDBusObjectPath &session_handle,
const QVariantMap &options,
double dx,
double dy);
void NotifyPointerAxisDiscrete(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint axis,
int steps);
void NotifyKeyboardKeycode(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int keycode,
uint state);
void NotifyKeyboardKeysym(const QDBusObjectPath &session_handle,
const QVariantMap &options,
int keysym,
uint state);
void NotifyTouchDown(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
uint slot,
int x,
int y);
void NotifyTouchMotion(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint stream,
uint slot,
int x,
int y);
void NotifyTouchUp(const QDBusObjectPath &session_handle,
const QVariantMap &options,
uint slot);
private:
};
#endif // XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_H
......@@ -296,23 +296,17 @@ uint ScreenCastPortal::CreateSession(const QDBusObjectPath &handle,
qCDebug(XdgDesktopPortalKdeScreenCast) << " app_id: " << app_id;
qCDebug(XdgDesktopPortalKdeScreenCast) << " options: " << options;
QDBusConnection sessionBus = QDBusConnection::sessionBus();
Session *session = new Session(this, app_id, session_handle.path());
if (sessionBus.registerVirtualObject(session_handle.path(), session, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
connect(session, &Session::closed, [this, session, session_handle] () {
m_sessionList.remove(session_handle.path());
QDBusConnection::sessionBus().unregisterObject(session_handle.path());
session->deleteLater();
stopStreaming();
});
m_sessionList.insert(session_handle.path(), session);
return 0;
} else {
qCDebug(XdgDesktopPortalKdeScreenCast) << sessionBus.lastError().message();
qCDebug(XdgDesktopPortalKdeScreenCast) << "Failed to register session object: " << session_handle.path();
session->deleteLater();
Session *session = Session::createSession(this, Session::ScreenCast, app_id, session_handle.path());
if (!session) {
return 2;
}
connect(session, &Session::closed, [this] () {
stopStreaming();
});
return 0;
}
uint ScreenCastPortal::SelectSources(const QDBusObjectPath &handle,
......@@ -330,9 +324,8 @@ uint ScreenCastPortal::SelectSources(const QDBusObjectPath &handle,
qCDebug(XdgDesktopPortalKdeScreenCast) << " options: " << options;
uint types = Monitor;
Session *session = nullptr;
session = m_sessionList.value(session_handle.path());
ScreenCastSession *session = qobject_cast<ScreenCastSession*>(Session::getSession(session_handle.path()));
if (!session) {
qCWarning(XdgDesktopPortalKdeScreenCast) << "Tried to select sources on non-existing session " << session_handle.path();
......@@ -371,8 +364,7 @@ uint ScreenCastPortal::Start(const QDBusObjectPath &handle,
qCDebug(XdgDesktopPortalKdeScreenCast) << " parent_window: " << parent_window;
qCDebug(XdgDesktopPortalKdeScreenCast) << " options: " << options;
Session *session = nullptr;
session = m_sessionList.value(session_handle.path());
ScreenCastSession *session = qobject_cast<ScreenCastSession*>(Session::getSession(session_handle.path()));
if (!session) {
qCWarning(XdgDesktopPortalKdeScreenCast) << "Tried to select sources on non-existing session " << session_handle.path();
......
......@@ -42,7 +42,6 @@ namespace KWayland {
}
}
class Session;
class ScreenChooserDialog;
class ScreenCastStream;
......@@ -131,7 +130,6 @@ private:
bool m_registryInitialized;
bool m_streamingEnabled;
QMap<QString, Session*> m_sessionList;
QMap<quint32, ScreenCastPortalOutput> m_outputMap;
QList<KWayland::Client::Output*> m_bindOutputs;
......
......@@ -31,9 +31,10 @@
Q_LOGGING_CATEGORY(XdgSessionKdeSession, "xdp-kde-session")
static QMap<QString, Session*> sessionList;
Session::Session(QObject *parent, const QString &appId, const QString &path)
: QDBusVirtualObject(parent)
, m_multipleSources(false)
, m_appId(appId)
, m_path(path)
{
......@@ -108,19 +109,78 @@ QString Session::introspect(const QString &path) const
return nodes;
}
bool Session::multipleSources() const
bool Session::close()
{
QDBusMessage reply = QDBusMessage::createSignal(m_path, QLatin1String("org.freedesktop.impl.portal.Session"), QLatin1String("Closed"));
return QDBusConnection::sessionBus().send(reply);
}
Session * Session::createSession(QObject *parent, SessionType type, const QString &appId, const QString &path)
{
QDBusConnection sessionBus = QDBusConnection::sessionBus();
Session *session = nullptr;
if (type == ScreenCast) {
session = new ScreenCastSession(parent, appId, path);
} else {
session = new RemoteDesktopSession(parent, appId, path);
}
if (sessionBus.registerVirtualObject(path, session, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
connect(session, &Session::closed, [session, path] () {
sessionList.remove(path);
QDBusConnection::sessionBus().unregisterObject(path);
session->deleteLater();
});
sessionList.insert(path, session);
return session;
} else {
qCDebug(XdgSessionKdeSession) << sessionBus.lastError().message();
qCDebug(XdgSessionKdeSession) << "Failed to register session object: " << path;
session->deleteLater();
return nullptr;
}
}
Session * Session::getSession(const QString &sessionHandle)
{
return sessionList.value(sessionHandle);
}
ScreenCastSession::ScreenCastSession(QObject *parent, const QString &appId, const QString &path)
: Session(parent, appId, path)
{
}
ScreenCastSession::~ScreenCastSession()
{
}
bool ScreenCastSession::multipleSources() const
{
return m_multipleSources;
}
void Session::setMultipleSources(bool multipleSources)
void ScreenCastSession::setMultipleSources(bool multipleSources)
{
m_multipleSources = multipleSources;
}
bool Session::close()
RemoteDesktopSession::RemoteDesktopSession(QObject *parent, const QString &appId, const QString &path)
: ScreenCastSession(parent, appId, path)
{
QDBusMessage reply = QDBusMessage::createSignal(m_path, QLatin1String("org.freedesktop.impl.portal.Session"), QLatin1String("Closed"));
return QDBusConnection::sessionBus().send(reply);
}
RemoteDesktopSession::~RemoteDesktopSession()
{
}
RemoteDesktopPortal::DeviceTypes RemoteDesktopSession::deviceTypes() const
{
return m_deviceTypes;
}
void RemoteDesktopSession::setDeviceTypes(RemoteDesktopPortal::DeviceTypes deviceTypes)
{
m_deviceTypes = deviceTypes;
}
......@@ -24,6 +24,8 @@
#include <QObject>
#include <QDBusVirtualObject>
#include "remotedesktop.h"
class Session : public QDBusVirtualObject
{
Q_OBJECT
......@@ -31,22 +33,54 @@ public:
explicit Session(QObject *parent = nullptr, const QString &appId = QString(), const QString &path = QString());
~Session();
enum SessionType {
ScreenCast = 0,
RemoteDesktop = 1
};
bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) override;
QString introspect(const QString &path) const override;
bool close();
bool multipleSources() const;
void setMultipleSources(bool multipleSources);
static Session *createSession(QObject *parent, SessionType type, const QString &appId, const QString &path);
static Session *getSession(const QString &sessionHandle);
Q_SIGNALS:
void closed();
private:
bool m_multipleSources;
const QString m_appId;
const QString m_path;
};
class ScreenCastSession : public Session
{
Q_OBJECT
public:
explicit ScreenCastSession(QObject *parent = nullptr, const QString &appId = QString(), const QString &path = QString());
~ScreenCastSession();
bool multipleSources() const;
void setMultipleSources(bool multipleSources);
private:
bool m_multipleSources;
// TODO type
};
class RemoteDesktopSession : public ScreenCastSession
{
Q_OBJECT
public:
explicit RemoteDesktopSession(QObject *parent = nullptr, const QString &appId = QString(), const QString &path = QString());
~RemoteDesktopSession();
RemoteDesktopPortal::DeviceTypes deviceTypes() const;
void setDeviceTypes(RemoteDesktopPortal::DeviceTypes deviceTypes);
private:
RemoteDesktopPortal::DeviceTypes m_deviceTypes;
};
#endif // XDG_DESKTOP_PORTAL_KDE_SESSION_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment