Commit e4a788d8 authored by Jan Grulich's avatar Jan Grulich

Merge branch 'jgrulich/remotedesktop'

parents 3bcb6459 fcbbedd8
[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
......@@ -25,11 +25,17 @@ if (SCREENCAST_ENABLED)
set (xdg_desktop_portal_kde_SRCS
${xdg_desktop_portal_kde_SRCS}
screencast.cpp
screencastcommon.cpp
screencaststream.cpp
screenchooserdialog.cpp)
screencastwidget.cpp
screenchooserdialog.cpp
remotedesktop.cpp
remotedesktopdialog.cpp
waylandintegration.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,9 +39,13 @@ 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))
{
#if SCREENCAST_ENABLED
WaylandIntegration::init();
#endif
}
DesktopPortal::~DesktopPortal()
......
......@@ -33,6 +33,8 @@
#include "print.h"
#if SCREENCAST_ENABLED
#include "screencast.h"
#include "remotedesktop.h"
#include "waylandintegration.h"
#endif
#include "screenshot.h"
......@@ -53,6 +55,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 "screencastcommon.h"
#include "session.h"
#include "remotedesktopdialog.h"
#include "waylandintegration.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeRemoteDesktop, "xdp-kde-remotedesktop")
RemoteDesktopPortal::RemoteDesktopPortal(QObject *parent)
: QDBusAbstractAdaptor(parent)
, m_screenCastCommon(new ScreenCastCommon())
{
}
RemoteDesktopPortal::~RemoteDesktopPortal()
{
if (m_screenCastCommon) {
delete m_screenCastCommon;
}
}
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] () {
m_screenCastCommon->stopStreaming();
});
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;
RemoteDesktopSession *session = qobject_cast<RemoteDesktopSession*>(Session::getSession(session_handle.path()));
if (!session) {
qCWarning(XdgDesktopPortalKdeRemoteDesktop) << "Tried to call start on non-existing session " << session_handle.path();
return 2;
}
// TODO check whether we got some outputs?
if (WaylandIntegration::screens().isEmpty()) {
qCWarning(XdgDesktopPortalKdeRemoteDesktop) << "Failed to show dialog as there is no screen to select";
return 2;
}
QScopedPointer<RemoteDesktopDialog, QScopedPointerDeleteLater> remoteDesktopDialog(new RemoteDesktopDialog(app_id, session->deviceTypes(), session->screenSharingEnabled(), session->multipleSources()));
if (remoteDesktopDialog->exec()) {
if (session->screenSharingEnabled()) {
WaylandIntegration::WaylandOutput selectedOutput = WaylandIntegration::screens().value(remoteDesktopDialog->selectedScreens().first());
QVariant streams = m_screenCastCommon->startStreaming(selectedOutput);
if (!streams.isValid()) {
qCWarning(XdgDesktopPortalKdeRemoteDesktop()) << "Pipewire stream is not ready to be streamed";
return 2;
}
results.insert(QLatin1String("streams"), streams);
}
// TODO devices
return 0;
}
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 ScreenCastCommon;
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:
ScreenCastCommon *m_screenCastCommon;
};
#endif // XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_H
/*
* 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 "remotedesktopdialog.h"
#include "ui_remotedesktopdialog.h"
#include <QLoggingCategory>
#include <QStandardPaths>
#include <QSettings>
#include <QPushButton>
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeRemoteDesktopDialog, "xdp-kde-remote-desktop-dialog")
RemoteDesktopDialog::RemoteDesktopDialog(const QString &appName, RemoteDesktopPortal::DeviceTypes deviceTypes, bool screenSharingEnabled,
bool multiple, QDialog *parent, Qt::WindowFlags flags)
: QDialog(parent, flags)
, m_dialog(new Ui::RemoteDesktopDialog)
{
m_dialog->setupUi(this);
m_dialog->screenCastWidget->setVisible(screenSharingEnabled);
if (screenSharingEnabled) {
connect(m_dialog->screenCastWidget, &QListWidget::itemDoubleClicked, this, &RemoteDesktopDialog::accept);
if (multiple) {
m_dialog->screenCastWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
}
// TODO
connect(m_dialog->buttonBox, &QDialogButtonBox::accepted, this, &RemoteDesktopDialog::accept);
connect(m_dialog->buttonBox, &QDialogButtonBox::rejected, this, &RemoteDesktopDialog::reject);
m_dialog->buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Share"));
QString applicationName;
const QString desktopFile = appName + QLatin1String(".desktop");
const QStringList desktopFilesLocations = QStandardPaths::locateAll(QStandardPaths::ApplicationsLocation, desktopFile, QStandardPaths::LocateFile);
QSettings settings(desktopFile, QSettings::IniFormat);
settings.beginGroup(QLatin1String("Desktop Entry"));
if (settings.contains(QLatin1String("X-GNOME-FullName"))) {
applicationName = settings.value(QLatin1String("X-GNOME-FullName")).toString();
} else {
applicationName = settings.value(QLatin1String("Name")).toString();
}
if (applicationName.isEmpty()) {
setWindowTitle(i18n("Select what to share with the requesting application"));
} else {
setWindowTitle(i18n("Select what to share with %1").arg(applicationName));
}
}
RemoteDesktopDialog::~RemoteDesktopDialog()
{
delete m_dialog;
}
QList<quint32> RemoteDesktopDialog::selectedScreens() const
{
return m_dialog->screenCastWidget->selectedScreens();
}
RemoteDesktopPortal::DeviceTypes RemoteDesktopDialog::deviceTypes() const
{
return 0;
}
/*
* 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_DIALOG_H
#define XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_DIALOG_H
#include <QAbstractListModel>
#include <QDialog>
#include "remotedesktop.h"
namespace Ui
{
class RemoteDesktopDialog;
}
class RemoteDesktopDialog : public QDialog
{
Q_OBJECT
public:
RemoteDesktopDialog(const QString &appName, RemoteDesktopPortal::DeviceTypes deviceTypes, bool screenSharingEnabled = false,
bool multiple = false, QDialog *parent = nullptr, Qt::WindowFlags flags = {});
~RemoteDesktopDialog();
QList<quint32> selectedScreens() const;
RemoteDesktopPortal::DeviceTypes deviceTypes() const;
private:
Ui::RemoteDesktopDialog * m_dialog;
};
#endif // XDG_DESKTOP_PORTAL_KDE_REMOTEDESKTOP_DIALOG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RemoteDesktopDialog</class>
<widget class="QDialog" name="RemoteDesktopDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>452</width>
<height>286</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="ScreenCastWidget" name="screenCastWidget">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="iconSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Allow access to:</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="pointerCheckbox">
<property name="text">
<string>Pointer</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="keyboardCheckbox">
<property name="text">
<string>Keyboard</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="touchScreenCheckbox">
<property name="text">
<string>Touch screen</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">