1
0
mirror of https://github.com/KDE/krfb synced 2026-07-02 00:01:18 -07:00

Compare commits

..

7 Commits

Author SHA1 Message Date
Christoph Feck
8432171959 GIT_SILENT Upgrade KDE Applications version to 19.04.3. 2019-07-06 11:31:27 +02:00
Christoph Feck
ed7cb43440 GIT_SILENT Upgrade KDE Applications version to 19.04.2. 2019-05-31 12:34:01 +02:00
Christoph Feck
2f8761080f GIT_SILENT Upgrade KDE Applications version to 19.04.1. 2019-05-02 12:51:42 +02:00
l10n daemon script
e21d3844bd GIT_SILENT made messages (after extraction) 2019-04-22 07:59:22 +02:00
Christoph Feck
827e1f12e5 GIT_SILENT Upgrade KDE Applications version to 19.04.0. 2019-04-08 14:06:39 +02:00
Christoph Feck
c8d6973f9f GIT_SILENT Upgrade KDE Applications version to 19.03.90. 2019-03-31 14:08:44 +02:00
Albert Astals Cid
ee879c4e4c GIT_SILENT Upgrade KDE Applications version to 19.03.80. 2019-03-16 22:03:48 +01:00
58 changed files with 238 additions and 3275 deletions

View File

@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.0)
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "20")
set (RELEASE_SERVICE_VERSION_MINOR "04")
set (RELEASE_SERVICE_VERSION_MICRO "3")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
set (KDE_APPLICATIONS_VERSION_MAJOR "19")
set (KDE_APPLICATIONS_VERSION_MINOR "04")
set (KDE_APPLICATIONS_VERSION_MICRO "3")
set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}")
project(krfb VERSION ${RELEASE_SERVICE_VERSION})
project(krfb VERSION ${KDE_APPLICATIONS_VERSION})
set(QT_MIN_VERSION 5.6.0)
set(KF5_MIN_VERSION 5.31.0)
@@ -21,9 +21,6 @@ include(ECMInstallIcons)
include(ECMAddAppIcon)
include(ECMSetupVersion)
include(FeatureSummary)
include(CheckIncludeFile)
check_include_file("linux/input.h" HAVE_LINUX_INPUT_H)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core DBus Widgets X11Extras)
@@ -39,7 +36,6 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Notifications
Wallet
WidgetsAddons
WindowSystem
XmlGui
)
@@ -77,12 +73,6 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} )
find_package(LibVNCServer REQUIRED)
find_package(PipeWire)
set_package_properties(PipeWire PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for pipewire screencast plugin"
)
ecm_setup_version(PROJECT
VARIABLE_PREFIX KRFB
VERSION_HEADER "krfb_version.h")
@@ -98,7 +88,6 @@ if(Q_WS_X11)
endif(NOT X11_XTest_FOUND)
endif(Q_WS_X11)
add_subdirectory(events)
add_subdirectory(krfb)
add_subdirectory(framebuffers)
add_subdirectory(doc)

View File

@@ -1,122 +0,0 @@
#.rst:
# FindPipeWire
# -------
#
# Try to find PipeWire on a Unix system.
#
# This will define the following variables:
#
# ``PipeWire_FOUND``
# True if (the requested version of) PipeWire is available
# ``PipeWire_VERSION``
# The version of PipeWire
# ``PipeWire_LIBRARIES``
# This can be passed to target_link_libraries() instead of the ``PipeWire::PipeWire``
# target
# ``PipeWire_INCLUDE_DIRS``
# This should be passed to target_include_directories() if the target is not
# used for linking
# ``PipeWire_DEFINITIONS``
# This should be passed to target_compile_options() if the target is not
# used for linking
#
# If ``PipeWire_FOUND`` is TRUE, it will also define the following imported target:
#
# ``PipeWire::PipeWire``
# The PipeWire library
#
# In general we recommend using the imported target, as it is easier to use.
# Bear in mind, however, that if the target is in the link interface of an
# exported library, it must be made available by the package config file.
#=============================================================================
# Copyright 2014 Alex Merry <alex.merry@kde.org>
# Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
# Copyright 2018-2020 Jan Grulich <jgrulich@redhat.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig QUIET)
pkg_search_module(PKG_PipeWire QUIET libpipewire-0.3 libpipewire-0.2)
pkg_search_module(PKG_Spa QUIET libspa-0.2 libspa-0.1)
set(PipeWire_DEFINITIONS "${PKG_PipeWire_CFLAGS}" "${PKG_Spa_CFLAGS}")
set(PipeWire_VERSION "${PKG_PipeWire_VERSION}")
find_path(PipeWire_INCLUDE_DIRS
NAMES
pipewire/pipewire.h
HINTS
${PKG_PipeWire_INCLUDE_DIRS}
${PKG_PipeWire_INCLUDE_DIRS}/pipewire-0.3
)
find_path(Spa_INCLUDE_DIRS
NAMES
spa/param/props.h
HINTS
${PKG_Spa_INCLUDE_DIRS}
${PKG_Spa_INCLUDE_DIRS}/spa-0.2
)
find_library(PipeWire_LIBRARIES
NAMES
pipewire-0.3
pipewire-0.2
HINTS
${PKG_PipeWire_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PipeWire
FOUND_VAR
PipeWire_FOUND
REQUIRED_VARS
PipeWire_LIBRARIES
PipeWire_INCLUDE_DIRS
Spa_INCLUDE_DIRS
VERSION_VAR
PipeWire_VERSION
)
if(PipeWire_FOUND AND NOT TARGET PipeWire::PipeWire)
add_library(PipeWire::PipeWire UNKNOWN IMPORTED)
set_target_properties(PipeWire::PipeWire PROPERTIES
IMPORTED_LOCATION "${PipeWire_LIBRARIES}"
INTERFACE_COMPILE_OPTIONS "${PipeWire_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${PipeWire_INCLUDE_DIRS};${Spa_INCLUDE_DIRS}"
)
endif()
mark_as_advanced(PipeWire_LIBRARIES PipeWire_INCLUDE_DIRS)
include(FeatureSummary)
set_package_properties(PipeWire PROPERTIES
URL "https://www.pipewire.org"
DESCRIPTION "PipeWire - multimedia processing"
)

View File

@@ -1,374 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright (C) 2017-2018 Red Hat, Inc.
This library 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/>.
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.freedesktop.portal.RemoteDesktop:
@short_description: Remote desktop portal
The Remote desktop portal allows to create remote desktop sessions.
This documentation describes version 1 of this interface.
-->
<interface name="org.freedesktop.portal.RemoteDesktop">
<!--
CreateSession:
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Create a remote desktop session.
A remote desktop session is used to allow remote controlling a desktop
session. It can also be used together with a screen cast session (see
org.freedesktop.portal.ScreenCast), but may only be started and stopped
with this interface.
To also get a screen content, call the
#org.freedesktop.ScreenCast.SelectSources with the
#org.freedesktop.Session object created with this method.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>handle_token s</term>
<listitem><para>
A string that will be used as the last element of the @handle. Must be a valid
object path element. See the #org.freedesktop.portal.Request documentation for
more information about the @handle.
</para></listitem>
</varlistentry>
<varlistentry>
<term>session_handle_token s</term>
<listitem><para>
A string that will be used as the last element of the session handle. Must be a valid
object path element. See the #org.freedesktop.portal.Session documentation for
more information about the session handle.
</para></listitem>
</varlistentry>
</variablelist>
The following results get returned via the #org.freedesktop.portal.Request::Response signal:
<variablelist>
<varlistentry>
<term>session_handle o</term>
<listitem><para>
The session handle. An object path for the
#org.freedesktop.portal.Session object representing the created
session.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="CreateSession">
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
SelectDevices:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Select input devices to remote control.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>handle_token s</term>
<listitem><para>
A string that will be used as the last element of the @handle. Must be a valid
object path element. See the #org.freedesktop.portal.Request documentation for
more information about the @handle.
</para></listitem>
</varlistentry>
<varlistentry>
<term>type u</term>
<listitem><para>
Bitmask of what device types to request remote controlling of.
Default is all.
</para></listitem>
</varlistentry>
</variablelist>
For available source types, see the AvailableDeviceTypes property.
-->
<method name="SelectDevices">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
Start:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@parent_window: Identifier for the application window, see <link linkend="parent_window">Common Conventions</link>
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Start the remote desktop session. This will typically result in the portal
presenting a dialog letting the user select what to share, including
devices and optionally screen content if screen cast sources was
selected.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>handle_token s</term>
<listitem><para>
A string that will be used as the last element of the @handle. Must be a valid
object path element. See the #org.freedesktop.portal.Request documentation for
more information about the @handle.
</para></listitem>
</varlistentry>
</variablelist>
The following results get returned via the
#org.freedesktop.portal.Request::Response signal:
<variablelist>
<varlistentry>
<term>devices u</term>
<listitem><para>
A bitmask of the devices selected by the user.
</para></listitem>
</varlistentry>
</variablelist>
If a screen cast source was selected, the results of the
#org.freedesktop.portal.ScreenCast.Start response signal may be
included.
-->
<method name="Start">
<arg type="o" name="session_handle" direction="in"/>
<arg type="s" name="parent_window" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
NotifyPointerMotion:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@dx: Relative movement on the x axis
@dy: Relative movement on the y axis
Notify about a new relative pointer motion event. The (dx, dy) vector
represents the new pointer position in the streams logical coordinate
space.
-->
<method name="NotifyPointerMotion">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="d" name="dx" direction="in"/>
<arg type="d" name="dy" direction="in"/>
</method>
<!--
NotifyPointerMotionAbsolute:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@stream: The PipeWire stream node the coordinate is relative to
@x: Pointer motion x coordinate
@y: Pointer motion y coordinate
Notify about a new absolute pointer motion event. The (x, y) position
represents the new pointer position in the streams logical coordinate
space (see the logical_size stream property in
#org.freedesktop.portal.ScreenCast).
-->
<method name="NotifyPointerMotionAbsolute">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="u" name="stream" direction="in"/>
<arg type="d" name="x" direction="in"/>
<arg type="d" name="y" direction="in"/>
</method>
<!--
NotifyPointerButton:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@button: The pointer button was pressed or released
@state: The new state of the button
The pointer button is encoded according to Linux Evdev button codes.
May only be called if POINTER access was provided after starting the
session.
Available button states:
<simplelist>
<member>0: Released</member>
<member>1: Pressed</member>
</simplelist>
-->
<method name="NotifyPointerButton">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="i" name="button" direction="in"/>
<arg type="u" name="state" direction="in"/>
</method>
<!--
NotifyPointerAxis:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@dx: Relative axis movement on the x axis
@dy: Relative axis movement on the y axis
The axis movement from a 'smooth scroll' device, such as a touchpad.
When applicable, the size of the motion delta should be equivalent to
the motion vector of a pointer motion done using the same advice.
May only be called if POINTER access was provided after starting the
session.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>finish b</term>
<listitem><para>
If set to true, this is the last axis event in a series, for
example as a result of the fingers being lifted from a touchpad
after a two-finger scroll. Default is false.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="NotifyPointerAxis">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="d" name="dx" direction="in"/>
<arg type="d" name="dy" direction="in"/>
</method>
<!--
NotifyPointerAxisDiscrete:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@axis: The axis that was scrolled
@steps: The number of steps scrolled
May only be called if POINTER access was provided after starting the
session.
Available axes:
<simplelist>
<member>0: Vertical scroll</member>
<member>1: Horizontal scroll</member>
</simplelist>
-->
<method name="NotifyPointerAxisDiscrete">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="u" name="axis" direction="in"/>
<arg type="i" name="steps" direction="in"/>
</method>
<!--
NotifyKeyboardKeycode:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@keycode: Keyboard code that was pressed or released
@state: New state of keyboard keysym
May only be called if KEYBOARD access was provided after starting the
session.
Available keyboard keysym states:
<simplelist>
<member>0: Released</member>
<member>1: Pressed</member>
</simplelist>
-->
<method name="NotifyKeyboardKeycode">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="i" name="keycode" direction="in"/>
<arg type="u" name="state" direction="in"/>
</method>
<!--
NotifyKeyboardKeysym:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@keysym: Keyboard symbol that was pressed or released
@state: New state of keyboard keysym
May only be called if KEYBOARD access was provided after starting the
session.
Available keyboard keysym states:
<simplelist>
<member>0: Released</member>
<member>1: Pressed</member>
</simplelist>
-->
<method name="NotifyKeyboardKeysym">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="i" name="keysym" direction="in"/>
<arg type="u" name="state" direction="in"/>
</method>
<!--
NotifyTouchDown:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@stream: The PipeWire stream node the coordinate is relative to
@slot: Touch slot where touch point appeared
@x: Touch down x coordinate
@y: Touch down y coordinate
May only be called if TOUCHSCREEN access was provided after starting the
session.
Notify about a new touch down event. The (x, y) position
represents the new touch point position in the streams logical
coordinate space (see the logical_size stream property in
#org.freedesktop.portal.ScreenCast).
-->
<method name="NotifyTouchDown">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="u" name="stream" direction="in"/>
<arg type="u" name="slot" direction="in"/>
<arg type="d" name="x" direction="in"/>
<arg type="d" name="y" direction="in"/>
</method>
<!--
NotifyTouchMotion:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@stream: The PipeWire stream node the coordinate is relative to
@slot: Touch slot where touch point appeared
@x: Touch motion x coordinate
@y: Touch motion y coordinate
May only be called if TOUCHSCREEN access was provided after starting the
session.
Notify about a new touch motion event. The (x, y) position
represents where the touch point position in the streams logical
coordinate space moved (see the logical_size stream property in
#org.freedesktop.portal.ScreenCast).
-->
<method name="NotifyTouchMotion">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="u" name="stream" direction="in"/>
<arg type="u" name="slot" direction="in"/>
<arg type="d" name="x" direction="in"/>
<arg type="d" name="y" direction="in"/>
</method>
<!--
NotifyTouchUp:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@slot: Touch slot where touch point appeared
May only be called if TOUCHSCREEN access was provided after starting the
session.
Notify about a new touch up event.
-->
<method name="NotifyTouchUp">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="u" name="slot" direction="in"/>
</method>
<!--
AvailableDeviceTypes:
A bitmask of available source types. Currently defined types are:
<simplelist>
<member>1: KEYBOARD</member>
<member>2: POINTER</member>
<member>4: TOUCHSCREEN</member>
</simplelist>
-->
<property name="AvailableDeviceTypes" type="u" access="read"/>
<property name="version" type="u" access="read"/>
</interface>
</node>

View File

@@ -1,186 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright (C) 2017-2018 Red Hat, Inc.
This library 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/>.
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.freedesktop.portal.ScreenCast:
@short_description: Screen cast portal
-->
<interface name="org.freedesktop.portal.ScreenCast">
<!--
CreateSession:
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Create a screen cast session. A successfully created session can at
any time be closed using org.freedesktop.portal.Session::Close, or may
at any time be closed by the portal implementation, which will be
signalled via org.freedesktop.portal.Session::Closed.
The following results get returned via the #org.freedesktop.portal.Request::Response signal:
<variablelist>
<varlistentry>
<term>session_handle o</term>
<listitem><para>
The session handle. An object path for the
#org.freedesktop.portal.Session object representing the created
session.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="CreateSession">
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
SelectSources:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Configure what the screen cast session should record. This method must
be called before starting the session.
Passing invalid input to this method will cause the session to be
closed. An application may only attempt to select sources once per
session.
Supported keys in the @options vardict include:
<variablelist>
<varlistentry>
<term>types u</term>
<listitem><para>
Bitmask of what types of content to record. Default is MONITOR.
</para></listitem>
</varlistentry>
<varlistentry>
<term>multiple b</term>
<listitem><para>
Whether to allow selecting multiple sources. Default is no.
</para></listitem>
</varlistentry>
</variablelist>
For available source types, see the AvailableSourceTypes property.
-->
<method name="SelectSources">
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
Start:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@parent_window: Identifier for the application window
@options: Vardict with optional further information
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
Start the screen cast session. This will typically result the portal
presenting a dialog letting the user do the selection set up by
SelectSources. An application can only attempt start a session once.
A screen cast session may only be started after having selected sources
using org.freedesktop.portal.ScreenCast::SelectSources.
The @parent_window identifier must be of the form "x11:$XID" for an X11
window. Support for other window systems may be added in the future.
The following results get returned via the
#org.freedesktop.portal.Request::Response signal:
<variablelist>
<varlistentry>
<term>streams a(ua{sv})</term>
<listitem><para>
An array of PipeWire streams. Each stream consists of a PipeWire
node ID (the first element in the tuple, and a Vardict of
properties.
The array will contain a single stream if 'multiple' (see
SelectSources) was set to 'false', or at least one stream if
'multiple' was set to 'true' as part of the SelectSources method.
</para></listitem>
</varlistentry>
</variablelist>
Stream properties include:
<variablelist>
<varlistentry>
<term>position (ii)</term>
<listitem><para>
A tuple consisting of the position (x, y) in the compositor
coordinate space. Note that the position may not be equivalent to a
position in a pixel coordinate space. Only available for monitor
streams.
</para></listitem>
</varlistentry>
<varlistentry>
<term>size (ii)</term>
<listitem><para>
A tuple consisting of (width, height). The size represents the size
of the stream as it is displayed in the compositor coordinate
space. Note that this size may not be equivalent to a size in a
pixel coordinate space. The size may differ from the size of the
stream.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="Start">
<arg type="o" name="session_handle" direction="in"/>
<arg type="s" name="parent_window" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
<arg type="o" name="handle" direction="out"/>
</method>
<!--
OpenPipeWireRemote:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@fd: File descriptor of an open PipeWire remote.
Open a file descriptor to the PipeWire remote where the screen cast
streams are available. The file descriptor should be used to create a
<classname>pw_remote</classname> object, by using
<function>pw_remote_connect_fd</function>. Only the screen cast stream
nodes will be available from this PipeWire node.
-->
<method name="OpenPipeWireRemote">
<annotation name="org.gtk.GDBus.C.Name" value="open_pipewire_remote"/>
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg type="h" name="fd" direction="out"/>
</method>
<!--
AvailableSourceTypes:
A bitmask of available source types. Currently defined types are:
<simplelist>
<member>1: MONITOR</member>
<member>2: WINDOW</member>
</simplelist>
-->
<property name="AvailableSourceTypes" type="u" access="read"/>
<property name="version" type="u" access="read"/>
</interface>
</node>

View File

@@ -1,6 +0,0 @@
add_subdirectory(x11)
# Makes sense to use only when PW framebuffer is used
if (${PipeWire_FOUND})
add_subdirectory(xdp)
endif()

View File

@@ -1,18 +0,0 @@
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
set (krfb_events_x11_SRCS
x11events.cpp
x11eventsplugin.cpp
)
add_library (krfb_events_x11 MODULE ${krfb_events_x11_SRCS})
target_link_libraries (krfb_events_x11
${X11_XTest_LIB}
KF5::CoreAddons
krfbprivate
)
install (TARGETS krfb_events_x11 DESTINATION ${PLUGIN_INSTALL_DIR}/krfb)

View File

@@ -1,63 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Comment=X11 XFakeInput based event handler for KRfb
Comment[ca]=Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb
Comment[ca@valencia]=Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb
Comment[de]=Ereignis-Modul basierend auf X11 XFakeInput für KRfb
Comment[el]=Χειριστής γεγονότων με βάση το X11 XFakeInput για το KRfb
Comment[en_GB]=X11 XFakeInput based event handler for KRfb
Comment[es]=Gestor de eventos basado en XFakeInput de X11 para KRfb
Comment[et]=KRfb X11 XFakeInput'i põhine sündmuste käitleja
Comment[eu]=KRfb-rako «X11 XFakeInput»en oinarritutako gertaera maneiatzailea
Comment[fi]=KRfb:n X11 XFakeInput -pohjainen tapahtumakäsittelijä
Comment[fr]=Gestionnaire d'évènements utilisant XFakeInput de X11 pour KRfb
Comment[gl]=Xestor de eventos para KRfb baseado no XFakeInput de X11
Comment[it]=Gestore eventi basato su XFakeInput di X11 per KRfb
Comment[ko]=X11 XFakeInput 기반 KRfb 이벤트 핸들러
Comment[nl]=Op X11 XFakeInput gebaseerde behandelaar van gebeurtenis voor KRfb
Comment[nn]=X11 XFakeInput-basert hendingshandtering for KRfb
Comment[pl]=Obsługa wydarzeń X11 oparta na XFakeInput dla KRfb
Comment[pt]=Tratamento de eventos baseado no XFakeInput do X11 para o KRfb
Comment[pt_BR]=Manipulador de eventos baseado no XFakeInput do X11 para o KRfb
Comment[sk]=X11 Spracovateľ udalostí založený na XFakeInput pre KRfb
Comment[sl]=Upravljalnik dogodkov za KRfb na podlagi X11 XFakeInput
Comment[sv]=Händelsehanterare för Krfb baserad på X11 XFakeInput
Comment[uk]=Обробник подій для KRfb на основі XFakeInput X11
Comment[x-test]=xxX11 XFakeInput based event handler for KRfbxx
Comment[zh_CN]=基于 X11 XFakeInput 的 KRfb 事件处理器
Comment[zh_TW]=KRfb 基於 X11 XFakeInput 的事件處理器
Name=X11 XFakeInput based event handler for KRfb
Name[ca]=Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb
Name[ca@valencia]=Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb
Name[de]=Ereignis-Modul basierend auf X11 XFakeInput für KRfb
Name[el]=Χειριστής γεγονότων με βάση το X11 XFakeInput για το KRfb
Name[en_GB]=X11 XFakeInput based event handler for KRfb
Name[es]=Gestor de eventos basado en XFakeInput de X11 para KRfb
Name[et]=KRfb X11 XFakeInput'i põhine sündmuste käitleja
Name[eu]=KRfb-rako «X11 XFakeInput»en oinarritutako gertaera maneiatzailea
Name[fi]=KRfb:n X11 XFakeInput -pohjainen tapahtumakäsittelijä
Name[fr]=Gestionnaire d'évènements utilisant XFakeInput de X11 pour KRfb
Name[gl]=Xestor de eventos para KRfb baseado no XFakeInput de X11
Name[it]=Gestore eventi basato su XFakeInput di X11 per KRfb
Name[ko]=X11 XFakeInput 기반 KRfb 이벤트 핸들러
Name[nl]=Op X11 XFakeInput gebaseerde behandelaar van gebeurtenis voor KRfb
Name[nn]=X11 XFakeInput-basert hendingshandtering for KRfb
Name[pl]=Obsługa wydarzeń X11 oparta na XFakeInput dla KRfb
Name[pt]=Tratamento de eventos baseado no XFakeInput do X11 para o KRfb
Name[pt_BR]=Manipulador de eventos baseado no XFakeInput do X11 para o KRfb
Name[sk]=X11 Spracovateľ udalostí založený na XFakeInput pre KRfb
Name[sl]=Upravljalnik dogodkov za KRfb na podlagi X11 XFakeInput
Name[sv]=Händelsehanterare för Krfb baserad på X11 XFakeInput
Name[uk]=Обробник подій для KRfb на основі XFakeInput X11
Name[x-test]=xxX11 XFakeInput based event handler for KRfbxx
Name[zh_CN]=基于 X11 XFakeInput 的 KRfb 事件处理器
Name[zh_TW]=KRfb 基於 X11 XFakeInput 的事件處理器
Type=Service
ServiceTypes=krfb/events
X-KDE-Library=krfb_events_x11
X-KDE-PluginInfo-Name=x11
X-KDE-PluginInfo-Version=0.1
X-KDE-PluginInfo-Website=https://www.kde.org
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true

View File

@@ -1,65 +0,0 @@
{
"Encoding": "UTF-8",
"KPlugin": {
"Description": "X11 XFakeInput based event handler for KRfb",
"Description[ca@valencia]": "Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb",
"Description[ca]": "Gestor d'esdeveniments basat en el XFakeInput de l'X11 per al KRfb",
"Description[de]": "Ereignis-Modul basierend auf X11 XFakeInput für KRfb",
"Description[el]": "Χειριστής γεγονότων με βάση το X11 XFakeInput για το KRfb",
"Description[en_GB]": "X11 XFakeInput based event handler for KRfb",
"Description[es]": "Gestor de eventos basado en XFakeInput de X11 para KRfb",
"Description[et]": "KRfb X11 XFakeInput'i põhine sündmuste käitleja",
"Description[eu]": "KRfb-rako «X11 XFakeInput»en oinarritutako gertaera maneiatzailea",
"Description[fi]": "KRfb:n X11 XFakeInput -pohjainen tapahtumakäsittelijä",
"Description[fr]": "Gestionnaire d'évènements utilisant XFakeInput de X11 pour KRfb",
"Description[gl]": "Xestor de eventos para KRfb baseado no XFakeInput de X11",
"Description[it]": "Gestore eventi basato su XFakeInput di X11 per KRfb",
"Description[ko]": "X11 XFakeInput 기반 KRfb 이벤트 핸들러",
"Description[nl]": "Op X11 XFakeInput gebaseerde behandelaar van gebeurtenis voor KRfb",
"Description[nn]": "X11 XFakeInput-basert hendingshandtering for KRfb",
"Description[pl]": "Obsługa wydarzeń X11 oparta na XFakeInput dla KRfb",
"Description[pt]": "Tratamento de eventos baseado no XFakeInput do X11 para o KRfb",
"Description[pt_BR]": "Manipulador de eventos baseado no XFakeInput do X11 para o KRfb",
"Description[sk]": "X11 Spracovateľ udalostí založený na XFakeInput pre KRfb",
"Description[sl]": "Upravljavec dogodkov za KRfb na osnovi X11 XFakeInput",
"Description[sv]": "Händelsehanterare för KRfb baserad på X11 XFakeInput",
"Description[uk]": "Обробник подій для KRfb на основі XFakeInput X11",
"Description[x-test]": "xxX11 XFakeInput based event handler for KRfbxx",
"Description[zh_CN]": "基于 X11 XFakeInput 的 KRfb 事件处理器",
"Description[zh_TW]": "KRfb 基於 X11 XFakeInput 的事件處理器",
"EnabledByDefault": true,
"Id": "x11",
"License": "GPL",
"Name": "X11 Event handler for KRfb",
"Name[ca@valencia]": "Gestor d'esdeveniments de l'X11 per al KRfb",
"Name[ca]": "Gestor d'esdeveniments de l'X11 per al KRfb",
"Name[de]": "Ereignis-Modul basierend auf X11 für KRfb",
"Name[el]": "Χειριστής γεγονότων X11 για το KRfb",
"Name[en_GB]": "X11 Event handler for KRfb",
"Name[es]": "Gestor de eventos de X11 para KRfb",
"Name[et]": "KRfb X11 sündmuste käitleja",
"Name[eu]": "KRfb-rako X11 gertaera maneiatzailea",
"Name[fi]": "KRfb:n X11-tapahtumakäsittelijä",
"Name[fr]": "Gestionnaire d'évènements X11 pour KRfb",
"Name[gl]": "Xestor de eventos de X11 para KRfb",
"Name[it]": "Gestore eventi X11 per KRfb",
"Name[ko]": "KRfb X11 이벤트 핸들러",
"Name[nl]": "Op X11 behandelaar van gebeurtenis voor KRfb",
"Name[nn]": "X11-hendingshandsamar for KRfb",
"Name[pl]": "Obsługa wydarzeń X11 dla KRfb",
"Name[pt]": "Tratamento de eventos do X11 para o KRfb",
"Name[pt_BR]": "Manipulador de eventos do X11 para o KRfb",
"Name[sk]": "X11 Obsluha udalostí pre KRfb",
"Name[sl]": "Upravljavec dogodkov za KRfb na osnovi X11",
"Name[sv]": "X11-händelsehanterare för Krfb",
"Name[uk]": "Обробник подій для KRfb на основі X11",
"Name[x-test]": "xxX11 Event handler for KRfbxx",
"Name[zh_CN]": "X11 KRfb 事件处理器",
"Name[zh_TW]": "KRfb 的 X11 事件處理器",
"ServiceTypes": [
"krfb/events"
],
"Version": "0.1",
"Website": "http://www.kde.org"
}
}

View File

@@ -1,210 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2016 by Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "x11events.h"
#include <QApplication>
#include <QX11Info>
#include <QDesktopWidget>
#include <QGlobalStatic>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <QX11Info>
enum {
LEFTSHIFT = 1,
RIGHTSHIFT = 2,
ALTGR = 4
};
class EventData
{
public:
EventData();
//keyboard
Display *dpy;
signed char modifiers[0x100];
KeyCode keycodes[0x100];
KeyCode leftShiftCode;
KeyCode rightShiftCode;
KeyCode altGrCode;
char modifierState;
//mouse
int buttonMask;
int x;
int y;
private:
void init();
};
Q_GLOBAL_STATIC(EventData, data)
EventData::EventData()
{
init();
}
void EventData::init()
{
buttonMask = 0;
dpy = QX11Info::display();
//initialize keycodes
KeySym key, *keymap;
int i, j, minkey, maxkey, syms_per_keycode;
memset(modifiers, -1, sizeof(modifiers));
XDisplayKeycodes(dpy, &minkey, &maxkey);
Q_ASSERT(minkey >= 8);
Q_ASSERT(maxkey < 256);
keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey,
(maxkey - minkey + 1),
&syms_per_keycode);
Q_ASSERT(keymap);
for (i = minkey; i <= maxkey; i++) {
for (j = 0; j < syms_per_keycode; j++) {
key = keymap[(i-minkey)*syms_per_keycode+j];
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
keycodes[key] = i;
modifiers[key] = j;
}
}
}
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
XFree((char *)keymap);
}
/* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */
static void tweakModifiers(signed char mod, bool down)
{
bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT);
if (mod < 0) {
return;
}
if (isShift && mod != 1) {
if (data->modifierState & LEFTSHIFT) {
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
down, CurrentTime);
}
if (data->modifierState & RIGHTSHIFT) {
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
down, CurrentTime);
}
}
if (!isShift && mod == 1) {
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
down, CurrentTime);
}
if ((data->modifierState & ALTGR) && mod != 2) {
XTestFakeKeyEvent(data->dpy, data->altGrCode,
!down, CurrentTime);
}
if (!(data->modifierState & ALTGR) && mod == 2) {
XTestFakeKeyEvent(data->dpy, data->altGrCode,
down, CurrentTime);
}
}
void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
{
#define ADJUSTMOD(sym,state) \
if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; }
if (QX11Info::isPlatformX11()) {
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT);
ADJUSTMOD(XK_Mode_switch, ALTGR);
if (keySym >= ' ' && keySym < 0x100) {
KeyCode k;
if (down) {
tweakModifiers(data->modifiers[keySym], True);
}
k = data->keycodes[keySym];
if (k != NoSymbol) {
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
}
if (down) {
tweakModifiers(data->modifiers[keySym], False);
}
} else {
KeyCode k = XKeysymToKeycode(data->dpy, keySym);
if (k != NoSymbol) {
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
}
}
}
/*
// Wayland platform and pipweire plugin in use
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("pw")) {
}*/
}
void X11EventHandler::handlePointer(int buttonMask, int x, int y)
{
if (QX11Info::isPlatformX11()) {
QDesktopWidget *desktopWidget = QApplication::desktop();
int screen = desktopWidget->screenNumber();
if (screen < 0) {
screen = 0;
}
XTestFakeMotionEvent(data->dpy, screen, x, y, CurrentTime);
for (int i = 0; i < 5; i++) {
if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) {
XTestFakeButtonEvent(data->dpy,
i + 1,
(buttonMask&(1 << i)) ? True : False,
CurrentTime);
}
}
data->buttonMask = buttonMask;
}
}

View File

@@ -1,41 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2016 by Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef EVENTS_X11EVENTS_H
#define EVENTS_X11EVENTS_H
#include "../../krfb/events.h"
class X11EventHandler : public EventHandler
{
Q_OBJECT
public:
explicit X11EventHandler(QObject *parent = nullptr)
: EventHandler(parent)
{
};
void handleKeyboard(bool down, rfbKeySym key) override;
void handlePointer(int buttonMask, int x, int y) override;
};
#endif

View File

@@ -1,45 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2016 Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "x11eventsplugin.h"
#include "x11events.h"
#include <KPluginFactory>
#include <QX11Info>
K_PLUGIN_FACTORY_WITH_JSON(X11EventsPluginFactory, "krfb_events_x11.json",
registerPlugin<X11EventsPlugin>();)
X11EventsPlugin::X11EventsPlugin(QObject *parent, const QVariantList &args)
: EventsPlugin(parent, args)
{
}
EventHandler *X11EventsPlugin::eventHandler()
{
// works only under X11
if(!QX11Info::isPlatformX11())
return nullptr;
return new X11EventHandler();
}
#include "x11eventsplugin.moc"

View File

@@ -1,43 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2016 Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KRFB_EVENTS_X11_X11EVENTSPLUGIN_H
#define KRFB_EVENTS_X11_X11EVENTSPLUGIN_H
#include "eventsplugin.h"
#include <QWidget>
class EventHandler;
class X11EventsPlugin : public EventsPlugin
{
Q_OBJECT
public:
X11EventsPlugin(QObject *parent, const QVariantList &args);
virtual ~X11EventsPlugin() = default;
EventHandler *eventHandler() override;
private:
Q_DISABLE_COPY(X11EventsPlugin)
};
#endif // Header guard

View File

@@ -1,27 +0,0 @@
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
set (krfb_events_xdp_SRCS
xdpevents.cpp
xdpeventsplugin.cpp
)
qt5_add_dbus_interface(
krfb_events_xdp_SRCS
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_remotedesktop_interface.xml
xdp_dbus_remotedesktop_interface
)
add_library (krfb_events_xdp MODULE ${krfb_events_xdp_SRCS})
target_link_libraries (krfb_events_xdp
KF5::CoreAddons
KF5::I18n
Qt5::DBus
krfbprivate
)
install (TARGETS krfb_events_xdp
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
)

View File

@@ -1,64 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Comment=Xdg-desktop-portal based event handler for KRfb
Comment[ca]=Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb
Comment[ca@valencia]=Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb
Comment[de]=Ereignis-Modul basierend auf Xdg-desktop-portal für KRfb
Comment[el]=Χειριστής γεγονότων με βάση το xdg-desktop-portal για το KRfb
Comment[en_GB]=Xdg-desktop-portal based event handler for KRfb
Comment[es]=Gestor de eventos basado en Xdg-desktop-portal para KRfb
Comment[et]=KRfb Xdg-desktop-portal'i põhine sündmuste käitleja
Comment[eu]=KRfb-rako «xdg-desktop-portal»en oinarritutako maneiatzailea
Comment[fi]=KRfb:n XDG-desktop-portal-pohjainen tapahtumakäsittelijä
Comment[fr]=Gestionnaire d'évènements utilisant Xdg-desktop-portal pour KRfb
Comment[gl]=Xestor de eventos para KRfb baseado en Xdg-desktop-portal
Comment[it]=Gestore eventi basato su xdg-desktop-portal per KRfb
Comment[ko]=Xdg-desktop-portal 기반 KRfb 이벤트 핸들러
Comment[nl]=Op Xdg-desktop-portal gebaseerde behandelaar van gebeurtenis voor KRfb
Comment[nn]=Xdg-desktop-portal-basert hendingshandtering for KRfb
Comment[pl]=Obsługa wydarzeń oparta na Xdg-desktop-portal dla KRfb
Comment[pt]=Tratamento de eventos baseado no Xdg-desktop-portal para o KRfb
Comment[pt_BR]=Manipulador de eventos baseado no xdg-desktop-portal para o KRfb
Comment[sk]=Obsluha udalostí založená na Xdg-desktop-portal pre KRfb
Comment[sl]=Upravljalnik dogodkov za KRfb na podlagi namiznega portala Xdg
Comment[sv]=Händelsehanterare för Krfb baserad på xdg-desktop-portal
Comment[uk]=Обробник подій для KRfb на основі Xdg-desktop-portal
Comment[x-test]=xxXdg-desktop-portal based event handler for KRfbxx
Comment[zh_CN]=基于 xdg-desktop-portal 的 KRfb 事件处理器
Comment[zh_TW]=KRfb 基於 Xdg-desktop-portal 的事件處理器
Name=Xdg-desktop-portal based event handler for KRfb
Name[ca]=Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb
Name[ca@valencia]=Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb
Name[de]=Ereignis-Modul basierend auf Xdg-desktop-portal für KRfb
Name[el]=Χειριστής γεγονότων με βάση το xdg-desktop-portal για το KRfb
Name[en_GB]=Xdg-desktop-portal based event handler for KRfb
Name[es]=Gestor de eventos basado en Xdg-desktop-portal para KRfb
Name[et]=KRfb Xdg-desktop-portal'i põhine sündmuste käitleja
Name[eu]=KRfb-rako «xdg-desktop-portal»en oinarritutako maneiatzailea
Name[fi]=KRfb:n XDG-desktop-portal-pohjainen tapahtumakäsittelijä
Name[fr]=Gestionnaire d'évènements utilisant Xdg-desktop-portal pour KRfb
Name[gl]=Xestor de eventos para KRfb baseado en Xdg-desktop-portal
Name[it]=Gestore eventi basato su xdg-desktop-portal per KRfb
Name[ko]=Xdg-desktop-portal 기반 KRfb 이벤트 핸들러
Name[nl]=Op Xdg-desktop-portal gebaseerde behandelaar van gebeurtenis voor KRfb
Name[nn]=Xdg-desktop-portal-basert hendingshandtering for KRfb
Name[pl]=Obsługa wydarzeń oparta na Xdg-desktop-portal dla KRfb
Name[pt]=Tratamento de eventos baseado no Xdg-desktop-portal para o KRfb
Name[pt_BR]=Manipulador de eventos baseado no xdg-desktop-portal para o KRfb
Name[sk]=Obsluha udalostí založená na Xdg-desktop-portal pre KRfb
Name[sl]=Upravljalnik dogodkov za KRfb na podlagi namiznega portala Xdg
Name[sv]=Händelsehanterare för Krfb baserad på xdg-desktop-portal
Name[uk]=Обробник подій для KRfb на основі Xdg-desktop-portal
Name[x-test]=xxXdg-desktop-portal based event handler for KRfbxx
Name[zh_CN]=基于 xdg-desktop-portal 的 KRfb 事件处理器
Name[zh_TW]=KRfb 基於 Xdg-desktop-portal 的事件處理器
Type=Service
ServiceTypes=krfb/events
X-KDE-Library=krfb_events_xdp
X-KDE-PluginInfo-Name=xdp
X-KDE-PluginInfo-Version=0.1
X-KDE-PluginInfo-Website=https://www.kde.org
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true

View File

@@ -1,65 +0,0 @@
{
"Encoding": "UTF-8",
"KPlugin": {
"Description": "Xdg-desktop-portal based event handler for KRfb",
"Description[ca@valencia]": "Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb",
"Description[ca]": "Gestor d'esdeveniments basat en el Xdg-desktop-portal per al KRfb",
"Description[de]": "Ereignis-Modul basierend auf Xdg-desktop-portal für KRfb",
"Description[el]": "Χειριστής γεγονότων με βάση το xdg-desktop-portal για το KRfb",
"Description[en_GB]": "Xdg-desktop-portal based event handler for KRfb",
"Description[es]": "Gestor de eventos basado en Xdg-desktop-portal para KRfb",
"Description[et]": "KRfb Xdg-desktop-portal'i põhine sündmuste käitleja",
"Description[eu]": "KRfb-rako «xdg-desktop-portal»en oinarritutako maneiatzailea",
"Description[fi]": "KRfb:n XDG-desktop-portal-pohjainen tapahtumakäsittelijä",
"Description[fr]": "Gestionnaire d'évènements utilisant Xdg-desktop-portal pour KRfb",
"Description[gl]": "Xestor de eventos para KRfb baseado en Xdg-desktop-portal",
"Description[it]": "Gestore eventi basato su xdg-desktop-portal per KRfb",
"Description[ko]": "Xdg-desktop-portal 기반 KRfb 이벤트 핸들러",
"Description[nl]": "Op Xdg-desktop-portal gebaseerde behandelaar van gebeurtenis voor KRfb",
"Description[nn]": "Xdg-desktop-portal-basert hendingshandtering for KRfb",
"Description[pl]": "Obsługa wydarzeń oparta na Xdg-desktop-portal dla KRfb",
"Description[pt]": "Tratamento de eventos baseado no Xdg-desktop-portal para o KRfb",
"Description[pt_BR]": "Manipulador de eventos baseado no xdg-desktop-portal para o KRfb",
"Description[sk]": "Obsluha udalostí založená na Xdg-desktop-portal pre KRfb",
"Description[sl]": "Upravljavec dogodkov, na osnovi portala Xdg-desktop za KRfb",
"Description[sv]": "Händelsehanterare för KRfb baserad på xdg-desktop-portal",
"Description[uk]": "Обробник подій для KRfb на основі Xdg-desktop-portal",
"Description[x-test]": "xxXdg-desktop-portal based event handler for KRfbxx",
"Description[zh_CN]": "基于 xdg-desktop-portal 的 KRfb 事件处理器",
"Description[zh_TW]": "KRfb 基於 Xdg-desktop-portal 的事件處理器",
"EnabledByDefault": true,
"Id": "xdp",
"License": "GPL",
"Name": "Xdg-desktop-portal Event handler for KRfb",
"Name[ca@valencia]": "Gestor d'esdeveniments Xdg-desktop-portal per al KRfb",
"Name[ca]": "Gestor d'esdeveniments Xdg-desktop-portal per al KRfb",
"Name[de]": "Ereignis-Modul basierend auf Xdg-desktop-portal für KRfb",
"Name[el]": "Χειριστής γεγονότων xdg-desktop-portal για το KRfb",
"Name[en_GB]": "Xdg-desktop-portal Event handler for KRfb",
"Name[es]": "Gestor de eventos de Xdg-desktop-portal para KRfb",
"Name[et]": "KRfb Xdg-desktop-portal'i sündmuste käitleja",
"Name[eu]": "KRfb-rako «xdg-desktop-portal» gertaera maneiatzailea",
"Name[fi]": "KRfb:n XDG-desktop-portal-pohjainen tapahtumakäsittelijä",
"Name[fr]": "Gestionnaire d'évènements Xdg-desktop-portal pour KRfb",
"Name[gl]": "Xestor de eventos de Xdg-desktop-portal para KRfb",
"Name[it]": "Gestore eventi xdg-desktop-portal per KRfb",
"Name[ko]": "KRfb Xdg-desktop-portal 이벤트 핸들러",
"Name[nl]": "Op Xdg-desktop-portal behandelaar van gebeurtenis voor KRfb",
"Name[nn]": "Xdg-desktop-portal-hendingshandtering for KRfb",
"Name[pl]": "Obsługa wydarzeń Xdg-desktop-portal dla KRfb",
"Name[pt]": "Tratamento de eventos do Xdg-desktop-portal para o KRfb",
"Name[pt_BR]": "Manipulador de eventos xdg-desktop-portal para o KRfb",
"Name[sk]": "Xdg-desktop-portal Obsluha udalostí pre KRfb",
"Name[sl]": "Upravljavec dogodkov za KRfb na osnovi portala Xdg-desktop",
"Name[sv]": "Xdg-desktop-portal händelsehanterare för Krfb",
"Name[uk]": "Обробник подій для KRfb на основі Xdg-desktop-portal",
"Name[x-test]": "xxXdg-desktop-portal Event handler for KRfbxx",
"Name[zh_CN]": "xdg-desktop-portal KRfb 事件处理器",
"Name[zh_TW]": "KRfb 的 Xdg-desktop-portal 事件處理器",
"ServiceTypes": [
"krfb/events"
],
"Version": "0.1",
"Website": "http://www.kde.org"
}
}

View File

@@ -1,126 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2018-2019 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "xdpevents.h"
#include "rfbservermanager.h"
#include "xdp_dbus_remotedesktop_interface.h"
#include <linux/input.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QGlobalStatic>
class EventData
{
public:
EventData();
//mouse
int buttonMask;
int x;
int y;
QScopedPointer<OrgFreedesktopPortalRemoteDesktopInterface> dbusXdpRemoteDesktopService;
private:
void init();
};
Q_GLOBAL_STATIC(EventData, data)
EventData::EventData()
{
init();
}
void EventData::init()
{
buttonMask = 0;
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QLatin1String("org.freedesktop.portal.Desktop"),
QLatin1String("/org/freedesktop/portal/desktop"), QDBusConnection::sessionBus()));
}
void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
{
// TODO: implement button handling
// both in FakeInput interface and here
Q_UNUSED(down)
Q_UNUSED(keySym)
}
void XdpEventHandler::handlePointer(int buttonMask, int x, int y)
{
const uint streamNodeId = frameBuffer()->customProperty(QLatin1String("stream_node_id")).toUInt();
const QDBusObjectPath sessionHandle = frameBuffer()->customProperty(QLatin1String("session_handle")).value<QDBusObjectPath>();
if (streamNodeId == 0 || sessionHandle.path().isEmpty()) {
return;
}
if (x != data->x || y != data->y) {
data->dbusXdpRemoteDesktopService->NotifyPointerMotionAbsolute(sessionHandle, QVariantMap(), streamNodeId, x, y);
data->x = x;
data->y = y;
}
if (buttonMask != data->buttonMask) {
int i = 0;
QVector<int> buttons = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 0, 0, 0, 0, BTN_SIDE, BTN_EXTRA };
for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) {
int prevButtonState = (data->buttonMask >> i) & 0x01;
int currentButtonState = (buttonMask >> i) & 0x01;
if (prevButtonState != currentButtonState) {
if (*it) {
data->dbusXdpRemoteDesktopService->NotifyPointerButton(sessionHandle, QVariantMap(), *it, buttonMask);
} else {
int axis = 0;
int steps = 0;
switch (i) {
case 3:
axis = 0; // Vertical
steps = -1;
break;
case 4:
axis = 0; // Vertical
steps = 1;
break;
case 5:
axis = 1; // Horizontal
steps = -1;
break;
case 6:
axis = 1; // Horizontal
steps = 1;
break;
}
data->dbusXdpRemoteDesktopService->NotifyPointerAxisDiscrete(sessionHandle, QVariantMap(), axis, steps);
}
}
++i;
}
data->buttonMask = buttonMask;
}
}

View File

@@ -1,37 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2018-2019 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef EVENTS_XDPEVENTS_H
#define EVENTS_XDPEVENTS_H
#include "../../krfb/events.h"
class XdpEventHandler : public EventHandler
{
Q_OBJECT
public:
void handleKeyboard(bool down, rfbKeySym key) override;
void handlePointer(int buttonMask, int x, int y) override;
};
#endif

View File

@@ -1,43 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2018-2019 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "xdpeventsplugin.h"
#include "xdpevents.h"
#include <KPluginFactory>
K_PLUGIN_FACTORY_WITH_JSON(XdpEventsPluginFactory, "krfb_events_xdp.json",
registerPlugin<XdpEventsPlugin>();)
XdpEventsPlugin::XdpEventsPlugin(QObject *parent, const QVariantList &args)
: EventsPlugin(parent, args)
{
}
EventHandler *XdpEventsPlugin::eventHandler()
{
// works only under Wayland
return new XdpEventHandler();
}
#include "xdpeventsplugin.moc"

View File

@@ -1,46 +0,0 @@
/*
This file is part of the KDE project
Copyright (C) 2018-2019 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KRFB_EVENTS_XDP_XDPEVENTSPLUGIN_H
#define KRFB_EVENTS_XDP_XDPEVENTSPLUGIN_H
#include "eventsplugin.h"
#include <QWidget>
class EventHandler;
class XdpEventsPlugin : public EventsPlugin
{
Q_OBJECT
public:
XdpEventsPlugin(QObject *parent, const QVariantList &args);
virtual ~XdpEventsPlugin() = default;
EventHandler *eventHandler() override;
private:
Q_DISABLE_COPY(XdpEventsPlugin)
};
#endif // Header guard

View File

@@ -1,9 +1,5 @@
add_subdirectory (qt)
if (${XCB_DAMAGE_FOUND} AND ${XCB_SHM_FOUND} AND ${XCB_IMAGE_FOUND})
add_subdirectory (xcb)
endif()
if (${PipeWire_FOUND})
add_subdirectory(pipewire)
add_subdirectory (xcb)
endif()

View File

@@ -1,38 +0,0 @@
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
set (krfb_framebuffer_pw_SRCS
pw_framebuffer.cpp
pw_framebufferplugin.cpp
)
qt5_add_dbus_interface(
krfb_framebuffer_pw_SRCS
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_screencast_interface.xml
xdp_dbus_screencast_interface
)
qt5_add_dbus_interface(
krfb_framebuffer_pw_SRCS
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_remotedesktop_interface.xml
xdp_dbus_remotedesktop_interface
)
add_library(krfb_framebuffer_pw
MODULE
${krfb_framebuffer_pw_SRCS}
)
target_link_libraries (krfb_framebuffer_pw
Qt5::Core
Qt5::Gui
Qt5::DBus
KF5::CoreAddons
krfbprivate
PipeWire::PipeWire
)
install (TARGETS krfb_framebuffer_pw
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
)

View File

@@ -1,69 +0,0 @@
{
"Encoding": "UTF-8",
"KPlugin": {
"Description": "PipeWire based Framebuffer for KRfb.",
"Description[ca@valencia]": "«Framebuffer» basat en el PipeWire per al KRfb.",
"Description[ca]": "«Framebuffer» basat en el PipeWire per al KRfb.",
"Description[cs]": "Framebuffer založený na Pipe pro KRfb.",
"Description[de]": "PipeWire-basierter Framebuffer für KRfb.",
"Description[el]": "Μνήμη ανανέωσης με βάση το pipewire για το KRfb.",
"Description[en_GB]": "PipeWire based Framebuffer for KRfb.",
"Description[es]": "Framebuffer basado en PipeWire para KRfb.",
"Description[et]": "KRfb PipeWire põhine kaadripuhver",
"Description[eu]": "KRfb-rako «PipeWire»n oinarritutako «Framebuffer».",
"Description[fi]": "KRfb:n PipeWire-pohjainen kehyspuskuri.",
"Description[fr]": "Tampon d'images utilisant PipeWire pour KRfb.",
"Description[gl]": "Búfer de fotograma para KRfb baseado en PipeWire.",
"Description[it]": "Framebuffer basato su PipeWire per KRfb.",
"Description[ko]": "KRfb용 PipeWire 기반 프레임버퍼입니다.",
"Description[nl]": "Op PipeWire gebaseerd framebuffer voor KRfb.",
"Description[nn]": "PipeWire-basert biletbuffer for KRfb.",
"Description[pl]": "Bufor ramki oparty na PipeWire dla KRfb.",
"Description[pt]": "'Framebuffer' baseado no PipeWire para o KRfb.",
"Description[pt_BR]": "Framebuffer baseado no PipeWire para o KRfb.",
"Description[ru]": "Буфер кадров для KRfb на базе Framebuffer",
"Description[sk]": "Framebuffer založený na PipeWire pre KRfb.",
"Description[sl]": "Slikovni medpomnilnik na osnovi PipeWire za KRfb.",
"Description[sv]": "Rambuffert för Krfb baserad på PipeWire",
"Description[uk]": "Буфер кадрів на основі PipeWire для KRfb.",
"Description[x-test]": "xxPipeWire based Framebuffer for KRfb.xx",
"Description[zh_CN]": "基于 PipeWire 的 KRfb 帧缓冲机制。",
"Description[zh_TW]": "KRfb 基於 PipeWire 的 Framebuffer。",
"EnabledByDefault": true,
"Id": "pw",
"License": "GPL3",
"Name": "PipeWire Framebuffer for KRfb",
"Name[ca@valencia]": "«Framebuffer» del PipeWire per al KRfb",
"Name[ca]": "«Framebuffer» del PipeWire per al KRfb",
"Name[cs]": "PipeWire Framebuffer pro KRfb",
"Name[de]": "PipeWire-Framebuffer für KRfb",
"Name[el]": "Μνήμη ανανέωσης pipewire για το KRfb",
"Name[en_GB]": "PipeWire Framebuffer for KRfb",
"Name[es]": "Framebuffer de PipeWire para KRfb",
"Name[et]": "KRfb PipeWire kaadripuhver",
"Name[eu]": "KRfb-rako «PipeWire Framebuffer»",
"Name[fi]": "KRfb:n PipeWire-kehyspuskuri",
"Name[fr]": "Tampon d'images PipeWire pour KRfb",
"Name[gl]": "Búfer de fotograma de PipeWire para KRfb",
"Name[it]": "Framebuffer PipeWire per KRfb",
"Name[ko]": "KRfb용 PipeWire 프레임버퍼",
"Name[nl]": "PipeWire-framebuffer voor KRfb",
"Name[nn]": "PipeWire-biletbuffer for KRfb",
"Name[pl]": "Wtyczki buforów ramek PipeWire dla KRfb",
"Name[pt]": "'Framebuffer' do PipeWire para o KRfb",
"Name[pt_BR]": "Framebuffer PipeWire para o KRfb",
"Name[ru]": "Буфер кадров PipeWire для KRfb",
"Name[sk]": "PipeWire Framebuffer pre KRfb",
"Name[sl]": "Slikovni medpomnilnik za KRfb na osnovi PipeWire",
"Name[sv]": "PipeWire-rambuffert för Krfb",
"Name[uk]": "Буфер кадрів PipeWire для KRfb",
"Name[x-test]": "xxPipeWire Framebuffer for KRfbxx",
"Name[zh_CN]": "KRfb 的 PipeWire 帧缓冲机制",
"Name[zh_TW]": "KRfb 的 PipeWire Framebuffer",
"ServiceTypes": [
"krfb/framebuffer"
],
"Version": "0.1",
"Website": "http://www.kde.org"
}
}

View File

@@ -1,895 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2018 Oleg Chernovskiy <kanedias@xaker.ru>
Copyright (C) 2018 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
*/
// system
#include <sys/mman.h>
#include <cstring>
// Qt
#include <QX11Info>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QScreen>
#include <QSocketNotifier>
#include <QDebug>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
#include <QRandomGenerator>
#endif
// pipewire
#include <pipewire/version.h>
#if PW_CHECK_VERSION(0, 2, 90)
#include <spa/utils/result.h>
#endif
#include <spa/param/format-utils.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/props.h>
#include <pipewire/pipewire.h>
#include <limits.h>
#include "pw_framebuffer.h"
#include "xdp_dbus_screencast_interface.h"
#include "xdp_dbus_remotedesktop_interface.h"
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)
{
arg.beginStructure();
arg >> stream.nodeId;
arg.beginMap();
while (!arg.atEnd()) {
QString key;
QVariant map;
arg.beginMapEntry();
arg >> key >> map;
arg.endMapEntry();
stream.map.insert(key, map);
}
arg.endMap();
arg.endStructure();
return arg;
}
#if !PW_CHECK_VERSION(0, 2, 90)
/**
* @brief The PwType class - helper class to contain pointers to raw C pipewire media mappings
*/
class PwType {
public:
spa_type_media_type media_type;
spa_type_media_subtype media_subtype;
spa_type_format_video format_video;
spa_type_video_format video_format;
};
#endif
/**
* @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 {
public:
Private(PWFrameBuffer *q);
~Private();
private:
friend class PWFrameBuffer;
#if PW_CHECK_VERSION(0, 2, 90)
static void onCoreError(void *data, uint32_t id, int seq, int res, const char *message);
static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format);
#else
static void onStateChanged(void *data, pw_remote_state old, pw_remote_state state, const char *error);
static void onStreamFormatChanged(void *data, const struct spa_pod *format);
#endif
static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message);
static void onStreamProcess(void *data);
void initDbus();
void initPw();
#if !PW_CHECK_VERSION(0, 2, 90)
void initializePwTypes();
#endif
// dbus handling
void handleSessionCreated(quint32 &code, QVariantMap &results);
void handleDevicesSelected(quint32 &code, QVariantMap &results);
void handleSourcesSelected(quint32 &code, QVariantMap &results);
void handleRemoteDesktopStarted(quint32 &code, QVariantMap &results);
// pw handling
pw_stream *createReceivingStream();
void handleFrame(pw_buffer *pwBuffer);
// link to public interface
PWFrameBuffer *q;
// pipewire stuff
#if PW_CHECK_VERSION(0, 2, 90)
struct pw_context *pwContext = nullptr;
struct pw_core *pwCore = nullptr;
struct pw_stream *pwStream = nullptr;
struct pw_thread_loop *pwMainLoop = nullptr;
// wayland-like listeners
// ...of events that happen in pipewire server
spa_hook coreListener = {};
spa_hook streamListener = {};
// event handlers
pw_core_events pwCoreEvents = {};
pw_stream_events pwStreamEvents = {};
#else
pw_core *pwCore = nullptr;
pw_loop *pwLoop = nullptr;
pw_thread_loop *pwMainLoop = nullptr;
pw_stream *pwStream = nullptr;
pw_remote *pwRemote = nullptr;
pw_type *pwCoreType = nullptr;
PwType *pwType = nullptr;
spa_hook remoteListener = {};
spa_hook streamListener = {};
// event handlers
pw_remote_events pwRemoteEvents = {};
pw_stream_events pwStreamEvents = {};
#endif
uint pwStreamNodeId = 0;
// negotiated video format
spa_video_info_raw *videoFormat = nullptr;
// requests a session from XDG Desktop Portal
// auto-generated and compiled from xdp_dbus_interface.xml file
QScopedPointer<OrgFreedesktopPortalScreenCastInterface> dbusXdpScreenCastService;
QScopedPointer<OrgFreedesktopPortalRemoteDesktopInterface> dbusXdpRemoteDesktopService;
// XDP screencast session handle
QDBusObjectPath sessionPath;
// Pipewire file descriptor
QDBusUnixFileDescriptor pipewireFd;
// screen geometry holder
struct {
quint32 width;
quint32 height;
} screenGeometry;
// Allowed devices
uint devices;
// sanity indicator
bool isValid = true;
};
PWFrameBuffer::Private::Private(PWFrameBuffer *q) : q(q)
{
#if PW_CHECK_VERSION(0, 2, 90)
pwCoreEvents.version = PW_VERSION_CORE_EVENTS;
pwCoreEvents.error = &onCoreError;
pwStreamEvents.version = PW_VERSION_STREAM_EVENTS;
pwStreamEvents.state_changed = &onStreamStateChanged;
pwStreamEvents.param_changed = &onStreamParamChanged;
pwStreamEvents.process = &onStreamProcess;
#else
// initialize event handlers, remote end and stream-related
pwRemoteEvents.version = PW_VERSION_REMOTE_EVENTS;
pwRemoteEvents.state_changed = &onStateChanged;
pwStreamEvents.version = PW_VERSION_STREAM_EVENTS;
pwStreamEvents.state_changed = &onStreamStateChanged;
pwStreamEvents.format_changed = &onStreamFormatChanged;
pwStreamEvents.process = &onStreamProcess;
#endif
}
/**
* @brief PWFrameBuffer::Private::initDbus - initialize D-Bus connectivity with XDG Desktop Portal.
* Based on XDG_CURRENT_DESKTOP environment variable it will give us implementation that we need,
* in case of KDE it is xdg-desktop-portal-kde binary.
*/
void PWFrameBuffer::Private::initDbus()
{
qInfo() << "Initializing D-Bus connectivity with XDG Desktop Portal";
dbusXdpScreenCastService.reset(new OrgFreedesktopPortalScreenCastInterface(QLatin1String("org.freedesktop.portal.Desktop"),
QLatin1String("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QLatin1String("org.freedesktop.portal.Desktop"),
QLatin1String("/org/freedesktop/portal/desktop"),
QDBusConnection::sessionBus()));
auto version = dbusXdpScreenCastService->version();
if (version < MIN_SUPPORTED_XDP_KDE_SC_VERSION) {
qWarning() << "Unsupported XDG Portal screencast interface version:" << version;
isValid = false;
return;
}
// create session
auto sessionParameters = QVariantMap {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
{ QLatin1String("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) },
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
#else
{ QLatin1String("session_handle_token"), QStringLiteral("krfb%1").arg(qrand()) },
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(qrand()) }
#endif
};
auto sessionReply = dbusXdpRemoteDesktopService->CreateSession(sessionParameters);
sessionReply.waitForFinished();
if (!sessionReply.isValid()) {
qWarning("Couldn't initialize XDP-KDE screencast session");
isValid = false;
return;
}
qInfo() << "DBus session created: " << sessionReply.value().path();
QDBusConnection::sessionBus().connect(QString(),
sessionReply.value().path(),
QLatin1String("org.freedesktop.portal.Request"),
QLatin1String("Response"),
this->q,
SLOT(handleXdpSessionCreated(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpSessionCreated(quint32 code, QVariantMap results)
{
d->handleSessionCreated(code, results);
}
/**
* @brief PWFrameBuffer::Private::handleSessionCreated - handle creation of ScreenCast session.
* XDG Portal answers with session path if it was able to successfully create the screencast.
*
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleSessionCreated(quint32 &code, QVariantMap &results)
{
if (code != 0) {
qWarning() << "Failed to create session: " << code;
isValid = false;
return;
}
sessionPath = QDBusObjectPath(results.value(QLatin1String("session_handle")).toString());
// select sources for the session
auto selectionOptions = QVariantMap {
// We have to specify it's an uint, otherwise xdg-desktop-portal will not forward it to backend implementation
{ QLatin1String("types"), QVariant::fromValue<uint>(7) }, // request all (KeyBoard, Pointer, TouchScreen)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
#else
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(qrand()) }
#endif
};
auto selectorReply = dbusXdpRemoteDesktopService->SelectDevices(sessionPath, selectionOptions);
selectorReply.waitForFinished();
if (!selectorReply.isValid()) {
qWarning() << "Couldn't select devices for the remote-desktop session";
isValid = false;
return;
}
QDBusConnection::sessionBus().connect(QString(),
selectorReply.value().path(),
QLatin1String("org.freedesktop.portal.Request"),
QLatin1String("Response"),
this->q,
SLOT(handleXdpDevicesSelected(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpDevicesSelected(quint32 code, QVariantMap results)
{
d->handleDevicesSelected(code, results);
}
/**
* @brief PWFrameBuffer::Private::handleDevicesCreated - handle selection of devices we want to use for remote desktop
*
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleDevicesSelected(quint32 &code, QVariantMap &results)
{
Q_UNUSED(results)
if (code != 0) {
qWarning() << "Failed to select devices: " << code;
isValid = false;
return;
}
// select sources for the session
auto selectionOptions = QVariantMap {
{ QLatin1String("types"), QVariant::fromValue<uint>(1) }, // only MONITOR is supported
{ QLatin1String("multiple"), false },
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
#else
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(qrand()) }
#endif
};
auto selectorReply = dbusXdpScreenCastService->SelectSources(sessionPath, selectionOptions);
selectorReply.waitForFinished();
if (!selectorReply.isValid()) {
qWarning() << "Couldn't select sources for the screen-casting session";
isValid = false;
return;
}
QDBusConnection::sessionBus().connect(QString(),
selectorReply.value().path(),
QLatin1String("org.freedesktop.portal.Request"),
QLatin1String("Response"),
this->q,
SLOT(handleXdpSourcesSelected(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpSourcesSelected(quint32 code, QVariantMap results)
{
d->handleSourcesSelected(code, results);
}
/**
* @brief PWFrameBuffer::Private::handleSourcesSelected - handle Screencast sources selection.
* XDG Portal shows a dialog at this point which allows you to select monitor from the list.
* This function is called after you make a selection.
*
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleSourcesSelected(quint32 &code, QVariantMap &)
{
if (code != 0) {
qWarning() << "Failed to select sources: " << code;
isValid = false;
return;
}
// start session
auto startParameters = QVariantMap {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
#else
{ QLatin1String("handle_token"), QStringLiteral("krfb%1").arg(qrand()) }
#endif
};
auto startReply = dbusXdpRemoteDesktopService->Start(sessionPath, QString(), startParameters);
startReply.waitForFinished();
QDBusConnection::sessionBus().connect(QString(),
startReply.value().path(),
QLatin1String("org.freedesktop.portal.Request"),
QLatin1String("Response"),
this->q,
SLOT(handleXdpRemoteDesktopStarted(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, QVariantMap results)
{
d->handleRemoteDesktopStarted(code, results);
}
/**
* @brief PWFrameBuffer::Private::handleScreencastStarted - handle Screencast start.
* At this point there shall be ready pipewire stream to consume.
*
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 &code, QVariantMap &results)
{
if (code != 0) {
qWarning() << "Failed to start screencast: " << code;
isValid = false;
return;
}
// there should be only one stream
Streams streams = qdbus_cast<Streams>(results.value(QLatin1String("streams")));
if (streams.isEmpty()) {
// maybe we should check deeper with qdbus_cast but this suffices for now
qWarning() << "Failed to get screencast streams";
isValid = false;
return;
}
auto streamReply = dbusXdpScreenCastService->OpenPipeWireRemote(sessionPath, QVariantMap());
streamReply.waitForFinished();
if (!streamReply.isValid()) {
qWarning() << "Couldn't open pipewire remote for the screen-casting session";
isValid = false;
return;
}
pipewireFd = streamReply.value();
if (!pipewireFd.isValid()) {
qWarning() << "Couldn't get pipewire connection file descriptor";
isValid = false;
return;
}
QSize streamResolution = qdbus_cast<QSize>(streams.first().map.value(QLatin1String("size")));
screenGeometry.width = streamResolution.width();
screenGeometry.height = streamResolution.height();
devices = results.value(QLatin1String("types")).toUInt();
pwStreamNodeId = streams.first().nodeId;
// Reallocate our buffer with actual needed size
q->fb = static_cast<char*>(malloc(screenGeometry.width * screenGeometry.height * 4));
if (!q->fb) {
qWarning() << "Failed to allocate buffer";
isValid = false;
return;
}
Q_EMIT q->frameBufferChanged();
initPw();
}
/**
* @brief PWFrameBuffer::Private::initPw - initialize Pipewire socket connectivity.
* pipewireFd should be pointing to existing file descriptor that was passed by D-Bus at this point.
*/
void PWFrameBuffer::Private::initPw() {
qInfo() << "Initializing Pipewire connectivity";
// init pipewire (required)
pw_init(nullptr, nullptr); // args are not used anyways
#if PW_CHECK_VERSION(0, 2, 90)
pwMainLoop = pw_thread_loop_new("pipewire-main-loop", nullptr);
pwContext = pw_context_new(pw_thread_loop_get_loop(pwMainLoop), nullptr, 0);
if (!pwContext) {
qWarning() << "Failed to create PipeWire context";
return;
}
pwCore = pw_context_connect(pwContext, nullptr, 0);
if (!pwCore) {
qWarning() << "Failed to connect PipeWire context";
return;
}
pw_core_add_listener(pwCore, &coreListener, &pwCoreEvents, this);
pwStream = createReceivingStream();
if (!pwStream) {
qWarning() << "Failed to create PipeWire stream";
return;
}
#else
// initialize our source
pwLoop = pw_loop_new(nullptr);
pwMainLoop = pw_thread_loop_new(pwLoop, "pipewire-main-loop");
// create PipeWire core object (required)
pwCore = pw_core_new(pwLoop, nullptr);
pwCoreType = pw_core_get_type(pwCore);
initializePwTypes();
// pw_remote should be initialized before type maps or connection error will happen
pwRemote = pw_remote_new(pwCore, nullptr, 0);
// init PipeWire remote, add listener to handle events
pw_remote_add_listener(pwRemote, &remoteListener, &pwRemoteEvents, this);
pw_remote_connect_fd(pwRemote, pipewireFd.fileDescriptor());
#endif
if (pw_thread_loop_start(pwMainLoop) < 0) {
qWarning() << "Failed to start main PipeWire loop";
isValid = false;
}
}
#if !PW_CHECK_VERSION(0, 2, 9)
/**
* @brief PWFrameBuffer::Private::initializePwTypes - helper method to initialize and map all needed
* Pipewire types from core to type structure.
*/
void PWFrameBuffer::Private::initializePwTypes()
{
// raw C-like PipeWire type map
spa_type_map *map = pwCoreType->map;
pwType = new PwType();
spa_type_media_type_map(map, &pwType->media_type);
spa_type_media_subtype_map(map, &pwType->media_subtype);
spa_type_format_video_map(map, &pwType->format_video);
spa_type_video_format_map(map, &pwType->video_format);
}
#endif
#if PW_CHECK_VERSION(0, 2, 90)
void PWFrameBuffer::Private::onCoreError(void *data, uint32_t id, int seq, int res, const char *message)
{
Q_UNUSED(data);
Q_UNUSED(id);
Q_UNUSED(seq);
Q_UNUSED(res);
qInfo() << "core error: " << message;
}
#else
/**
* @brief PWFrameBuffer::Private::onStateChanged - global state tracking for pipewire connection
* @param data pointer that you have set in pw_remote_add_listener call's last argument
* @param state new state that connection has changed to
* @param error optional error message, is set to non-null if state is error
*/
void PWFrameBuffer::Private::onStateChanged(void *data, pw_remote_state /*old*/, pw_remote_state state, const char *error)
{
qInfo() << "remote state: " << pw_remote_state_as_string(state);
PWFrameBuffer::Private *d = static_cast<PWFrameBuffer::Private*>(data);
switch (state) {
case PW_REMOTE_STATE_ERROR:
qWarning() << "remote error: " << error;
break;
case PW_REMOTE_STATE_CONNECTED:
d->pwStream = d->createReceivingStream();
break;
default:
qInfo() << "remote state: " << pw_remote_state_as_string(state);
break;
}
}
#endif
/**
* @brief PWFrameBuffer::Private::onStreamStateChanged - called whenever stream state changes on pipewire server
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param state new state that stream has changed to
* @param error_message optional error message, is set to non-null if state is error
*/
void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /*old*/, pw_stream_state state, const char *error_message)
{
qInfo() << "Stream state changed: " << pw_stream_state_as_string(state);
auto *d = static_cast<PWFrameBuffer::Private *>(data);
#if PW_CHECK_VERSION(0, 2, 90)
switch (state) {
case PW_STREAM_STATE_ERROR:
qWarning() << "pipewire stream error: " << error_message;
break;
case PW_STREAM_STATE_PAUSED:
pw_stream_set_active(d->pwStream, true);
break;
case PW_STREAM_STATE_STREAMING:
case PW_STREAM_STATE_UNCONNECTED:
case PW_STREAM_STATE_CONNECTING:
break;
}
#else
switch (state) {
case PW_STREAM_STATE_ERROR:
qWarning() << "pipewire stream error: " << error_message;
break;
case PW_STREAM_STATE_CONFIGURE:
pw_stream_set_active(d->pwStream, true);
break;
default:
break;
}
#endif
}
/**
* @brief PWFrameBuffer::Private::onStreamFormatChanged - being executed after stream is set to active
* and after setup has been requested to connect to it. The actual video format is being negotiated here.
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param format format that's being proposed
*/
#if PW_CHECK_VERSION(0, 2, 90)
void PWFrameBuffer::Private::onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format)
#else
void PWFrameBuffer::Private::onStreamFormatChanged(void *data, const struct spa_pod *format)
#endif
{
qInfo() << "Stream format changed";
auto *d = static_cast<PWFrameBuffer::Private *>(data);
const int bpp = 4;
#if PW_CHECK_VERSION(0, 2, 90)
if (!format || id != SPA_PARAM_Format) {
#else
if (!format) {
pw_stream_finish_format(d->pwStream, 0, nullptr, 0);
#endif
return;
}
d->videoFormat = new spa_video_info_raw();
#if PW_CHECK_VERSION(0, 2, 90)
spa_format_video_raw_parse(format, d->videoFormat);
#else
spa_format_video_raw_parse(format, d->videoFormat, &d->pwType->format_video);
#endif
auto width = d->videoFormat->size.width;
auto height = d->videoFormat->size.height;
auto stride = SPA_ROUND_UP_N(width * bpp, 4);
auto size = height * stride;
uint8_t buffer[1024];
auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
// setup buffers and meta header for new format
const struct spa_pod *params[2];
#if PW_CHECK_VERSION(0, 2, 90)
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32),
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16)));
params[1] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))));
pw_stream_update_params(d->pwStream, params, 2);
#else
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_object(&builder,
d->pwCoreType->param.idBuffers, d->pwCoreType->param_buffers.Buffers,
":", d->pwCoreType->param_buffers.size, "i", size,
":", d->pwCoreType->param_buffers.stride, "i", stride,
":", d->pwCoreType->param_buffers.buffers, "iru", 8, SPA_POD_PROP_MIN_MAX(1, 32),
":", d->pwCoreType->param_buffers.align, "i", 16));
params[1] = reinterpret_cast<spa_pod *>(spa_pod_builder_object(&builder,
d->pwCoreType->param.idMeta, d->pwCoreType->param_meta.Meta,
":", d->pwCoreType->param_meta.type, "I", d->pwCoreType->meta.Header,
":", d->pwCoreType->param_meta.size, "i", sizeof(struct spa_meta_header)));
pw_stream_finish_format(d->pwStream, 0, params, 2);
#endif
}
/**
* @brief PWFrameBuffer::Private::onNewBuffer - called when new buffer is available in pipewire stream
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param id
*/
void PWFrameBuffer::Private::onStreamProcess(void *data)
{
auto *d = static_cast<PWFrameBuffer::Private *>(data);
pw_buffer *buf;
if (!(buf = pw_stream_dequeue_buffer(d->pwStream))) {
return;
}
d->handleFrame(buf);
pw_stream_queue_buffer(d->pwStream, buf);
}
void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer)
{
auto *spaBuffer = pwBuffer->buffer;
void *src = nullptr;
src = spaBuffer->datas[0].data;
if (!src) {
return;
}
quint32 maxSize = spaBuffer->datas[0].maxsize;
qint32 srcStride = spaBuffer->datas[0].chunk->stride;
if (srcStride != q->paddedWidth()) {
qWarning() << "Got buffer with stride different from screen stride" << srcStride << "!=" << q->paddedWidth();
return;
}
q->tiles.append(QRect(0, 0, q->width(), q->height()));
std::memcpy(q->fb, src, maxSize);
}
/**
* @brief PWFrameBuffer::Private::createReceivingStream - create a stream that will consume Pipewire buffers
* and copy the framebuffer to the existing image that we track. The state of the stream and configuration
* are later handled by the corresponding listener.
*/
pw_stream *PWFrameBuffer::Private::createReceivingStream()
{
spa_rectangle pwMinScreenBounds = SPA_RECTANGLE(1, 1);
spa_rectangle pwMaxScreenBounds = SPA_RECTANGLE(screenGeometry.width, screenGeometry.height);
spa_fraction pwFramerateMin = SPA_FRACTION(0, 1);
spa_fraction pwFramerateMax = SPA_FRACTION(60, 1);
#if PW_CHECK_VERSION(0, 2, 90)
auto stream = pw_stream_new_simple(pw_thread_loop_get_loop(pwMainLoop), "krfb-fb-consume-stream",
pw_properties_new(PW_KEY_MEDIA_TYPE, "Video",
PW_KEY_MEDIA_CATEGORY, "Capture",
PW_KEY_MEDIA_ROLE, "Screen",
nullptr),
&pwStreamEvents, this);
#else
auto reuseProps = pw_properties_new("pipewire.client.reuse", "1", nullptr); // null marks end of varargs
auto stream = pw_stream_new(pwRemote, "krfb-fb-consume-stream", reuseProps);
#endif
uint8_t buffer[1024] = {};
const spa_pod *params[1];
auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
#if PW_CHECK_VERSION(0, 2, 90)
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGBx),
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMaxScreenBounds, &pwMinScreenBounds, &pwMaxScreenBounds),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&pwFramerateMin),
SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction(&pwFramerateMax, &pwFramerateMin, &pwFramerateMax)));
#else
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_object(&builder,
pwCoreType->param.idEnumFormat, pwCoreType->spa_format,
"I", pwType->media_type.video,
"I", pwType->media_subtype.raw,
":", pwType->format_video.format, "I", pwType->video_format.RGBx,
":", pwType->format_video.size, "Rru", &pwMaxScreenBounds, SPA_POD_PROP_MIN_MAX(&pwMinScreenBounds, &pwMaxScreenBounds),
":", pwType->format_video.framerate, "F", &pwFramerateMin,
":", pwType->format_video.max_framerate, "Fru", &pwFramerateMax, 2, &pwFramerateMin, &pwFramerateMax));
pw_stream_add_listener(stream, &streamListener, &pwStreamEvents, this);
#endif
auto flags = static_cast<pw_stream_flags>(PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_MAP_BUFFERS);
#if PW_CHECK_VERSION(0, 2, 90)
if (pw_stream_connect(stream, PW_DIRECTION_INPUT, PW_ID_ANY, flags, params, 1) != 0) {
#else
if (pw_stream_connect(stream, PW_DIRECTION_INPUT, nullptr, flags, params, 1) != 0) {
#endif
qWarning() << "Could not connect receiving stream";
isValid = false;
}
return stream;
}
PWFrameBuffer::Private::~Private()
{
if (pwMainLoop) {
pw_thread_loop_stop(pwMainLoop);
}
#if !PW_CHECK_VERSION(0, 2, 9)
if (pwType) {
delete pwType;
}
#endif
if (pwStream) {
pw_stream_destroy(pwStream);
}
#if !PW_CHECK_VERSION(0, 2, 90)
if (pwRemote) {
pw_remote_destroy(pwRemote);
}
#endif
#if PW_CHECK_VERSION(0, 2, 90)
if (pwCore) {
pw_core_disconnect(pwCore);
}
if (pwContext) {
pw_context_destroy(pwContext);
}
#else
if (pwCore) {
pw_core_destroy(pwCore);
}
#endif
if (pwMainLoop) {
pw_thread_loop_destroy(pwMainLoop);
}
#if !PW_CHECK_VERSION(0, 2, 90)
if (pwLoop) {
pw_loop_leave(pwLoop);
pw_loop_destroy(pwLoop);
}
#endif
}
PWFrameBuffer::PWFrameBuffer(WId winid, QObject *parent)
: FrameBuffer (winid, parent),
d(new Private(this))
{
// D-Bus is most important in init chain, no toys for us if something is wrong with XDP
// PipeWire connectivity is initialized after D-Bus session is started
d->initDbus();
// FIXME: for now use some initial size, later on we will reallocate this with the actual size we get from portal
d->screenGeometry.width = 800;
d->screenGeometry.height = 600;
fb = nullptr;
}
PWFrameBuffer::~PWFrameBuffer()
{
free(fb);
fb = nullptr;
}
int PWFrameBuffer::depth()
{
return 32;
}
int PWFrameBuffer::height()
{
return static_cast<qint32>(d->screenGeometry.height);
}
int PWFrameBuffer::width()
{
return static_cast<qint32>(d->screenGeometry.width);
}
int PWFrameBuffer::paddedWidth()
{
return width() * 4;
}
void PWFrameBuffer::getServerFormat(rfbPixelFormat &format)
{
format.bitsPerPixel = 32;
format.depth = 32;
format.trueColour = true;
format.bigEndian = false;
}
void PWFrameBuffer::startMonitor()
{
}
void PWFrameBuffer::stopMonitor()
{
}
QVariant PWFrameBuffer::customProperty(const QString &property) const
{
if (property == QLatin1String("stream_node_id")) {
return QVariant::fromValue<uint>(d->pwStreamNodeId);
} if (property == QLatin1String("session_handle")) {
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
}
return FrameBuffer::customProperty(property);
}
bool PWFrameBuffer::isValid() const
{
return d->isValid;
}

View File

@@ -1,59 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2018 Oleg Chernovskiy <kanedias@xaker.ru>
Copyright (C) 2018-2020 Jan Grulich <jgrulich@redhat.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
*/
#ifndef KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
#include "framebuffer.h"
#include <QWidget>
#include <QVariantMap>
/**
* @brief The PWFrameBuffer class - framebuffer implementation based on XDG Desktop Portal ScreenCast interface.
* The design relies heavily on a presence of XDG D-Bus service and PipeWire daemon.
*
* @author Oleg Chernovskiy <kanedias@xaker.ru>
*/
class PWFrameBuffer: public FrameBuffer
{
Q_OBJECT
public:
typedef struct {
uint nodeId;
QVariantMap map;
} Stream;
typedef QList<Stream> Streams;
PWFrameBuffer(WId winid, QObject *parent = nullptr);
virtual ~PWFrameBuffer() override;
int depth() override;
int height() override;
int width() override;
int paddedWidth() override;
void getServerFormat(rfbPixelFormat &format) override;
void startMonitor() override;
void stopMonitor() override;
QVariant customProperty(const QString &property) const override;
bool isValid() const;
private Q_SLOTS:
void handleXdpSessionCreated(quint32 code, QVariantMap results);
void handleXdpDevicesSelected(quint32 code, QVariantMap results);
void handleXdpSourcesSelected(quint32 code, QVariantMap results);
void handleXdpRemoteDesktopStarted(quint32 code, QVariantMap results);
private:
class Private;
const QScopedPointer<Private> d;
};
#endif

View File

@@ -1,53 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2018 Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "pw_framebufferplugin.h"
#include "pw_framebuffer.h"
#include <KPluginFactory>
K_PLUGIN_FACTORY_WITH_JSON(PWFrameBufferPluginFactory, "krfb_framebuffer_pw.json",
registerPlugin<PWFrameBufferPlugin>();)
PWFrameBufferPlugin::PWFrameBufferPlugin(QObject *parent, const QVariantList &args)
: FrameBufferPlugin(parent, args)
{
}
PWFrameBufferPlugin::~PWFrameBufferPlugin()
{
}
FrameBuffer *PWFrameBufferPlugin::frameBuffer(WId id)
{
auto pwfb = new PWFrameBuffer(id);
// sanity check for dbus/wayland/pipewire errors
if (!pwfb->isValid()) {
delete pwfb;
return nullptr;
}
return pwfb;
}
#include "pw_framebufferplugin.moc"

View File

@@ -1,45 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2018 Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
#define KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
#include "framebufferplugin.h"
#include <QWidget>
class FrameBuffer;
class PWFrameBufferPlugin: public FrameBufferPlugin
{
Q_OBJECT
public:
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
virtual ~PWFrameBufferPlugin() override;
FrameBuffer *frameBuffer(WId id) override;
private:
Q_DISABLE_COPY(PWFrameBufferPlugin)
};
#endif // Header guard

View File

@@ -5,13 +5,12 @@
"Description[ca]": "«Framebuffer» basat en les Qt per al KRfb.",
"Description[cs]": "Framebuffer založený na Qt pro KRfb.",
"Description[da]": "Qt-baseret framebuffer til KRfb.",
"Description[de]": "Qt-basierter Framebuffer für KRfb.",
"Description[de]": "Qt-basierter Framebuffer für KRfb",
"Description[el]": "Μνήμη ανανέωσης βίντεο με βάση τhn Qt για το KRfb.",
"Description[en_GB]": "Qt based Framebuffer for KRfb.",
"Description[es]": "Framebuffer basado en Qt para KRfb.",
"Description[et]": "KRfb Qt põhine kaadripuhver",
"Description[eu]": "KRfb-rako Qt-n oinarritutako «Framebuffer».",
"Description[fi]": "KRfb:n Qt-pohjainen kehyspuskuri.",
"Description[fi]": "QT-perustainen Kehyspuskuri KRfb:lle",
"Description[fr]": "Tampon d'images utilisant Qt pour KRfb.",
"Description[gl]": "Framebuffer baseado en Qt para KRfb.",
"Description[ia]": "Framebuffer basate sur Qt per KRfb",
@@ -20,12 +19,12 @@
"Description[ko]": "KRfb용 Qt 기반 프레임버퍼입니다.",
"Description[nl]": "Op Qt gebaseerd framebuffer voor KRfb.",
"Description[nn]": "Qt-basert biletbuffer for KRfb.",
"Description[pl]": "Bufor ramki oparty na Qt dla KRfb.",
"Description[pl]": "Bufor ramki na podstawie Qt dla KRfb.",
"Description[pt]": "'Framebuffer' baseado no Qt para o KRfb.",
"Description[pt_BR]": "Framebuffer baseado no Qt para o KRfb.",
"Description[ru]": "Буфер кадров для KRfb на базе Qt",
"Description[sk]": "Framebuffer založený na Qt pre KRfb.",
"Description[sl]": "Slikovni medpomnilnik za KRfb na osnovi Qt.",
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na Qt",
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу КуТу",
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu Qtu",
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu Qtu",
@@ -49,8 +48,7 @@
"Name[en_GB]": "Qt Framebuffer for KRfb",
"Name[es]": "Framebuffer de Qt para KRfb",
"Name[et]": "KRfb Qt kaadripuhver",
"Name[eu]": "KRfb-rako Qt «Framebuffer»",
"Name[fi]": "KRfb:n Qt-kehyspuskuri",
"Name[fi]": "QT-kehyspuskuri KRfb:lle",
"Name[fr]": "Tampon d'images Qt pour KRfb",
"Name[gl]": "Framebuffer de Qt para KRfb",
"Name[ia]": "Framebuffer Qt per KRfb",
@@ -64,12 +62,12 @@
"Name[pt_BR]": "Framebuffer do Qt para o KRfb",
"Name[ru]": "Буфер кадров Qt для KRfb",
"Name[sk]": "Qt Framebuffer pre KRfb",
"Name[sl]": "Slikovni medpomnilnik za KRfb na osnovi Qt",
"Name[sl]": "Slikovni medpomnilnik Qt za KRfb",
"Name[sr@ijekavian]": "КуТ‑ов кадробафер за КРФБ",
"Name[sr@ijekavianlatin]": "Qtov kadrobafer za KRFB",
"Name[sr@latin]": "Qtov kadrobafer za KRFB",
"Name[sr]": "КуТ‑ов кадробафер за КРФБ",
"Name[sv]": "QT-rambuffert för Krfb",
"Name[sv]": "X11-rambuffert för Krfb",
"Name[tr]": "KRfb için Qt Çerçeve tamponu",
"Name[uk]": "Буфер кадрів на Qt для KRfb",
"Name[x-test]": "xxQt Framebuffer for KRfbxx",

View File

@@ -26,11 +26,7 @@ QtFrameBuffer::QtFrameBuffer(WId id, QObject *parent)
if (screen) {
primaryScreen = screen;
fbImage = screen->grabWindow(win).toImage();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
fb = new char[fbImage.sizeInBytes()];
#else
fb = new char[fbImage.byteCount()];
#endif
} else {
fb = nullptr;
primaryScreen = nullptr;
@@ -108,11 +104,7 @@ void QtFrameBuffer::updateFrameBuffer()
tiles.append(img.rect());
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
memcpy(fb, img.bits(), static_cast<size_t>(img.sizeInBytes()));
#else
memcpy(fb, img.bits(), img.byteCount());
#endif
memcpy(fb, (const char *)img.bits(), img.byteCount());
fbImage = img;
}

View File

@@ -1,8 +1,8 @@
{
"KPlugin": {
"Description": "X11 XDamage/XShm based Framebuffer for KRfb.",
"Description[ca@valencia]": "«Framebuffer» basat en XDamage/XShm de l'X11 per al KRfb.",
"Description[ca]": "«Framebuffer» basat en XDamage/XShm de l'X11 per al KRfb.",
"Description[ca@valencia]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
"Description[ca]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
"Description[cs]": "Framebuffer založený na X11 XDamage/XShm pro KRfb.",
"Description[da]": "X11 XDamage/XShm-baseret framebuffer til KRfb.",
"Description[de]": "X11 XDamage/XShm-basierter Framebuffer für KRfb.",
@@ -10,8 +10,7 @@
"Description[en_GB]": "X11 XDamage/XShm based Framebuffer for KRfb.",
"Description[es]": "Framebuffer basado en XDamage/XShm de X11 para KRfb.",
"Description[et]": "KRfb X11 XDamage/XShm põhine kaadripuhver",
"Description[eu]": "KRfb-rako «X11 XDamage/XShm»en oinarritutako «Framebuffer».",
"Description[fi]": "KRfb:n X11 XDamage/XShm -pohjainen kehyspuskuri.",
"Description[fi]": "X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.",
"Description[fr]": "Tampon d'images utilisant XDamage/XShm de X11 pour KRfb.",
"Description[gl]": "Framebuffer baseado en X11 XDamage/Xshm para XRfb.",
"Description[ia]": "Framebuffer basate sur X11 XDamage/XShm per KRfb.",
@@ -25,7 +24,7 @@
"Description[pt_BR]": "Framebuffer baseado no XDamage/XShm do X11 para o KRfb.",
"Description[ru]": "Буфер кадров для KRfb на базе X11 XDamage/XShm",
"Description[sk]": "Framebuffer založený na X11 XDamage/XShm pre KRfb.",
"Description[sl]": "Slikovni medpomnilnik za KRfb, na osnovi X11 XDamage/XShm.",
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na X11 XDamage/XShm",
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.",
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
@@ -40,8 +39,8 @@
"Id": "xcb",
"License": "GPL",
"Name": "X11 Framebuffer for KRfb",
"Name[ca@valencia]": "«Framebuffer» de l'X11 per al KRfb.",
"Name[ca]": "«Framebuffer» de l'X11 per al KRfb.",
"Name[ca@valencia]": "«Framebuffer» del X11 per al KRfb.",
"Name[ca]": "«Framebuffer» del X11 per al KRfb.",
"Name[cs]": "X11 Framebuffer pro KRfb",
"Name[da]": "X11-framebuffer til KRfb",
"Name[de]": "X11-Framebuffer für KRfb",
@@ -49,8 +48,7 @@
"Name[en_GB]": "X11 Framebuffer for KRfb",
"Name[es]": "Framebuffer X11 para KRfb",
"Name[et]": "KRfb X11 kaadripuhver",
"Name[eu]": "KRfb-rako «X11 Framebuffer»",
"Name[fi]": "KRfb:n X11-kehyspuskuri",
"Name[fi]": "X11-kehyspuskuri KRfb:lle",
"Name[fr]": "Tampon d'images X11 pour KRfb",
"Name[gl]": "Framebuffer de X11 para KRfb",
"Name[ia]": "Framebuffer X11 per KRfb",
@@ -64,7 +62,7 @@
"Name[pt_BR]": "Framebuffer do X11 para o KRfb",
"Name[ru]": "Буфер кадров X11 для KRfb",
"Name[sk]": "X11 Framebuffer pre KRfb",
"Name[sl]": "Slikovni medpomnilnik za KRfb na osnovi X11",
"Name[sl]": "Slikovni medpomnilnik X11 za KRfb",
"Name[sr@ijekavian]": "Икс11 кадробафер за КРФБ.",
"Name[sr@ijekavianlatin]": "X11 kadrobafer za KRFB.",
"Name[sr@latin]": "X11 kadrobafer za KRFB.",

View File

@@ -381,50 +381,49 @@ void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
// information about pixels layout
if (root_visualtype) {
uint16_t pixelmaxValue = (1 << root_visualtype->bits_per_rgb_value) - 1;
#ifdef _DEBUG
qDebug("xcb framebuffer: Got info about root visual:\n"
" bits per rgb value: %d\n"
" red mask: %08x\n"
" green mask: %08x\n"
" blue mask: %08x\n",
" blue mask: %08x\n"
" pixelMaxValue = %d\n",
(int)root_visualtype->bits_per_rgb_value,
root_visualtype->red_mask,
root_visualtype->green_mask,
root_visualtype->blue_mask);
root_visualtype->blue_mask,
(int)pixelmaxValue);
#endif
// calculate shifts
format.redShift = 0;
format.redMax = pixelmaxValue;
if (root_visualtype->red_mask) {
while (!(root_visualtype->red_mask & (1 << format.redShift))) {
format.redShift++;
}
}
format.greenShift = 0;
format.greenMax = pixelmaxValue;
if (root_visualtype->green_mask) {
while (!(root_visualtype->green_mask & (1 << format.greenShift))) {
format.greenShift++;
}
}
format.blueShift = 0;
format.blueMax = pixelmaxValue;
if (root_visualtype->blue_mask) {
while (!(root_visualtype->blue_mask & (1 << format.blueShift))) {
format.blueShift++;
}
}
// calculate pixel max value.
// NOTE: bits_per_rgb_value is unreliable, thus should be avoided.
format.redMax = root_visualtype->red_mask >> format.redShift;
format.greenMax = root_visualtype->green_mask >> format.greenShift;
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
#ifdef _DEBUG
qDebug() << " Calculated redShift =" << (int)format.redShift;
qDebug() << " Calculated greenShift =" << (int)format.greenShift;
qDebug() << " Calculated blueShift =" << (int)format.blueShift;
qDebug( " Calculated max values: R%d G%d B%d",
format.redMax, format.greenMax, format.blueMax);
#endif
} else {
// some kind of fallback (unlikely code execution will go this way)

3
krfb.kdev4 Normal file
View File

@@ -0,0 +1,3 @@
[Project]
Manager=KDevCMakeManager
Name=krfb

View File

@@ -11,8 +11,6 @@ include(GenerateExportHeader)
set (krfbprivate_SRCS
framebuffer.cpp
framebufferplugin.cpp
events.cpp
eventsplugin.cpp
)
add_library (krfbprivate
@@ -21,7 +19,6 @@ add_library (krfbprivate
)
generate_export_header(krfbprivate BASE_NAME krfbprivate)
target_link_libraries (krfbprivate
Qt5::Core
Qt5::Widgets
@@ -42,7 +39,6 @@ install (TARGETS krfbprivate
install (FILES
krfb-framebuffer.desktop
krfb-events.desktop
DESTINATION ${SERVICETYPES_INSTALL_DIR}
)
@@ -52,9 +48,8 @@ install (FILES
set (krfb_SRCS
connectiondialog.cpp
framebuffermanager.cpp
events.cpp
eventsmanager.cpp
framebuffermanager.cpp
main.cpp
mainwindow.cpp
sockethelpers.cpp
@@ -101,7 +96,6 @@ target_link_libraries (krfb
KF5::Notifications
KF5::Wallet
KF5::WidgetsAddons
KF5::WindowSystem
KF5::XmlGui
${LIBVNCSERVER_LIBRARIES}
)
@@ -129,4 +123,4 @@ install(FILES org.kde.krfb.appdata.xml
install (FILES krfb.notifyrc
DESTINATION ${DATA_INSTALL_DIR}/krfb
)

View File

@@ -24,17 +24,177 @@
#include "events.h"
EventHandler::EventHandler(QObject *parent)
: QObject(parent)
#include <QApplication>
#include <QX11Info>
#include <QDesktopWidget>
#include <QGlobalStatic>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
enum {
LEFTSHIFT = 1,
RIGHTSHIFT = 2,
ALTGR = 4
};
class EventData
{
public:
EventData();
//keyboard
Display *dpy;
signed char modifiers[0x100];
KeyCode keycodes[0x100];
KeyCode leftShiftCode;
KeyCode rightShiftCode;
KeyCode altGrCode;
char modifierState;
//mouse
int buttonMask;
private:
void init();
};
Q_GLOBAL_STATIC(EventData, data)
EventData::EventData()
{
init();
}
void EventHandler::setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer)
void EventData::init()
{
fb = frameBuffer;
dpy = QX11Info::display();
buttonMask = 0;
//initialize keycodes
KeySym key, *keymap;
int i, j, minkey, maxkey, syms_per_keycode;
memset(modifiers, -1, sizeof(modifiers));
XDisplayKeycodes(dpy, &minkey, &maxkey);
Q_ASSERT(minkey >= 8);
Q_ASSERT(maxkey < 256);
keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey,
(maxkey - minkey + 1),
&syms_per_keycode);
Q_ASSERT(keymap);
for (i = minkey; i <= maxkey; i++) {
for (j = 0; j < syms_per_keycode; j++) {
key = keymap[(i-minkey)*syms_per_keycode+j];
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
keycodes[key] = i;
modifiers[key] = j;
}
}
}
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
XFree((char *)keymap);
}
QSharedPointer<FrameBuffer> EventHandler::frameBuffer()
/* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */
static void tweakModifiers(signed char mod, bool down)
{
return fb;
bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT);
if (mod < 0) {
return;
}
if (isShift && mod != 1) {
if (data->modifierState & LEFTSHIFT) {
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
down, CurrentTime);
}
if (data->modifierState & RIGHTSHIFT) {
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
down, CurrentTime);
}
}
if (!isShift && mod == 1) {
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
down, CurrentTime);
}
if ((data->modifierState & ALTGR) && mod != 2) {
XTestFakeKeyEvent(data->dpy, data->altGrCode,
!down, CurrentTime);
}
if (!(data->modifierState & ALTGR) && mod == 2) {
XTestFakeKeyEvent(data->dpy, data->altGrCode,
down, CurrentTime);
}
}
void EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
{
#define ADJUSTMOD(sym,state) \
if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; }
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT);
ADJUSTMOD(XK_Mode_switch, ALTGR);
if (keySym >= ' ' && keySym < 0x100) {
KeyCode k;
if (down) {
tweakModifiers(data->modifiers[keySym], True);
}
k = data->keycodes[keySym];
if (k != NoSymbol) {
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
}
if (down) {
tweakModifiers(data->modifiers[keySym], False);
}
} else {
KeyCode k = XKeysymToKeycode(data->dpy, keySym);
if (k != NoSymbol) {
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
}
}
}
void EventHandler::handlePointer(int buttonMask, int x, int y)
{
QDesktopWidget *desktopWidget = QApplication::desktop();
int screen = desktopWidget->screenNumber();
if (screen < 0) {
screen = 0;
}
XTestFakeMotionEvent(data->dpy, screen, x, y, CurrentTime);
for (int i = 0; i < 5; i++) {
if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) {
XTestFakeButtonEvent(data->dpy,
i + 1,
(buttonMask&(1 << i)) ? True : False,
CurrentTime);
}
}
data->buttonMask = buttonMask;
}

View File

@@ -25,26 +25,13 @@
#ifndef EVENTS_H
#define EVENTS_H
#include "framebuffer.h"
#include "rfb.h"
#include "krfbprivate_export.h"
#include <QObject>
class KRFBPRIVATE_EXPORT EventHandler : public QObject
class EventHandler
{
Q_OBJECT
public:
explicit EventHandler(QObject *parent = nullptr);
virtual ~EventHandler() = default;
virtual void handleKeyboard(bool down, rfbKeySym key) = 0;
virtual void handlePointer(int buttonMask, int x, int y) = 0;
void setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer);
QSharedPointer<FrameBuffer> frameBuffer();
private:
// Used to track framebuffer plugin which we need for xdp event plugin
QSharedPointer<FrameBuffer> fb;
static void handleKeyboard(bool down, rfbKeySym key);
static void handlePointer(int buttonMask, int x, int y);
};
#endif

View File

@@ -1,118 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
@author George Goldberg <george.goldberg@collabora.co.uk>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "eventsmanager.h"
#include "eventsplugin.h"
#include "krfbconfig.h"
#include "rfbservermanager.h"
#include <QDebug>
#include <QGlobalStatic>
#include <KPluginFactory>
#include <KPluginLoader>
#include <KPluginMetaData>
#include <QtCore/QSharedPointer>
class EventsManagerStatic
{
public:
EventsManager instance;
};
Q_GLOBAL_STATIC(EventsManagerStatic, eventsManagerStatic)
EventsManager::EventsManager()
{
//qDebug();
loadPlugins();
}
EventsManager::~EventsManager()
{
//qDebug();
}
EventsManager *EventsManager::instance()
{
//qDebug();
return &eventsManagerStatic->instance;
}
void EventsManager::loadPlugins()
{
//qDebug();
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("krfb"), [](const KPluginMetaData & md) {
return md.serviceTypes().contains(QStringLiteral("krfb/events"));
});
QVectorIterator<KPluginMetaData> i(plugins);
i.toBack();
QSet<QString> unique;
while (i.hasPrevious()) {
KPluginMetaData data = i.previous();
// only load plugins once, even if found multiple times!
if (unique.contains(data.name()))
continue;
KPluginFactory *factory = KPluginLoader(data.fileName()).factory();
if (!factory) {
qDebug() << "KPluginFactory could not load the plugin:" << data.fileName();
continue;
} else {
qDebug() << "found plugin at " << data.fileName();
}
EventsPlugin *plugin = factory->create<EventsPlugin>(this);
if (plugin) {
m_plugins.insert(data.pluginId(), plugin);
qDebug() << "Loaded plugin with name " << data.pluginId();
} else {
qDebug() << "unable to load plugin for " << data.fileName();
}
unique.insert (data.name());
}
}
QSharedPointer<EventHandler> EventsManager::eventHandler()
{
QMap<QString, EventsPlugin *>::const_iterator iter = m_plugins.constBegin();
while (iter != m_plugins.constEnd()) {
QSharedPointer<EventHandler> eventHandler(iter.value()->eventHandler());
if (eventHandler) {
eventHandler->setFrameBufferPlugin(RfbServerManager::instance()->framebuffer());
return eventHandler;
}
++iter;
}
// No valid events plugin found.
qDebug() << "No valid event handlers found. returning null.";
return QSharedPointer<EventHandler>();
}

View File

@@ -1,62 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
@author George Goldberg <george.goldberg@collabora.co.uk>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KRFB_EVENTSMANAGER_H
#define KRFB_EVENTSMANAGER_H
#include "events.h"
#include "krfbprivate_export.h"
#include <QtCore/QMap>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QtCore/QWeakPointer>
#include <QWidget>
class EventsPlugin;
class KPluginFactory;
class KRFBPRIVATE_EXPORT EventsManager : public QObject
{
Q_OBJECT
friend class EventsManagerStatic;
public:
static EventsManager *instance();
virtual ~EventsManager();
QSharedPointer<EventHandler> eventHandler();
private:
Q_DISABLE_COPY(EventsManager)
EventsManager();
void loadPlugins();
QMap<QString, EventsPlugin *> m_plugins;
QList<QWeakPointer<EventHandler> > m_eventHandlers;
};
#endif // Header guard

View File

@@ -1,32 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2016 Oleg Chernovskiy <kanedias@xaker.ru>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "eventsplugin.h"
#include "events.h"
EventsPlugin::EventsPlugin(QObject *parent, const QVariantList &)
: QObject(parent)
{
}
EventsPlugin::~EventsPlugin()
{
}

View File

@@ -1,42 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
@author George Goldberg <george.goldberg@collabora.co.uk>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef LIB_KRFB_EVENTSPLUGIN_H
#define LIB_KRFB_EVENTSPLUGIN_H
#include "krfbprivate_export.h"
#include <QtCore/QVariantList>
#include <QWidget>
class EventHandler;
class KRFBPRIVATE_EXPORT EventsPlugin : public QObject
{
Q_OBJECT
public:
EventsPlugin(QObject *parent, const QVariantList &args);
virtual ~EventsPlugin();
virtual EventHandler *eventHandler() = 0;
};
#endif // Header guard

View File

@@ -50,12 +50,6 @@ void FrameBuffer::getServerFormat(rfbPixelFormat &)
{
}
QVariant FrameBuffer::customProperty(const QString &property) const
{
Q_UNUSED(property)
return QVariant();
}
int FrameBuffer::depth()
{
return 32;

View File

@@ -17,7 +17,6 @@
#include <QObject>
#include <QRect>
#include <QList>
#include <QVariant>
#include <QWidget>
@@ -45,10 +44,6 @@ public:
virtual void getServerFormat(rfbPixelFormat &format);
virtual QVariant customProperty(const QString &property) const;
Q_SIGNALS:
void frameBufferChanged();
protected:
WId win;
char *fb;

View File

@@ -79,7 +79,6 @@ void FrameBufferManager::loadPlugins()
if (!factory) {
qDebug() << "KPluginFactory could not load the plugin:" << data.fileName();
continue;
} else {
qDebug() << "found plugin at " << data.fileName();
}

View File

@@ -125,6 +125,7 @@ void PendingInvitationsRfbClient::onSocketActivated()
bool PendingInvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
{
QByteArray password ;
qDebug() << "about to start authentication";
if(InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword(

View File

@@ -119,7 +119,7 @@ InvitationsRfbServer::InvitationsRfbServer()
InvitationsRfbServer::~InvitationsRfbServer()
{
InvitationsRfbServer::stop(); // calling virtual funcs in destructor is bad
stop();
KConfigGroup krfbConfig(KSharedConfig::openConfig(), "Security");
krfbConfig.writeEntry("allowUnattendedAccess", m_allowUnattendedAccess);

View File

@@ -1,32 +0,0 @@
[Desktop Entry]
Type=ServiceType
X-KDE-ServiceType=krfb/events
Comment=Event plugins for KRfb
Comment[ca]=Connectors d'esdeveniments per al KRfb.
Comment[ca@valencia]=Connectors d'esdeveniments per al KRfb.
Comment[cs]=Moduly událostí pro KRfb
Comment[de]=Ereignis-Module für KRfb
Comment[el]=Πρόσθετα γεγονότων για το KRfb
Comment[en_GB]=Event plugins for KRfb
Comment[es]=Complementos de eventos para KRfb
Comment[et]=KRfb sündmuste pluginad
Comment[eu]=KRfb-rako gertaeren pluginak
Comment[fi]=KRfb:n tapahtumaliitännäinen
Comment[fr]=Modules externes d'événements pour Krfb
Comment[gl]=Complementos de eventos para KRfb
Comment[it]=Estensioni degli eventi per KRfb
Comment[ko]=KRfb 이벤트 플러그인
Comment[nl]=Plug-ins voor gebeurtenis voor KRfb
Comment[nn]=Hendingstillegg for KRfb
Comment[pl]=Wtyczki wydarzeń dla KRfb
Comment[pt]='Plugins' de eventos para o KRfb
Comment[pt_BR]=Plugins de evento para o KRfb
Comment[sk]=Doplnky udalostí pre KRfb
Comment[sl]=Vstavki dogodkov za KRFB
Comment[sv]=Händelseinsticksprogram för Krfb
Comment[uk]=Додатки обробки подій для KRfb
Comment[x-test]=xxEvent plugins for KRfbxx
Comment[zh_CN]=KRfb 事件插件
Comment[zh_TW]=KRfb 的事件外掛程式

View File

@@ -1,32 +0,0 @@
{
"KPlugin": {
"Description": "Events plugins for KRfb",
"Description[ca@valencia]": "Connectors d'esdeveniments per al KRfb.",
"Description[ca]": "Connectors d'esdeveniments per al KRfb.",
"Description[cs]": "Moduly událostí pro KRfb",
"Description[de]": "Ereignis-Module für KRfb",
"Description[el]": "Πρόσθετα γεγονότων για το KRfb",
"Description[en_GB]": "Events plugins for KRfb",
"Description[es]": "Complementos de eventos para KRfb",
"Description[et]": "KRfb sündmuste pluginad",
"Description[eu]": "KRfb-rako gertaeren pluginak",
"Description[fi]": "KRfb:n tapahtumaliitännäinen",
"Description[fr]": "Modules externes d'évènements pour KRfb",
"Description[gl]": "Complementos de eventos para KRfb",
"Description[it]": "Estensioni degli eventi per KRfb",
"Description[ko]": "KRfb 이벤트 플러그인",
"Description[nl]": "Plug-ins voor gebeurtenis voor KRfb",
"Description[nn]": "Hendingstillegg for KRfb",
"Description[pl]": "Wtyczki wydarzeń dla KRfb",
"Description[pt]": "'Plugins' de eventos para o KRfb",
"Description[pt_BR]": "Plugins de evento para o KRfb",
"Description[sk]": "Doplnky udalostí pre KRfb",
"Description[sl]": "Vtičniki za dogodke za KRfb",
"Description[sv]": "Händelseinsticksprogram för Krfb",
"Description[uk]": "Додатки обробки подій для KRfb",
"Description[x-test]": "xxEvents plugins for KRfbxx",
"Description[zh_CN]": "KRfb 事件插件",
"Description[zh_TW]": "KRfb 的事件外掛程式"
},
"X-KDE-ServiceType": "krfb/events"
}

View File

@@ -36,7 +36,7 @@ Comment[nl]=Framebuffer-plugins voor KRfb
Comment[nn]=Framebuffer-tillegg KRfb
Comment[pa]=KRfb ਲਈ ਫਰੇਮ ਬਫ਼ਰ ਪਲੱਗਇਨ
Comment[pl]=Wtyczki buforów ramek dla KRfb
Comment[pt]='Plugins' do 'Framebuffer' para o KRfb
Comment[pt]='Plugins' de 'framebuffers' para o KRfb
Comment[pt_BR]=Plugins de framebuffers para o KRfb
Comment[ru]=Модуль буфера кадров для KRfb
Comment[si]=KRfb සඳහා රාමු බෆර ප්ලගින

View File

@@ -1,8 +1,8 @@
{
"KPlugin": {
"Description": "Frame Buffer plugins for KRfb",
"Description[ca@valencia]": "Connectors de «Frame Buffer» per al KRfb.",
"Description[ca]": "Connectors de «Frame Buffer» per al KRfb.",
"Description[ca@valencia]": "Connectors de «framebuffer» per al KRfb.",
"Description[ca]": "Connectors de «framebuffer» per al KRfb.",
"Description[cs]": "Moduly Frame bufferu pro KRfb",
"Description[da]": "Framebuffer-plugins til KRfb",
"Description[de]": "Framebuffer-Module für KRfb",
@@ -10,8 +10,7 @@
"Description[en_GB]": "Frame Buffer plugins for KRfb",
"Description[es]": "Complementos de framebuffer para KRfb",
"Description[et]": "KRfb kaadripuhvri pluginad",
"Description[eu]": "KRfb-rako «Frame Buffer» pluginak",
"Description[fi]": "KRfb:n kehyspuskuriliitännäinen",
"Description[fi]": "Kehyspuskuriliitännäinen kohteelle KRfb",
"Description[fr]": "Modules de tampons d'image pour KRfb",
"Description[gl]": "Complemento de búfer de fotograma para KRfb",
"Description[ia]": "Plug-ins de Frame Buffer per KRfb",
@@ -25,7 +24,7 @@
"Description[pt_BR]": "Plugins de framebuffers para o KRfb",
"Description[ru]": "Модули буфера кадров для KRfb",
"Description[sk]": "Frame Buffer modul pre KRfb",
"Description[sl]": "Vtičniki vmesnika medpomnilnika za KRfb",
"Description[sl]": "Vstavki slikovnih medpomnilnikov za KRfb",
"Description[sr@ijekavian]": "Прикључци кадробафера за КРФБ",
"Description[sr@ijekavianlatin]": "Priključci kadrobafera za KRFB",
"Description[sr@latin]": "Priključci kadrobafera za KRFB",

View File

@@ -1253,7 +1253,7 @@ Comment[nl]=Ontving een onverwachte verbinding, afgebroken
Comment[nn]=Fekk ei uventa tilkopling, så avbryt no
Comment[pl]=Otrzymano niespodziewane połączenie. Przerwane.
Comment[pt]=Foi recebida uma ligação inesperada, pelo que foi interrompida
Comment[pt_BR]=Conexão recebida inesperadamente; cancelar
Comment[pt_BR]=Conexão recebida inesperadamente; abortar
Comment[ro]=Conexiune neașteptată recepționată, abandonare
Comment[ru]=Получено неожиданное соединение. Отключение
Comment[si]=බලාපොරොත්තු රහිත සබඳතාවක් ලැබිනි, පිටවෙමින්

View File

@@ -25,7 +25,6 @@
#include <KDBusService>
#include <KLocalizedString>
#include <KMessageBox>
#include <KWindowSystem>
#include <QDebug>
#include <QPixmap>
@@ -40,6 +39,7 @@
static const char description[] = I18N_NOOP("VNC-compatible server to share "
"desktops");
static bool checkX11Capabilities()
{
int bp1, bp2, majorv, minorv;
@@ -57,6 +57,7 @@ static bool checkX11Capabilities()
return true;
}
static void checkOldX11PluginConfig() {
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("x11")) {
qDebug() << "Detected deprecated configuration: preferredFrameBufferPlugin = x11";
@@ -70,21 +71,6 @@ static void checkOldX11PluginConfig() {
}
}
static void checkWaylandPluginConfig()
{
if (KrfbConfig::preferredFrameBufferPlugin() != QStringLiteral("pw")) {
qWarning() << "Wayland: Detected invalid configuration: "
"preferredFrameBufferPlugin is not pipewire: "
<< KrfbConfig::preferredFrameBufferPlugin();
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(
QStringLiteral("preferredFrameBufferPlugin"));
if (config_item) {
config_item->setProperty(QStringLiteral("pw"));
KrfbConfig::self()->save();
qDebug() << "Wayland: Fixed preferredFrameBufferPlugin to \"pw\".";
}
}
}
int main(int argc, char *argv[])
{
@@ -135,24 +121,13 @@ int main(int argc, char *argv[])
app.setQuitOnLastWindowClosed(false);
if (KWindowSystem::isPlatformX11()) {
if (!checkX11Capabilities()) {
return 1;
}
// upgrade the configuration
checkOldX11PluginConfig();
} else if (KWindowSystem::isPlatformWayland()) {
// check that default plugin in Wayland is PipeWire
checkWaylandPluginConfig();
} else {
KMessageBox::error(nullptr,
i18n("Desktop Sharing is not running under an X11 Server or Wayland.\n"
"Other display servers are currently not supported."),
i18n("Desktop Sharing Error"));
if (!checkX11Capabilities()) {
return 1;
}
// upgrade the configuration
checkOldX11PluginConfig();
//init the core
InvitationsRfbServer::init();

View File

@@ -34,7 +34,6 @@
#include <QVector>
#include <QSet>
#include <QNetworkInterface>
#include <QHostInfo>
class TCP: public QWidget, public Ui::TCP
@@ -58,7 +57,7 @@ public:
vboxLayout->addWidget(walletWarning);
// show warning when "noWallet" checkbox is checked
QObject::connect(kcfg_noWallet, &QCheckBox::toggled, this, [this] (bool checked) {
QObject::connect(kcfg_noWallet, &QCheckBox::toggled, [this](bool checked){
walletWarning->setVisible(checked);
});
}
@@ -142,14 +141,10 @@ MainWindow::MainWindow(QWidget *parent)
continue;
if(interface.flags() & QNetworkInterface::IsRunning &&
!interface.addressEntries().isEmpty()) {
const QString hostName = QHostInfo::localHostName();
const QString ipAddress = interface.addressEntries().constFirst().ip().toString();
const QString addressLabelText = hostName.isEmpty()
? QStringLiteral("%1 : %2").arg(ipAddress).arg(port)
: QStringLiteral("%1 (%2) : %3").arg(hostName, ipAddress).arg(port);
m_ui.addressDisplayLabel->setText(addressLabelText);
}
!interface.addressEntries().isEmpty())
m_ui.addressDisplayLabel->setText(QStringLiteral("%1 : %2")
.arg(interface.addressEntries().first().ip().toString())
.arg(port));
}
//Figure out the password
@@ -261,7 +256,7 @@ void MainWindow::showConfiguration()
dialog->addPage(new Security, i18n("Security"), QStringLiteral("security-high"));
dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), QStringLiteral("video-display"));
dialog->show();
connect(dialog, &KConfigDialog::settingsChanged, this, [this] () {
connect(dialog, &KConfigDialog::settingsChanged, [this] () {
// check if framebuffer plugin config has changed
if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) {
KMessageBox::information(this, i18n("To apply framebuffer plugin setting, "

View File

@@ -12,8 +12,6 @@
<name xml:lang="el">Krfb</name>
<name xml:lang="en-GB">Krfb</name>
<name xml:lang="es">Krfb</name>
<name xml:lang="et">Krfb</name>
<name xml:lang="eu">Krfb</name>
<name xml:lang="fi">Krfb</name>
<name xml:lang="fr">Krfb</name>
<name xml:lang="gl">Krfb</name>
@@ -47,8 +45,6 @@
<summary xml:lang="el">Κοινή χρήση επιφάνειας εργασίας</summary>
<summary xml:lang="en-GB">Desktop sharing</summary>
<summary xml:lang="es">Compartir el escritorio</summary>
<summary xml:lang="et">Töölaua jagamine</summary>
<summary xml:lang="eu">Mahaigaina partekatzea</summary>
<summary xml:lang="fi">Työpöydän jako</summary>
<summary xml:lang="fr">Partage de bureau</summary>
<summary xml:lang="gl">Compartición do escritorio</summary>
@@ -82,11 +78,9 @@
<p xml:lang="el">Η κοινή χρήση επιφάνειας εργασίας Krfb είναι μια εφαρμογή εξυπηρετητή που σας επιτρέπει να μοιράζεστε την τρέχουσα συνεδρία σας με έναν χρήστη σε άλλο μηχάνημα, ο οποίος μπορεί να χρησιμοποιεί έναν πελάτη VNC για να παρακολουθεί ή και να ελέγχει την επιφάνεια εργασίας σας.</p>
<p xml:lang="en-GB">Krfb Desktop Sharing is a server application that allows you to share your current session with a user on another machine, who can use a VNC client to view or even control the desktop.</p>
<p xml:lang="es">Krfb para compartir el escritorio es una aplicación de servidor que le permite compartir su sesión actual con un usuario de otra máquina, que puede usar un cliente VNC para ver e incluso controlar su escritorio.</p>
<p xml:lang="et">Krfb töölaua jagamine on serverirakendus, mis võimaldab jagada aktiivset seanssi mõne teise masina taga istuva kasutajaga, kes saab VNC kliendi kaudu töölauda näha või isegi juhtida.</p>
<p xml:lang="eu">Krfb Mahaigaina Partekatzea zerbitzari aplikazio bat da zure uneko saioa beste makina batean dagoen erabiltzaile batekin partekatzen uzten dizuna. Beste makinan VNC bezeroa erabil dezake zure mahaigaina ikusi edo baita kontrolatzeko ere.</p>
<p xml:lang="fi">Krfb-työpöytäjako on palvelinsovellus, jolla voit jakaa nykyisen istuntosi toisen koneen käyttäjälle, joka voi VNC-asiakkaalla nähdä tai jopa hallita työpöytääsi.</p>
<p xml:lang="fr">Le partage de bureau Krfb est une application de serveur qui vous permet de partager votre session courante avec un utilisateur sur une autre machine, qui peut utiliser un client VNC pour afficher et même contrôler le bureau.</p>
<p xml:lang="gl">Krfb é unha aplicación de servidor que permite compartir a sesión actual cun usuario que está noutro equipo, que pode usar un cliente VNC para ver ou mesmo controlar o escritorio.</p>
<p xml:lang="gl">Krfb é un aplicativo de servidor que permite compartir a sesión actual cun usuario que está noutro equipo, que pode usar un cliente VNC para ver ou mesmo controlar o escritorio.</p>
<p xml:lang="id">Krfb Desktop Sharing adalah aplikasi server yang memungkinkan kamu untuk berbagi sesimu saat ini dengan pengguna di mesin lain, yang bisa menggunakan klien VNC untuk menampilkan atau bahkan mengendalikan desktop.</p>
<p xml:lang="it">Condivisione del desktop Krfb è un'applicazione server che permette di condividere la sessione attuale con un utente su un'altra macchina, che potrà usare un client VNC per visualizzare ed anche controllare il desktop.</p>
<p xml:lang="ko">Krfb 데스크톱 공유는 현재 세션을 다른 머신의 사용자와 VNC를 통해서 공유하거나 원격 제어를 요청할 수 있는 서버 프로그램입니다.</p>
@@ -106,7 +100,7 @@
<p xml:lang="uk">Програма для спільного використання стільниці Krfb — це серверна програма, яка надає вам змогу розділити ваш поточний сеанс роботи з користувачем, який працює на іншому комп’ютері, так, щоб цей користувач зміг скористатися клієнтом VNC для перегляду або навіть керування вашою стільницею.</p>
<p xml:lang="x-test">xxKrfb Desktop Sharing is a server application that allows you to share your current session with a user on another machine, who can use a VNC client to view or even control the desktop.xx</p>
<p xml:lang="zh-CN">Krfb 桌面共享是一个可以让您与另一个在其他机器上的用户共享当前会话的服务器程序,他可以使用 VNC 客户端来查看甚至控制桌面。</p>
<p xml:lang="zh-TW">Krfb 桌面分享是款伺服器應用程式,它可以將您目前的桌面階段分享給一位於其他主機上的使用者,以讓他能使用 VNC 戶端檢視、甚至控制您的桌面。</p>
<p xml:lang="zh-TW">Krfb 桌面分享是款伺服器應用程式,它可以將您目前的桌面階段分享給一位於其他主機上的使用者,以讓他能使用 VNC 戶端檢視、甚至控制您的桌面。</p>
</description>
<url type="homepage">https://userbase.kde.org/Krfb</url>
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?format=guided&amp;product=krfb</url>
@@ -120,11 +114,8 @@
<caption xml:lang="cs">Sdílím pracovní plochu pomocí Krfb</caption>
<caption xml:lang="da">Deler skrivebord med Krfb</caption>
<caption xml:lang="de">Freigabe der Arbeitsfläche mit Krfb</caption>
<caption xml:lang="el">Κοινή χρήση επιφάνειας εργασίας με το Krfb</caption>
<caption xml:lang="en-GB">Sharing desktop with Krfb</caption>
<caption xml:lang="es">Compartiendo el escritorio con Krfb</caption>
<caption xml:lang="et">Töölaua jagamine Krfb abil</caption>
<caption xml:lang="eu">Mahaigaina Krfb-ren bidez partekatzea</caption>
<caption xml:lang="fi">Työpöydän jakaminen Krfb:llä</caption>
<caption xml:lang="fr">Partage de bureau grâce à Krfb</caption>
<caption xml:lang="gl">Compartindo o escritorio con Krfb</caption>
@@ -136,8 +127,6 @@
<caption xml:lang="pt">Partilha do ecrã com o Krfb</caption>
<caption xml:lang="pt-BR">Compartilhando a área de trabalho com o Krfb</caption>
<caption xml:lang="ru">Общий доступ к рабочему столу с использованием Krfb</caption>
<caption xml:lang="sk">Zdieľanie pracovnej plochy s Krfb</caption>
<caption xml:lang="sl">Deljenje namizij s Krfb</caption>
<caption xml:lang="sv">Dela skrivbord med Krfb</caption>
<caption xml:lang="uk">Спільне використання стільниці за допомогою Krfb</caption>
<caption xml:lang="x-test">xxSharing desktop with Krfbxx</caption>
@@ -150,10 +139,4 @@
<binary>krfb</binary>
</provides>
<project_group>KDE</project_group>
<releases>
<release version="20.04.3" date="2020-07-09"/>
<release version="20.04.2" date="2020-06-11"/>
<release version="20.04.1" date="2020-05-14"/>
<release version="20.04.0" date="2020-04-23"/>
</releases>
</component>

View File

@@ -215,6 +215,5 @@ Comment[x-test]=xxDesktop Sharingxx
Comment[zh_CN]=桌面共享
Comment[zh_HK]=桌面分享
Comment[zh_TW]=桌面分享
Categories=Qt;KDE;Network;RemoteAccess;
Categories=Qt;KDE;System;Network;RemoteAccess;
X-DBUS-ServiceName=org.kde.krfb
X-KDE-Wayland-Interfaces=org_kde_kwin_fake_input,org_kde_kwin_remote_access_manager

View File

@@ -21,7 +21,7 @@
#include "connectiondialog.h"
#include "krfbconfig.h"
#include "sockethelpers.h"
#include "eventsmanager.h"
#include "events.h"
#include <QSocketNotifier>
#include <QDebug>
#include <poll.h>
@@ -37,7 +37,6 @@ struct RfbClient::Private
bool controlEnabled;
rfbClientPtr client;
QSocketNotifier *notifier;
QSharedPointer<EventHandler> eventHandler;
QString remoteAddressString;
};
@@ -50,8 +49,6 @@ RfbClient::RfbClient(rfbClientPtr client, QObject* parent)
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
d->notifier->setEnabled(false);
connect(d->notifier, &QSocketNotifier::activated, this, &RfbClient::onSocketActivated);
d->eventHandler = EventsManager::instance()->eventHandler();
}
RfbClient::~RfbClient()
@@ -113,14 +110,14 @@ rfbClientPtr RfbClient::getRfbClientPtr()
void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym)
{
if (d->controlEnabled) {
d->eventHandler->handleKeyboard(down, keySym);
EventHandler::handleKeyboard(down, keySym);
}
}
void RfbClient::handleMouseEvent(int buttonMask, int x, int y)
{
if (d->controlEnabled) {
d->eventHandler->handlePointer(buttonMask, x, y);
EventHandler::handlePointer(buttonMask, x, y);
}
}
@@ -217,11 +214,11 @@ bool PendingRfbClient::vncAuthCheckPassword(const QByteArray& password, const QB
return true;
}
char passwd[MAXPWLEN+1]; // +1 to make sure there's a nullptr at the end
char passwd[MAXPWLEN];
unsigned char challenge[CHALLENGESIZE];
memcpy(challenge, m_rfbClient->authChallenge, CHALLENGESIZE);
memset(passwd, 0, sizeof(passwd));
bzero(passwd, MAXPWLEN);
if (!password.isEmpty()) {
strncpy(passwd, password.constData(),

View File

@@ -24,7 +24,6 @@
#include <QClipboard>
#include <QPointer>
#include <QDebug>
#include <QX11Info>
struct RfbServer::Private
{
@@ -109,7 +108,7 @@ bool RfbServer::start()
}
if (listeningAddress() != "0.0.0.0") {
strncpy(d->screen->thisHost, listeningAddress().constData(), 254);
strncpy(d->screen->thisHost, listeningAddress().data(), 254);
}
if (listeningPort() == 0) {
@@ -144,11 +143,8 @@ bool RfbServer::start()
d->ipv6notifier = new QSocketNotifier(d->screen->listen6Sock, QSocketNotifier::Read, this);
connect(d->ipv6notifier, &QSocketNotifier::activated, this, &RfbServer::onListenSocketActivated);
}
if (QX11Info::isPlatformX11()) {
connect(QApplication::clipboard(), &QClipboard::dataChanged,
this, &RfbServer::krfbSendServerCutText);
}
connect(QApplication::clipboard(), &QClipboard::dataChanged,
this, &RfbServer::krfbSendServerCutText);
return true;
}
@@ -166,17 +162,6 @@ void RfbServer::stop()
}
}
void RfbServer::updateFrameBuffer(char *fb, int width, int height, int depth)
{
int bpp = depth >> 3;
if (bpp != 1 && bpp != 2 && bpp != 4) {
bpp = 4;
}
rfbNewFramebuffer(d->screen, fb, width, height, 8, 3, bpp);
}
void RfbServer::updateScreen(const QList<QRect> & modifiedTiles)
{
if (d->screen) {

View File

@@ -43,7 +43,6 @@ public Q_SLOTS:
virtual bool start();
virtual void stop();
void updateFrameBuffer(char *fb, int width, int height, int depth);
void updateScreen(const QList<QRect> & modifiedTiles);
void updateCursorPosition(const QPoint & position);

View File

@@ -90,6 +90,7 @@ RfbServerManager* RfbServerManager::instance()
return &s_instance->server;
}
struct RfbServerManager::Private
{
QSharedPointer<FrameBuffer> fb;
@@ -112,11 +113,6 @@ RfbServerManager::~RfbServerManager()
delete d;
}
QSharedPointer<FrameBuffer> RfbServerManager::framebuffer() const
{
return d->fb;
}
void RfbServerManager::init()
{
//qDebug();
@@ -127,18 +123,10 @@ void RfbServerManager::init()
d->desktopName = QStringLiteral("%1@%2 (shared desktop)") //FIXME check if we can use utf8
.arg(KUser().loginName(),QHostInfo::localHostName()).toLatin1();
connect(d->fb.data(), &FrameBuffer::frameBufferChanged, this, &RfbServerManager::updateFrameBuffer);
connect(&d->rfbUpdateTimer, &QTimer::timeout, this, &RfbServerManager::updateScreens);
connect(qApp, &QApplication::aboutToQuit, this, &RfbServerManager::cleanup);
}
void RfbServerManager::updateFrameBuffer()
{
Q_FOREACH(RfbServer *server, d->servers) {
server->updateFrameBuffer(d->fb->data(), d->fb->width(), d->fb->height(), d->fb->depth());
}
}
void RfbServerManager::updateScreens()
{
QList<QRect> rects = d->fb->modifiedTiles();
@@ -206,6 +194,7 @@ rfbScreenInfoPtr RfbServerManager::newScreen()
screen->paddedWidthInBytes = d->fb->paddedWidth();
d->fb->getServerFormat(screen->serverFormat);
screen->frameBuffer = d->fb->data();
screen->desktopName = d->desktopName.constData();
screen->cursor = d->myCursor;
}

View File

@@ -21,7 +21,6 @@
#define RFBSERVERMANAGER_H
#include "rfb.h"
#include "framebuffer.h"
#include <QObject>
class RfbClient;
@@ -34,14 +33,12 @@ class RfbServerManager : public QObject
public:
static RfbServerManager *instance();
QSharedPointer<FrameBuffer> framebuffer() const;
Q_SIGNALS:
void clientConnected(RfbClient *cc);
void clientDisconnected(RfbClient *cc);
private Q_SLOTS:
void init();
void updateFrameBuffer();
void updateScreens();
void cleanup();

View File

@@ -18,8 +18,6 @@
#ifndef TRAYICON_H
#define TRAYICON_H
#include <QHash>
#include <KStatusNotifierItem>
class RfbClient;