mirror of
https://github.com/KDE/krfb
synced 2026-07-01 15:51:18 -07:00
Compare commits
5 Commits
Applicatio
...
gbm-vnc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73107409ee | ||
|
|
09f360ded6 | ||
|
|
d517bf8573 | ||
|
|
469782625a | ||
|
|
056b9a1ab6 |
@@ -6,7 +6,7 @@ include(FeatureSummary)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core DBus Widgets X11Extras)
|
||||
|
||||
find_package(ECM 1.7.0 NO_MODULE REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
@@ -29,6 +29,39 @@ find_package(KF5 REQUIRED COMPONENTS
|
||||
XmlGui
|
||||
)
|
||||
|
||||
find_package(KF5Wayland CONFIG)
|
||||
set_package_properties(KF5Wayland PROPERTIES DESCRIPTION "KDE Frameworks Wayland integration package"
|
||||
URL "https://github.com/KDE/kwayland"
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "Required for wayland integration with KWin server"
|
||||
)
|
||||
|
||||
find_package(epoxy)
|
||||
set_package_properties(epoxy PROPERTIES DESCRIPTION "libepoxy"
|
||||
URL "http://github.com/anholt/libepoxy"
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "OpenGL dispatch library for GBM backend"
|
||||
)
|
||||
|
||||
find_package(Libdrm)
|
||||
set_package_properties(Libdrm PROPERTIES DESCRIPTION "Libdrm"
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "Required for GBM access to compositor buffers on Wayland"
|
||||
)
|
||||
|
||||
set(HAVE_DRM FALSE)
|
||||
if(KF5Wayland_FOUND AND Libdrm_FOUND AND epoxy_FOUND)
|
||||
set(HAVE_DRM TRUE)
|
||||
endif()
|
||||
|
||||
find_package(gbm)
|
||||
set_package_properties(gbm PROPERTIES TYPE OPTIONAL PURPOSE "Required for egl ouput of drm backend.")
|
||||
set(HAVE_GBM FALSE)
|
||||
if(HAVE_DRM AND gbm_FOUND)
|
||||
set(HAVE_GBM TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
if(WIN32)
|
||||
@@ -70,6 +103,7 @@ endif(Q_WS_X11)
|
||||
|
||||
add_subdirectory(krfb)
|
||||
add_subdirectory(framebuffers)
|
||||
add_subdirectory(events)
|
||||
add_subdirectory(doc)
|
||||
|
||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
126
cmake/modules/FindLibdrm.cmake
Normal file
126
cmake/modules/FindLibdrm.cmake
Normal file
@@ -0,0 +1,126 @@
|
||||
#.rst:
|
||||
# FindLibdrm
|
||||
# -------
|
||||
#
|
||||
# Try to find libdrm on a Unix system.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``Libdrm_FOUND``
|
||||
# True if (the requested version of) libdrm is available
|
||||
# ``Libdrm_VERSION``
|
||||
# The version of libdrm
|
||||
# ``Libdrm_LIBRARIES``
|
||||
# This can be passed to target_link_libraries() instead of the ``Libdrm::Libdrm``
|
||||
# target
|
||||
# ``Libdrm_INCLUDE_DIRS``
|
||||
# This should be passed to target_include_directories() if the target is not
|
||||
# used for linking
|
||||
# ``Libdrm_DEFINITIONS``
|
||||
# This should be passed to target_compile_options() if the target is not
|
||||
# used for linking
|
||||
#
|
||||
# If ``Libdrm_FOUND`` is TRUE, it will also define the following imported target:
|
||||
#
|
||||
# ``Libdrm::Libdrm``
|
||||
# The libdrm 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>
|
||||
#
|
||||
# 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.
|
||||
#=============================================================================
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
message(FATAL_ERROR "CMake 2.8.12 is required by FindLibdrm.cmake")
|
||||
endif()
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibdrm.cmake")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_Libdrm QUIET libdrm)
|
||||
|
||||
set(Libdrm_DEFINITIONS ${PKG_Libdrm_CFLAGS_OTHER})
|
||||
set(Libdrm_VERSION ${PKG_Libdrm_VERSION})
|
||||
|
||||
find_path(Libdrm_INCLUDE_DIR
|
||||
NAMES
|
||||
xf86drm.h
|
||||
HINTS
|
||||
${PKG_Libdrm_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(Libdrm_LIBRARY
|
||||
NAMES
|
||||
drm
|
||||
HINTS
|
||||
${PKG_Libdrm_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libdrm
|
||||
FOUND_VAR
|
||||
Libdrm_FOUND
|
||||
REQUIRED_VARS
|
||||
Libdrm_LIBRARY
|
||||
Libdrm_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
Libdrm_VERSION
|
||||
)
|
||||
|
||||
if(Libdrm_FOUND AND NOT TARGET Libdrm::Libdrm)
|
||||
add_library(Libdrm::Libdrm UNKNOWN IMPORTED)
|
||||
set_target_properties(Libdrm::Libdrm PROPERTIES
|
||||
IMPORTED_LOCATION "${Libdrm_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Libdrm_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}/libdrm"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Libdrm_LIBRARY Libdrm_INCLUDE_DIR)
|
||||
|
||||
# compatibility variables
|
||||
set(Libdrm_LIBRARIES ${Libdrm_LIBRARY})
|
||||
set(Libdrm_INCLUDE_DIRS ${Libdrm_INCLUDE_DIR})
|
||||
set(Libdrm_VERSION_STRING ${Libdrm_VERSION})
|
||||
|
||||
else()
|
||||
message(STATUS "FindLibdrm.cmake cannot find libdrm on Windows systems.")
|
||||
set(Libdrm_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(Libdrm PROPERTIES
|
||||
URL "https://wiki.freedesktop.org/dri/"
|
||||
DESCRIPTION "Userspace interface to kernel DRM services."
|
||||
)
|
||||
56
cmake/modules/Findepoxy.cmake
Normal file
56
cmake/modules/Findepoxy.cmake
Normal file
@@ -0,0 +1,56 @@
|
||||
# - Try to find libepoxy
|
||||
# Once done this will define
|
||||
#
|
||||
# epoxy_FOUND - System has libepoxy
|
||||
# epoxy_LIBRARY - The libepoxy library
|
||||
# epoxy_INCLUDE_DIR - The libepoxy include dir
|
||||
# epoxy_DEFINITIONS - Compiler switches required for using libepoxy
|
||||
# epoxy_HAS_GLX - Whether GLX support is available
|
||||
|
||||
# Copyright (c) 2014 Fredrik Höglund <fredrik@kde.org>
|
||||
#
|
||||
# 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 above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_epoxy QUIET epoxy)
|
||||
|
||||
set(epoxy_DEFINITIONS ${PKG_epoxy_CFLAGS})
|
||||
|
||||
find_path(epoxy_INCLUDE_DIR NAMES epoxy/gl.h HINTS ${PKG_epoxy_INCLUDEDIR} ${PKG_epoxy_INCLUDE_DIRS})
|
||||
find_library(epoxy_LIBRARY NAMES epoxy HINTS ${PKG_epoxy_LIBDIR} ${PKG_epoxy_LIBRARY_DIRS})
|
||||
find_file(epoxy_GLX_HEADER NAMES epoxy/glx.h HINTS ${epoxy_INCLUDE_DIR})
|
||||
|
||||
if (epoxy_GLX_HEADER STREQUAL "epoxy_GLX_HEADER-NOTFOUND")
|
||||
set(epoxy_HAS_GLX FALSE CACHE BOOL "whether glx is available")
|
||||
else ()
|
||||
set(epoxy_HAS_GLX TRUE CACHE BOOL "whether glx is available")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(epoxy DEFAULT_MSG epoxy_LIBRARY epoxy_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(epoxy_INCLUDE_DIR epoxy_LIBRARY epoxy_HAS_GLX)
|
||||
endif()
|
||||
125
cmake/modules/Findgbm.cmake
Normal file
125
cmake/modules/Findgbm.cmake
Normal file
@@ -0,0 +1,125 @@
|
||||
#.rst:
|
||||
# Findgbm
|
||||
# -------
|
||||
#
|
||||
# Try to find gbm on a Unix system.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``gbm_FOUND``
|
||||
# True if (the requested version of) gbm is available
|
||||
# ``gbm_VERSION``
|
||||
# The version of gbm
|
||||
# ``gbm_LIBRARIES``
|
||||
# This can be passed to target_link_libraries() instead of the ``gbm::gbm``
|
||||
# target
|
||||
# ``gbm_INCLUDE_DIRS``
|
||||
# This should be passed to target_include_directories() if the target is not
|
||||
# used for linking
|
||||
# ``gbm_DEFINITIONS``
|
||||
# This should be passed to target_compile_options() if the target is not
|
||||
# used for linking
|
||||
#
|
||||
# If ``gbm_FOUND`` is TRUE, it will also define the following imported target:
|
||||
#
|
||||
# ``gbm::gbm``
|
||||
# The gbm 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>
|
||||
#
|
||||
# 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.
|
||||
#=============================================================================
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
message(FATAL_ERROR "CMake 2.8.12 is required by Findgbm.cmake")
|
||||
endif()
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Findgbm.cmake")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_gbm QUIET gbm)
|
||||
|
||||
set(gbm_DEFINITIONS ${PKG_gbm_CFLAGS_OTHER})
|
||||
set(gbm_VERSION ${PKG_gbm_VERSION})
|
||||
|
||||
find_path(gbm_INCLUDE_DIR
|
||||
NAMES
|
||||
gbm.h
|
||||
HINTS
|
||||
${PKG_gbm_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(gbm_LIBRARY
|
||||
NAMES
|
||||
gbm
|
||||
HINTS
|
||||
${PKG_gbm_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gbm
|
||||
FOUND_VAR
|
||||
gbm_FOUND
|
||||
REQUIRED_VARS
|
||||
gbm_LIBRARY
|
||||
gbm_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
gbm_VERSION
|
||||
)
|
||||
|
||||
if(gbm_FOUND AND NOT TARGET gbm::gbm)
|
||||
add_library(gbm::gbm UNKNOWN IMPORTED)
|
||||
set_target_properties(gbm::gbm PROPERTIES
|
||||
IMPORTED_LOCATION "${gbm_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${gbm_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${gbm_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(gbm_LIBRARY gbm_INCLUDE_DIR)
|
||||
|
||||
# compatibility variables
|
||||
set(gbm_LIBRARIES ${gbm_LIBRARY})
|
||||
set(gbm_INCLUDE_DIRS ${gbm_INCLUDE_DIR})
|
||||
set(gbm_VERSION_STRING ${gbm_VERSION})
|
||||
|
||||
else()
|
||||
message(STATUS "Findgbm.cmake cannot find gbm on Windows systems.")
|
||||
set(gbm_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(gbm PROPERTIES
|
||||
URL "http://www.mesa3d.org"
|
||||
DESCRIPTION "Mesa gbm library."
|
||||
)
|
||||
4
events/CMakeLists.txt
Normal file
4
events/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
add_subdirectory (x11)
|
||||
if(HAVE_GBM)
|
||||
add_subdirectory (fakeinput)
|
||||
endif()
|
||||
25
events/fakeinput/CMakeLists.txt
Normal file
25
events/fakeinput/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_events_gbm_SRCS
|
||||
fakeinputevents.cpp
|
||||
fakeinputeventsplugin.cpp
|
||||
)
|
||||
|
||||
add_library(krfb_events_fakeinput
|
||||
MODULE
|
||||
${krfb_events_gbm_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_events_fakeinput
|
||||
${GBM_XTest_LIB}
|
||||
KF5::CoreAddons
|
||||
KF5::WaylandClient
|
||||
KF5::I18n
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_events_fakeinput
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
118
events/fakeinput/fakeinputevents.cpp
Normal file
118
events/fakeinput/fakeinputevents.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
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 "fakeinputevents.h"
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGlobalStatic>
|
||||
// KDE
|
||||
#include <KLocalizedString>
|
||||
// KWayland
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/fakeinput.h>
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData() = default;
|
||||
|
||||
//mouse
|
||||
int buttonMask = 0;
|
||||
int oldX = 0;
|
||||
int oldY = 0;
|
||||
};
|
||||
|
||||
FakeInputEventHandler::FakeInputEventHandler()
|
||||
: EventHandler(), m_eventData(new EventData())
|
||||
{
|
||||
initWaylandConnection();
|
||||
}
|
||||
|
||||
void FakeInputEventHandler::initWaylandConnection()
|
||||
{
|
||||
using namespace KWayland::Client;
|
||||
ConnectionThread *conn = ConnectionThread::fromApplication(this);
|
||||
Registry *registry = new Registry(this);
|
||||
registry->create(conn);
|
||||
connect(registry, &Registry::fakeInputAnnounced, this,
|
||||
[this, registry] (qint32 name, qint32 version) {
|
||||
m_interface = registry->createFakeInput(name, version, this);
|
||||
}
|
||||
);
|
||||
registry->setup();
|
||||
}
|
||||
|
||||
void FakeInputEventHandler::authIfNeeded()
|
||||
{
|
||||
if (!m_authRequested) {
|
||||
m_interface->authenticate(i18n("Krfb"), i18n("Remote VNC input"));
|
||||
m_authRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FakeInputEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||
{
|
||||
if (!m_interface)
|
||||
return;
|
||||
|
||||
authIfNeeded();
|
||||
|
||||
// TODO: implement button handling
|
||||
// both in FakeInput interface and here
|
||||
Q_UNUSED(down)
|
||||
Q_UNUSED(keySym)
|
||||
}
|
||||
|
||||
void FakeInputEventHandler::handlePointer(int buttonMask, int x, int y)
|
||||
{
|
||||
if (!m_interface)
|
||||
return;
|
||||
|
||||
authIfNeeded();
|
||||
|
||||
int oldMask = m_eventData->buttonMask;
|
||||
int oldX = m_eventData->oldX;
|
||||
int oldY = m_eventData->oldY;
|
||||
|
||||
if (!(oldMask & 1) && buttonMask & 1) { // single left click
|
||||
m_interface->requestPointerButtonClick(Qt::LeftButton);
|
||||
}
|
||||
if (!(oldMask & 2) && buttonMask & 2) { // single right click
|
||||
m_interface->requestPointerButtonClick(Qt::RightButton);
|
||||
}
|
||||
if (!(oldMask & 4) && buttonMask & 4) { // single middle click
|
||||
m_interface->requestPointerButtonClick(Qt::MiddleButton);
|
||||
}
|
||||
if (!(oldMask & 8) && buttonMask & 8) { // wheel up
|
||||
m_interface->requestPointerAxis(Qt::Vertical, +10);
|
||||
}
|
||||
if (!(oldMask & 16) && buttonMask & 16) { // wheel down
|
||||
m_interface->requestPointerAxis(Qt::Vertical, -10);
|
||||
}
|
||||
|
||||
if (oldX != x || oldY != y) {
|
||||
m_interface->requestPointerMove(QSizeF(x - oldX, y - oldY));
|
||||
}
|
||||
|
||||
m_eventData->buttonMask = buttonMask;
|
||||
}
|
||||
54
events/fakeinput/fakeinputevents.h
Normal file
54
events/fakeinput/fakeinputevents.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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_GBMEVENTS_H
|
||||
#define EVENTS_GBMEVENTS_H
|
||||
|
||||
#include "../../krfb/events.h"
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class FakeInput;
|
||||
}
|
||||
}
|
||||
|
||||
class EventData;
|
||||
|
||||
class FakeInputEventHandler : public EventHandler
|
||||
{
|
||||
public:
|
||||
FakeInputEventHandler();
|
||||
virtual void handleKeyboard(bool down, rfbKeySym key);
|
||||
virtual void handlePointer(int buttonMask, int x, int y);
|
||||
private:
|
||||
void initWaylandConnection();
|
||||
void authIfNeeded();
|
||||
|
||||
QScopedPointer<EventData> m_eventData;
|
||||
KWayland::Client::FakeInput *m_interface = nullptr;
|
||||
bool m_authRequested = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
41
events/fakeinput/fakeinputeventsplugin.cpp
Normal file
41
events/fakeinput/fakeinputeventsplugin.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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 "fakeinputeventsplugin.h"
|
||||
|
||||
#include "fakeinputevents.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(FakeInputEventsPluginFactory, "krfb_events_fakeinput.json",
|
||||
registerPlugin<FakeInputEventsPlugin>();)
|
||||
|
||||
FakeInputEventsPlugin::FakeInputEventsPlugin(QObject *parent, const QVariantList &args)
|
||||
: EventsPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
EventHandler *FakeInputEventsPlugin::eventHandler()
|
||||
{
|
||||
// works only under Wayland
|
||||
return new FakeInputEventHandler();
|
||||
}
|
||||
|
||||
#include "fakeinputeventsplugin.moc"
|
||||
45
events/fakeinput/fakeinputeventsplugin.h
Normal file
45
events/fakeinput/fakeinputeventsplugin.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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_GBM_GBMEVENTSPLUGIN_H
|
||||
#define KRFB_EVENTS_GBM_GBMEVENTSPLUGIN_H
|
||||
|
||||
#include "eventsplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class EventHandler;
|
||||
|
||||
class FakeInputEventsPlugin : public EventsPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FakeInputEventsPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~FakeInputEventsPlugin() = default;
|
||||
|
||||
EventHandler *eventHandler() override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FakeInputEventsPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
17
events/fakeinput/krfb_events_fakeinput.desktop
Normal file
17
events/fakeinput/krfb_events_fakeinput.desktop
Normal file
@@ -0,0 +1,17 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=KWin FakeInput based event handler for KRfb
|
||||
Comment[ru]=Обработчик событий для KRfb на базе интерфейса FakeInput KWin
|
||||
Comment[x-test]=KWin FakeInput based event handler for KRfbxx
|
||||
Name=KWin FakeInput based event handler for KRfb
|
||||
Name[ru]=Обработчик событий для KRfb на базе интерфейса FakeInput KWin
|
||||
Name[x-test]=xxKWin FakeInput based event handler for KRfbxx
|
||||
Type=Service
|
||||
ServiceTypes=krfb/events
|
||||
|
||||
X-KDE-Library=krfb_events_fakeinput
|
||||
X-KDE-PluginInfo-Name=fakeinput
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://www.kde.org
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
17
events/fakeinput/krfb_events_fakeinput.json
Normal file
17
events/fakeinput/krfb_events_fakeinput.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "KWin FakeInput based event handler for KRfb",
|
||||
"Description[x-test]": "xxKWin FakeInput based event handler for KRfbxx",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "fakeinput",
|
||||
"License": "GPL",
|
||||
"Name": "KWin FakeInput Event handler for KRfb",
|
||||
"Name[x-test]": "xxKWin FakeInput Event handler for KRfbxx",
|
||||
"ServiceTypes": [
|
||||
"krfb/events"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
23
events/x11/CMakeLists.txt
Normal file
23
events/x11/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
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
|
||||
)
|
||||
17
events/x11/krfb_events_x11.desktop
Normal file
17
events/x11/krfb_events_x11.desktop
Normal file
@@ -0,0 +1,17 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=X11 XFakeInput based event handler for KRfb
|
||||
Comment[ru]=Обработчик событий для KRfb на базе XFakeInput
|
||||
Comment[x-test]=xxX11 XFakeInput based event handler for KRfbxx
|
||||
Name=X11 XFakeInput based event handler for KRfb
|
||||
Name[ru]=Обработчик событий для KRfb на базе XFakeInput
|
||||
Name[x-test]=xxX11 XFakeInput based event handler for KRfbxx
|
||||
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=http://www.kde.org
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
17
events/x11/krfb_events_x11.json
Normal file
17
events/x11/krfb_events_x11.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "X11 XFakeInput based event handler for KRfb",
|
||||
"Description[x-test]": "xxX11 XFakeInput based event handler for KRfbxx",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "x11",
|
||||
"License": "GPL",
|
||||
"Name": "X11 Event handler for KRfb",
|
||||
"Name[x-test]": "xxX11 Event handler for KRfbxx",
|
||||
"ServiceTypes": [
|
||||
"krfb/events"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
200
events/x11/x11events.cpp
Normal file
200
events/x11/x11events.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
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 "x11events.h"
|
||||
|
||||
#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 EventData::init()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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; }
|
||||
|
||||
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 X11EventHandler::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;
|
||||
}
|
||||
|
||||
#include "x11events.moc"
|
||||
|
||||
40
events/x11/x11events.h
Normal file
40
events/x11/x11events.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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)
|
||||
{
|
||||
};
|
||||
|
||||
virtual void handleKeyboard(bool down, rfbKeySym key);
|
||||
virtual void handlePointer(int buttonMask, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
45
events/x11/x11eventsplugin.cpp
Normal file
45
events/x11/x11eventsplugin.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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"
|
||||
|
||||
45
events/x11/x11eventsplugin.h
Normal file
45
events/x11/x11eventsplugin.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
add_subdirectory (qt)
|
||||
add_subdirectory (x11)
|
||||
|
||||
if(HAVE_GBM)
|
||||
add_subdirectory (gbm)
|
||||
endif()
|
||||
|
||||
29
framebuffers/gbm/CMakeLists.txt
Normal file
29
framebuffers/gbm/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_gbm_SRCS
|
||||
logging.cpp
|
||||
gbmframebuffer.cpp
|
||||
gbmframebufferplugin.cpp
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_gbm
|
||||
MODULE
|
||||
${krfb_framebuffer_gbm_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_framebuffer_gbm
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
KF5::CoreAddons
|
||||
KF5::WaylandClient
|
||||
${epoxy_LIBRARY}
|
||||
Libdrm::Libdrm
|
||||
gbm::gbm
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_gbm
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
330
framebuffers/gbm/gbmframebuffer.cpp
Normal file
330
framebuffers/gbm/gbmframebuffer.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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 "gbmframebuffer.h"
|
||||
#include "logging.h"
|
||||
#include "gbmframebuffer.moc"
|
||||
// KWayland
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/remote_access.h>
|
||||
// Qt
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
#include <QtCore/QThread>
|
||||
// system
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <libdrm/drm_mode.h>
|
||||
|
||||
static QString formatGLError(GLenum err)
|
||||
{
|
||||
switch(err) {
|
||||
case GL_NO_ERROR: return QStringLiteral("GL_NO_ERROR");
|
||||
case GL_INVALID_ENUM: return QStringLiteral("GL_INVALID_ENUM");
|
||||
case GL_INVALID_VALUE: return QStringLiteral("GL_INVALID_VALUE");
|
||||
case GL_INVALID_OPERATION: return QStringLiteral("GL_INVALID_OPERATION");
|
||||
case GL_STACK_OVERFLOW: return QStringLiteral("GL_STACK_OVERFLOW");
|
||||
case GL_STACK_UNDERFLOW: return QStringLiteral("GL_STACK_UNDERFLOW");
|
||||
case GL_OUT_OF_MEMORY: return QStringLiteral("GL_OUT_OF_MEMORY");
|
||||
default: return QLatin1String("0x") + QString::number(err, 16);
|
||||
}
|
||||
}
|
||||
|
||||
GbmFrameBuffer::GbmFrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent)
|
||||
{
|
||||
|
||||
// TODO: check out the case when new resolution was applied on KWin side
|
||||
// TODO: check possibility of multi-screen configuration
|
||||
QSize size = QApplication::screens().first()->size();
|
||||
m_img = new QImage(size, QImage::Format_ARGB32);
|
||||
fb = reinterpret_cast<char*>(m_img->bits());
|
||||
|
||||
// open DRM device
|
||||
setupDrm();
|
||||
|
||||
// get EGL client extensions
|
||||
initClientEglExtensions();
|
||||
|
||||
// initialize EGL context and display
|
||||
initEgl();
|
||||
|
||||
// get KWin connection
|
||||
initWaylandConnection();
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::setupDrm()
|
||||
{
|
||||
m_drmFd = open("/dev/dri/card0", O_RDWR);
|
||||
m_gbmDevice = gbm_create_device(m_drmFd);
|
||||
if(!m_gbmDevice) {
|
||||
qCCritical(KRFB_GBM) << "Cannot create GBM device:" << strerror(errno);
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// cloned from KWin AbstractEglBackend
|
||||
void GbmFrameBuffer::initClientEglExtensions()
|
||||
{
|
||||
if(!m_valid)
|
||||
return;
|
||||
|
||||
// Get the list of client extensions
|
||||
const char* clientExtensionsCString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||
const QByteArray clientExtensionsString = QByteArray::fromRawData(clientExtensionsCString, qstrlen(clientExtensionsCString));
|
||||
if (clientExtensionsString.isEmpty()) {
|
||||
// If eglQueryString() returned NULL, the implementation doesn't support
|
||||
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
|
||||
qCCritical(KRFB_GBM) << "No client extensions defined!" << formatGLError(eglGetError());
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
m_egl.extensions = clientExtensionsString.split(' ');
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::initEgl()
|
||||
{
|
||||
if(!m_valid)
|
||||
return;
|
||||
|
||||
// Use eglGetPlatformDisplayEXT() to get the display pointer
|
||||
// if the implementation supports it.
|
||||
if (!m_egl.extensions.contains(QByteArrayLiteral("EGL_EXT_platform_base")) ||
|
||||
!m_egl.extensions.contains(QByteArrayLiteral("EGL_MESA_platform_gbm"))) {
|
||||
qCCritical(KRFB_GBM) << "One of required EGL extensions is missing";
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, m_gbmDevice, nullptr);
|
||||
if (m_egl.display == EGL_NO_DISPLAY) {
|
||||
qCCritical(KRFB_GBM) << "Error during obtaining EGL display:" << formatGLError(eglGetError());
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
EGLint major, minor;
|
||||
if (eglInitialize(m_egl.display, &major, &minor) == EGL_FALSE) {
|
||||
qCCritical(KRFB_GBM) << "Error during eglInitialize:" << formatGLError(eglGetError());
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
|
||||
qCCritical(KRFB_GBM) << "bind OpenGL API failed";
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
qCDebug(KRFB_GBM) << "Egl Initialize succeeded";
|
||||
qCDebug(KRFB_GBM) << QString("EGL version: %1.%2").arg(major).arg(minor);
|
||||
|
||||
m_egl.context = eglCreateContext(m_egl.display, nullptr, EGL_NO_CONTEXT, nullptr);
|
||||
if(m_egl.context == EGL_NO_CONTEXT) {
|
||||
qCCritical(KRFB_GBM) << "Couldn't create EGL context:" << formatGLError(eglGetError());
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::initWaylandConnection()
|
||||
{
|
||||
if(!m_valid)
|
||||
return;
|
||||
|
||||
using namespace KWayland::Client;
|
||||
ConnectionThread *conn = ConnectionThread::fromApplication(this);
|
||||
if(!conn) { // trying to instantiate wayland not having a wayland platform?
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// what do we do if server dies?
|
||||
// since we use foreign connection, the whole application will be disconnected,
|
||||
// not only plugin, let's assume application will die anyway
|
||||
|
||||
Registry *registry = new Registry(this);
|
||||
registry->create(conn);
|
||||
connect(registry, &Registry::remoteAccessManagerAnnounced, this,
|
||||
[this, registry] (qint32 name, qint32 version) {
|
||||
m_interface = registry->createRemoteAccessManager(name, version, this);
|
||||
connect(m_interface, &RemoteAccessManager::bufferReady, this, &GbmFrameBuffer::obtainBuffer);
|
||||
}
|
||||
);
|
||||
registry->setup();
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::obtainBuffer(KWayland::Client::RemoteBuffer *rbuf)
|
||||
{
|
||||
using namespace KWayland::Client;
|
||||
connect(rbuf, &RemoteBuffer::paramsObtained, this,
|
||||
[this, rbuf] (qint32 fd, quint32 width, quint32 height, quint32 stride, quint32 format) {
|
||||
updateHandle(fd, width, height, stride, format);
|
||||
// deleteLater() is not working due to QTBUG-18434 (or similar)
|
||||
// TODO: try with Qt 5.8.0
|
||||
delete rbuf;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::updateHandle(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format)
|
||||
{
|
||||
qCDebug(KRFB_GBM) << QString("Incoming GBM fd %1, %2x%3, stride %4, fourcc 0x%5")
|
||||
.arg(gbmHandle).arg(width).arg(height).arg(stride).arg(QString::number(format, 16));
|
||||
|
||||
if(!gbm_device_is_format_supported(m_gbmDevice, format, GBM_BO_USE_SCANOUT)) {
|
||||
qCCritical(KRFB_GBM) << "GBM format is not supported by device!";
|
||||
return;
|
||||
}
|
||||
|
||||
if(this->width() != (int) width || this->height() != (int) height) {
|
||||
qCCritical(KRFB_GBM) << QString("Size of GBM buffer (%3x%4) is not equal to expected (%1x%2)!")
|
||||
.arg(this->width()).arg(this->height()).arg(width).arg(height);
|
||||
return;
|
||||
}
|
||||
|
||||
// import GBM buffer that was passed from KWin
|
||||
gbm_import_fd_data importInfo = {gbmHandle, width, height, stride, format};
|
||||
gbm_bo *imported = gbm_bo_import(m_gbmDevice, GBM_BO_IMPORT_FD, &importInfo, GBM_BO_USE_SCANOUT);
|
||||
if(!imported) {
|
||||
qCCritical(KRFB_GBM) << "Cannot import passed GBM fd:" << strerror(errno);
|
||||
return;
|
||||
}
|
||||
|
||||
// bind context to render thread
|
||||
eglMakeCurrent(m_egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, m_egl.context);
|
||||
|
||||
// create EGL image from imported BO
|
||||
EGLImageKHR image = eglCreateImageKHR(m_egl.display, NULL, EGL_NATIVE_PIXMAP_KHR, imported, NULL);
|
||||
if (image == EGL_NO_IMAGE_KHR) {
|
||||
qCCritical(KRFB_GBM) << "Error creating EGLImageKHR" << formatGLError(glGetError());
|
||||
return;
|
||||
}
|
||||
// create GL 2D texture for framebuffer
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||
|
||||
// bind framebuffer to copy pixels from
|
||||
GLuint framebuffer;
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||
const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
qCCritical(KRFB_GBM) << "glCheckFramebufferStatus failed:" << formatGLError(glGetError());
|
||||
glDeleteTextures(1, &texture);
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
eglDestroyImageKHR(m_egl.display, image);
|
||||
return;
|
||||
}
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_img->bits());
|
||||
tiles.append(m_img->rect());
|
||||
|
||||
// unbind all
|
||||
glDeleteTextures(1, &texture);
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
eglDestroyImageKHR(m_egl.display, image);
|
||||
|
||||
// from this point buffer object can be safely freed
|
||||
close(gbmHandle);
|
||||
}
|
||||
|
||||
GbmFrameBuffer::~GbmFrameBuffer()
|
||||
{
|
||||
fb = nullptr;
|
||||
|
||||
delete m_img;
|
||||
m_img = nullptr;
|
||||
|
||||
if(m_egl.context != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(m_egl.display, m_egl.context);
|
||||
}
|
||||
|
||||
if(m_gbmDevice) {
|
||||
gbm_device_destroy(m_gbmDevice);
|
||||
}
|
||||
|
||||
if(m_drmFd) {
|
||||
close(m_drmFd);
|
||||
}
|
||||
}
|
||||
|
||||
int GbmFrameBuffer::depth()
|
||||
{
|
||||
return m_img->depth();
|
||||
}
|
||||
|
||||
int GbmFrameBuffer::height()
|
||||
{
|
||||
return m_img->height();
|
||||
}
|
||||
|
||||
int GbmFrameBuffer::width()
|
||||
{
|
||||
return m_img->width();
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
format.trueColour = true;
|
||||
|
||||
format.bigEndian = false;
|
||||
|
||||
// GL images have different shift
|
||||
format.redShift = 0;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 16;
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::updateFrameBuffer()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
int GbmFrameBuffer::paddedWidth()
|
||||
{
|
||||
return m_img->bytesPerLine();
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::startMonitor()
|
||||
{
|
||||
// not needed - we get events as a signals from Wayland interface
|
||||
// no other updates are possible
|
||||
}
|
||||
|
||||
void GbmFrameBuffer::stopMonitor()
|
||||
{
|
||||
|
||||
}
|
||||
85
framebuffers/gbm/gbmframebuffer.h
Normal file
85
framebuffers/gbm/gbmframebuffer.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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_GBM_GBMFRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_GBM_GBMFRAMEBUFFER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
// Qt
|
||||
#include <QImage>
|
||||
// system
|
||||
#include <gbm.h>
|
||||
#include <epoxy/egl.h>
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class RemoteAccessManager;
|
||||
class RemoteBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@author Oleg Chernovskiy <adonai@xaker.ru>
|
||||
*/
|
||||
class GbmFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GbmFrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~GbmFrameBuffer();
|
||||
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
inline bool isValid() { return m_valid; };
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateFrameBuffer();
|
||||
|
||||
private:
|
||||
void initWaylandConnection();
|
||||
void setupDrm();
|
||||
void initClientEglExtensions();
|
||||
void initEgl();
|
||||
void obtainBuffer(KWayland::Client::RemoteBuffer *rbuf);
|
||||
void updateHandle(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format);
|
||||
|
||||
qint32 m_drmFd = 0; // for GBM buffer mmap
|
||||
gbm_device *m_gbmDevice = nullptr; // for passed GBM buffer retrieval
|
||||
struct {
|
||||
QList<QByteArray> extensions;
|
||||
EGLDisplay display = EGL_NO_DISPLAY;
|
||||
EGLContext context = EGL_NO_CONTEXT;
|
||||
} m_egl;
|
||||
|
||||
KWayland::Client::RemoteAccessManager *m_interface = nullptr;
|
||||
QImage *m_img;
|
||||
|
||||
bool m_valid = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
50
framebuffers/gbm/gbmframebufferplugin.cpp
Normal file
50
framebuffers/gbm/gbmframebufferplugin.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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 "gbmframebufferplugin.h"
|
||||
|
||||
#include "gbmframebuffer.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(GbmFrameBufferPluginFactory, "krfb_framebuffer_gbm.json",
|
||||
registerPlugin<GbmFrameBufferPlugin>();)
|
||||
|
||||
GbmFrameBufferPlugin::GbmFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
GbmFrameBufferPlugin::~GbmFrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *GbmFrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
auto p = new GbmFrameBuffer(id);
|
||||
if (!p->isValid()) {
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#include "gbmframebufferplugin.moc"
|
||||
|
||||
45
framebuffers/gbm/gbmframebufferplugin.h
Normal file
45
framebuffers/gbm/gbmframebufferplugin.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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_GBM_GBMFRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_GBM_GBMFRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class GbmFrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GbmFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~GbmFrameBufferPlugin();
|
||||
|
||||
FrameBuffer *frameBuffer(WId id) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(GbmFrameBufferPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
62
framebuffers/gbm/krfb_framebuffer_gbm.json
Normal file
62
framebuffers/gbm/krfb_framebuffer_gbm.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "GBM based Framebuffer for KRfb.",
|
||||
"Description[ca@valencia]": "«Framebuffer» basat en GBM per al KRfb.",
|
||||
"Description[ca]": "«Framebuffer» basat en GBM per al KRfb.",
|
||||
"Description[cs]": "Framebuffer založený na GBM pro KRfb.",
|
||||
"Description[de]": "GBM-basierter Framebuffer für KRfb",
|
||||
"Description[es]": "Framebuffer basado en GBM para KRfb.",
|
||||
"Description[fi]": "QT-perustainen Kehyspuskuri KRfb:lle",
|
||||
"Description[gl]": "Framebuffer baseado en GBM para KRfb.",
|
||||
"Description[it]": "Framebuffer basato su GBM per KRfb.",
|
||||
"Description[ko]": "KRfb용 GBM 기반 프레임버퍼입니다.",
|
||||
"Description[nl]": "Op GBM gebaseerd framebuffer voor KRfb.",
|
||||
"Description[pl]": "Bufor ramki na podstawie GBM dla KRfb.",
|
||||
"Description[pt]": "'Framebuffer' baseado no GBM para o KRfb.",
|
||||
"Description[pt_BR]": "Framebuffer baseado no GBM para o KRfb.",
|
||||
"Description[sk]": "Framebuffer založený na GBM pre KRfb.",
|
||||
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na GBM",
|
||||
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu GBM‑u",
|
||||
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu GBM‑u",
|
||||
"Description[sr]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sv]": "X11-rambuffert för Krfb.",
|
||||
"Description[uk]": "Заснований на GBM буфер кадрів для KRfb.",
|
||||
"Description[x-test]": "xxGBM based Framebuffer for KRfb.xx",
|
||||
"Description[zh_CN]": "KRfb 的基于 GBM 的帧缓冲。",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "gbm",
|
||||
"License": "GPL",
|
||||
"Name": "GBM Framebuffer for KRfb",
|
||||
"Name[ast]": "Framebuffer GBM pa KRfb",
|
||||
"Name[ca@valencia]": "«Framebuffer» GBM per al KRfb.",
|
||||
"Name[ca]": "«Framebuffer» GBM per al KRfb.",
|
||||
"Name[cs]": "GBM Framebuffer pro KRfb",
|
||||
"Name[de]": "GBM-Framebuffer für KRfb",
|
||||
"Name[es]": "Framebuffer de GBM para KRfb",
|
||||
"Name[fi]": "QT-kehyspuskuri KRfb:lle",
|
||||
"Name[gl]": "Framebuffer de GBM para KRfb",
|
||||
"Name[it]": "Framebuffer GBM per KRfb",
|
||||
"Name[ko]": "KRfb용 GBM 프레임버퍼",
|
||||
"Name[nl]": "GBM-framebuffer voor KRfb",
|
||||
"Name[pl]": "Bufor ramki GBM dla KRfb",
|
||||
"Name[pt]": "'Framebuffer' do GBM para o KRfb",
|
||||
"Name[pt_BR]": "Framebuffer do GBM para o KRfb",
|
||||
"Name[sk]": "GBM Framebuffer pre KRfb",
|
||||
"Name[sl]": "Slikovni medpomnilnik GBM za KRfb",
|
||||
"Name[sr@ijekavian]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sr@ijekavianlatin]": "GBM‑ov kadrobafer za KRFB",
|
||||
"Name[sr@latin]": "GBM‑ov kadrobafer za KRFB",
|
||||
"Name[sr]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sv]": "X11-rambuffert för Krfb",
|
||||
"Name[uk]": "Буфер кадрів на GBM для KRfb",
|
||||
"Name[x-test]": "xxGBM Framebuffer for KRfbxx",
|
||||
"Name[zh_CN]": "KRfb 的 GBM 帧缓冲",
|
||||
"ServiceTypes": [
|
||||
"krfb/framebuffer"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
21
framebuffers/gbm/logging.cpp
Normal file
21
framebuffers/gbm/logging.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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 "logging.h"
|
||||
Q_LOGGING_CATEGORY(KRFB_GBM, "krfb-gbm", QtCriticalMsg)
|
||||
26
framebuffers/gbm/logging.h
Normal file
26
framebuffers/gbm/logging.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2016 Oleg Chernovskiy <adonai@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_GBM_LOGGING
|
||||
#define KRFB_FRAMEBUFFER_GBM_LOGGING
|
||||
#include <QDebug>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(KRFB_GBM)
|
||||
#endif
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "qtframebuffer.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <QX11Info>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(QtFrameBufferPluginFactory, "krfb_framebuffer_qt.json",
|
||||
registerPlugin<QtFrameBufferPlugin>();)
|
||||
registerPlugin<QtFrameBufferPlugin>();)
|
||||
|
||||
QtFrameBufferPlugin::QtFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
@@ -38,6 +39,10 @@ QtFrameBufferPlugin::~QtFrameBufferPlugin()
|
||||
|
||||
FrameBuffer *QtFrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
// works only under X11
|
||||
if(!QX11Info::isPlatformX11())
|
||||
return nullptr;
|
||||
|
||||
return new QtFrameBuffer(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "x11framebuffer.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <QX11Info>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(X11FrameBufferPluginFactory, "krfb_framebuffer_x11.json",
|
||||
registerPlugin<X11FrameBufferPlugin>();)
|
||||
registerPlugin<X11FrameBufferPlugin>();)
|
||||
|
||||
X11FrameBufferPlugin::X11FrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
@@ -38,6 +39,10 @@ X11FrameBufferPlugin::~X11FrameBufferPlugin()
|
||||
|
||||
FrameBuffer *X11FrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
// works only under X11
|
||||
if(!QX11Info::isPlatformX11())
|
||||
return nullptr;
|
||||
|
||||
return new X11FrameBuffer(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ include(GenerateExportHeader)
|
||||
set (krfbprivate_SRCS
|
||||
framebuffer.cpp
|
||||
framebufferplugin.cpp
|
||||
events.cpp
|
||||
eventsplugin.cpp
|
||||
)
|
||||
|
||||
add_library (krfbprivate
|
||||
@@ -39,6 +41,7 @@ install (TARGETS krfbprivate
|
||||
|
||||
install (FILES
|
||||
krfb-framebuffer.desktop
|
||||
krfb-events.desktop
|
||||
DESTINATION ${SERVICETYPES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
@@ -48,8 +51,8 @@ install (FILES
|
||||
|
||||
set (krfb_SRCS
|
||||
connectiondialog.cpp
|
||||
events.cpp
|
||||
framebuffermanager.cpp
|
||||
eventsmanager.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
sockethelpers.cpp
|
||||
@@ -118,4 +121,4 @@ install(FILES org.kde.krfb.appdata.xml
|
||||
install (FILES krfb.notifyrc
|
||||
DESTINATION ${DATA_INSTALL_DIR}/krfb
|
||||
)
|
||||
|
||||
|
||||
|
||||
174
krfb/events.cpp
174
krfb/events.cpp
@@ -24,177 +24,9 @@
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#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
|
||||
EventHandler::EventHandler(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
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 EventData::init()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
#include "events.moc"
|
||||
|
||||
@@ -26,12 +26,18 @@
|
||||
#define EVENTS_H
|
||||
|
||||
#include "rfb.h"
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
class EventHandler
|
||||
#include <QObject>
|
||||
|
||||
class KRFBPRIVATE_EXPORT EventHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void handleKeyboard(bool down, rfbKeySym key);
|
||||
static void handlePointer(int buttonMask, int x, int y);
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
118
krfb/eventsmanager.cpp
Normal file
118
krfb/eventsmanager.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 <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();
|
||||
} 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)
|
||||
return eventHandler;
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
// No valid events plugin found.
|
||||
qDebug() << "No valid event handlers found. returning null.";
|
||||
return QSharedPointer<EventHandler>();
|
||||
}
|
||||
|
||||
|
||||
#include "eventsmanager.moc"
|
||||
|
||||
63
krfb/eventsmanager.h
Normal file
63
krfb/eventsmanager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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
|
||||
|
||||
35
krfb/eventsplugin.cpp
Normal file
35
krfb/eventsplugin.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#include "eventsplugin.moc"
|
||||
|
||||
44
krfb/eventsplugin.h
Normal file
44
krfb/eventsplugin.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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
|
||||
|
||||
@@ -71,25 +71,25 @@ void FrameBufferManager::loadPlugins()
|
||||
i.toBack();
|
||||
QSet<QString> unique;
|
||||
while (i.hasPrevious()) {
|
||||
KPluginMetaData data = i.previous();
|
||||
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();
|
||||
} else {
|
||||
qDebug() << "found plugin at " << data.fileName();
|
||||
}
|
||||
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(this);
|
||||
if (plugin) {
|
||||
m_plugins.insert(data.pluginId(), plugin);
|
||||
qDebug() << "Loaded plugin with name " << data.pluginId();
|
||||
} else {
|
||||
qDebug() << "unable to load pluign for " << data.fileName();
|
||||
}
|
||||
KPluginFactory *factory = KPluginLoader(data.fileName()).factory();
|
||||
|
||||
if (!factory) {
|
||||
qDebug() << "KPluginFactory could not load the plugin:" << data.fileName();
|
||||
} else {
|
||||
qDebug() << "found plugin at " << data.fileName();
|
||||
}
|
||||
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(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());
|
||||
}
|
||||
}
|
||||
|
||||
7
krfb/krfb-events.desktop
Normal file
7
krfb/krfb-events.desktop
Normal file
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=krfb/events
|
||||
|
||||
Comment=Event plugins for KRfb
|
||||
Comment[ru]=Модули обработки событий для Krfb
|
||||
Comment[x-test]=xxEvent plugins for KRfbxx
|
||||
7
krfb/krfb-events.json
Normal file
7
krfb/krfb-events.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Description": "Events plugins for KRfb",
|
||||
"Description[x-test]": "xxFrame Buffer plugins for KRfbxx"
|
||||
},
|
||||
"X-KDE-ServiceType": "krfb/events"
|
||||
}
|
||||
@@ -41,6 +41,9 @@ static const char description[] = I18N_NOOP("VNC-compatible server to share "
|
||||
|
||||
static bool checkX11Capabilities()
|
||||
{
|
||||
if(!QX11Info::isPlatformX11())
|
||||
return false;
|
||||
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
@@ -56,6 +59,15 @@ static bool checkX11Capabilities()
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool checkWaylandCapabilities()
|
||||
{
|
||||
if (!QGuiApplication::platformName().contains(QStringLiteral("wayland"), Qt::CaseInsensitive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
@@ -63,10 +75,10 @@ int main(int argc, char *argv[])
|
||||
KLocalizedString::setApplicationDomain("krfb");
|
||||
|
||||
KAboutData aboutData("krfb",
|
||||
i18n("Desktop Sharing"),
|
||||
KRFB_VERSION,
|
||||
i18n("Desktop Sharing"),
|
||||
KRFB_VERSION,
|
||||
i18n(description),
|
||||
KAboutLicense::GPL,
|
||||
KAboutLicense::GPL,
|
||||
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||
"(c) 2007, Alessandro Praduroux\n"
|
||||
"(c) 2001-2003, Tim Jansen\n"
|
||||
@@ -105,7 +117,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!checkX11Capabilities()) {
|
||||
bool supportsX11 = checkX11Capabilities();
|
||||
bool supportsWayland = checkWaylandCapabilities();
|
||||
|
||||
if (!supportsWayland && !supportsX11) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#include "connectiondialog.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "events.h"
|
||||
#include "eventsmanager.h"
|
||||
// Qt
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <QSharedPointer>
|
||||
#include <QDebug>
|
||||
// system
|
||||
#include <poll.h>
|
||||
#include <strings.h> //for bzero()
|
||||
|
||||
@@ -37,6 +40,7 @@ struct RfbClient::Private
|
||||
bool controlEnabled;
|
||||
rfbClientPtr client;
|
||||
QSocketNotifier *notifier;
|
||||
QSharedPointer<EventHandler> eventHandler;
|
||||
QString remoteAddressString;
|
||||
};
|
||||
|
||||
@@ -49,6 +53,8 @@ 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()
|
||||
@@ -110,14 +116,14 @@ rfbClientPtr RfbClient::getRfbClientPtr()
|
||||
void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym)
|
||||
{
|
||||
if (d->controlEnabled) {
|
||||
EventHandler::handleKeyboard(down, keySym);
|
||||
d->eventHandler->handleKeyboard(down, keySym);
|
||||
}
|
||||
}
|
||||
|
||||
void RfbClient::handleMouseEvent(int buttonMask, int x, int y)
|
||||
{
|
||||
if (d->controlEnabled) {
|
||||
EventHandler::handlePointer(buttonMask, x, y);
|
||||
d->eventHandler->handlePointer(buttonMask, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user