diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -10,14 +10,12 @@ add_subdirectory(battery) add_subdirectory(findmyphone) add_subdirectory(remotekeyboard) -if(WIN32) - add_subdirectory(mousepad_windows) -else() +add_subdirectory(mousepad) +if(NOT WIN32) add_subdirectory(runcommand) add_subdirectory(sendnotifications) add_subdirectory(pausemusic) add_subdirectory(mpriscontrol) - add_subdirectory(mousepad) add_subdirectory(screensaver-inhibit) add_subdirectory(sftp) endif() diff --git a/plugins/mousepad/CMakeLists.txt b/plugins/mousepad/CMakeLists.txt --- a/plugins/mousepad/CMakeLists.txt +++ b/plugins/mousepad/CMakeLists.txt @@ -1,32 +1,41 @@ -find_package(LibFakeKey) -set_package_properties(LibFakeKey PROPERTIES DESCRIPTION "fake key events" - URL "https://www.yoctoproject.org/tools-resources/projects/matchbox" - TYPE OPTIONAL - PURPOSE "Needed for the remote mousepad plugin" - ) - -if (LibFakeKey_FOUND) - find_package(XTest REQUIRED) - find_package(X11 REQUIRED) - find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) +if(NOT WIN32) + find_package(LibFakeKey) + set_package_properties(LibFakeKey PROPERTIES DESCRIPTION "fake key events" + URL "https://www.yoctoproject.org/tools-resources/projects/matchbox" + TYPE OPTIONAL + PURPOSE "Needed for the remote mousepad plugin" + ) + if (LibFakeKey_FOUND) + find_package(XTest REQUIRED) + find_package(X11 REQUIRED) + find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) + include_directories(${XTEST_INCLUDE_DIRS} ${X11_INCLUDE_DIR} ${LibFakeKey_INCLUDE_DIRS}) + endif() + + find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS Wayland) + endif() -find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS Wayland) + +set(HAVE_WINDOWS ${WIN32}) set(HAVE_X11 ${LibFakeKey_FOUND}) set(HAVE_WAYLAND ${KF5Wayland_FOUND}) configure_file(config-mousepad.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-mousepad.h ) -kdeconnect_add_plugin(kdeconnect_mousepad JSON kdeconnect_mousepad.json SOURCES mousepadplugin.cpp) +kdeconnect_add_plugin(kdeconnect_mousepad JSON kdeconnect_mousepad.json SOURCES mousepadplugin.cpp abstractremoteinput.cpp) +target_link_libraries(kdeconnect_mousepad kdeconnectcore Qt5::Gui KF5::I18n) + -if (HAVE_X11) - include_directories(${XTEST_INCLUDE_DIRS} ${X11_INCLUDE_DIR} ${LibFakeKey_INCLUDE_DIRS}) +if (HAVE_WINDOWS) + target_sources(kdeconnect_mousepad PUBLIC windowsremoteinput.cpp) endif() -target_link_libraries(kdeconnect_mousepad kdeconnectcore Qt5::Gui KF5::I18n) - if(HAVE_WAYLAND) + target_sources(kdeconnect_mousepad PUBLIC waylandremoteinput.cpp) target_link_libraries(kdeconnect_mousepad KF5::WaylandClient) endif() + if(HAVE_X11) + target_sources(kdeconnect_mousepad PUBLIC x11remoteinput.cpp) target_link_libraries(kdeconnect_mousepad Qt5::X11Extras ${X11_LIBRARIES} ${XTEST_LIBRARIES} ${LibFakeKey_LIBRARIES}) endif() diff --git a/plugins/mousepad_windows/mousepadplugin_windows.h b/plugins/mousepad/abstractremoteinput.h rename from plugins/mousepad_windows/mousepadplugin_windows.h rename to plugins/mousepad/abstractremoteinput.h --- a/plugins/mousepad_windows/mousepadplugin_windows.h +++ b/plugins/mousepad/abstractremoteinput.h @@ -1,5 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,25 +18,21 @@ * along with this program. If not, see . */ -#ifndef MOUSEPADPLUGIN_H -#define MOUSEPADPLUGIN_H +#ifndef ABSTRACTREMOTEINPUT_H +#define ABSTRACTREMOTEINPUT_H #include -#include -#include +#include -class MousepadPlugin - : public KdeConnectPlugin +class AbstractRemoteInput + : public QObject { Q_OBJECT - public: - explicit MousepadPlugin(QObject* parent, const QVariantList &args); - ~MousepadPlugin() override; + explicit AbstractRemoteInput(QObject* parent = nullptr); - bool receivePacket(const NetworkPacket& np) override; - void connected() override { } + virtual bool handlePacket(const NetworkPacket& np) = 0; }; #endif diff --git a/plugins/mousepad_windows/mousepadplugin_windows.h b/plugins/mousepad/abstractremoteinput.cpp copy from plugins/mousepad_windows/mousepadplugin_windows.h copy to plugins/mousepad/abstractremoteinput.cpp --- a/plugins/mousepad_windows/mousepadplugin_windows.h +++ b/plugins/mousepad/abstractremoteinput.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,25 +18,11 @@ * along with this program. If not, see . */ -#ifndef MOUSEPADPLUGIN_H -#define MOUSEPADPLUGIN_H -#include -#include +#include "abstractremoteinput.h" -#include - -class MousepadPlugin - : public KdeConnectPlugin +AbstractRemoteInput::AbstractRemoteInput(QObject* parent) + : QObject(parent) { - Q_OBJECT - -public: - explicit MousepadPlugin(QObject* parent, const QVariantList &args); - ~MousepadPlugin() override; - - bool receivePacket(const NetworkPacket& np) override; - void connected() override { } -}; -#endif +} diff --git a/plugins/mousepad/config-mousepad.h.cmake b/plugins/mousepad/config-mousepad.h.cmake --- a/plugins/mousepad/config-mousepad.h.cmake +++ b/plugins/mousepad/config-mousepad.h.cmake @@ -1,2 +1,3 @@ #cmakedefine01 HAVE_WAYLAND #cmakedefine01 HAVE_X11 +#cmakedefine01 HAVE_WINDOWS diff --git a/plugins/mousepad/mousepadplugin.h b/plugins/mousepad/mousepadplugin.h --- a/plugins/mousepad/mousepadplugin.h +++ b/plugins/mousepad/mousepadplugin.h @@ -1,5 +1,7 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora + * Copyright 2015 Martin Gräßlin + * Copyright 2014 Ahmed I. Khalil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -21,21 +23,10 @@ #ifndef MOUSEPADPLUGIN_H #define MOUSEPADPLUGIN_H -#include #include #include -struct FakeKey; - -#if HAVE_WAYLAND -namespace KWayland -{ -namespace Client -{ -class FakeInput; -} -} -#endif +#include "abstractremoteinput.h" class MousepadPlugin : public KdeConnectPlugin @@ -50,22 +41,8 @@ void connected() override { } private: -#if HAVE_X11 - bool handlePacketX11(const NetworkPacket& np); -#endif -#if HAVE_WAYLAND - void setupWaylandIntegration(); - bool handPacketWayland(const NetworkPacket& np); -#endif + AbstractRemoteInput* m_impl; -#if HAVE_X11 - FakeKey* m_fakekey; -#endif - const bool m_x11; -#if HAVE_WAYLAND - KWayland::Client::FakeInput* m_waylandInput; - bool m_waylandAuthenticationRequested; -#endif }; #endif diff --git a/plugins/mousepad/mousepadplugin.cpp b/plugins/mousepad/mousepadplugin.cpp --- a/plugins/mousepad/mousepadplugin.cpp +++ b/plugins/mousepad/mousepadplugin.cpp @@ -1,6 +1,7 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * Copyright 2015 Martin Gräßlin + * Copyright 2014 Ahmed I. Khalil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,316 +23,54 @@ #include "mousepadplugin.h" #include #include -#include -#include -#if HAVE_X11 -#include -#include -#include -#include +#if HAVE_WINDOWS + #include "windowsremoteinput.h" +#else + #include + #include + #if HAVE_X11 + #include "x11remoteinput.h" + #endif + #if HAVE_WAYLAND + #include "waylandremoteinput.h" + #endif #endif -#if HAVE_WAYLAND -#include -#include -#include -#endif K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mousepad.json", registerPlugin< MousepadPlugin >(); ) -enum MouseButtons { - LeftMouseButton = 1, - MiddleMouseButton = 2, - RightMouseButton = 3, - MouseWheelUp = 4, - MouseWheelDown = 5 -}; - -#if HAVE_X11 -//Translation table to keep in sync within all the implementations -int SpecialKeysMap[] = { - 0, // Invalid - XK_BackSpace, // 1 - XK_Tab, // 2 - XK_Linefeed, // 3 - XK_Left, // 4 - XK_Up, // 5 - XK_Right, // 6 - XK_Down, // 7 - XK_Page_Up, // 8 - XK_Page_Down, // 9 - XK_Home, // 10 - XK_End, // 11 - XK_Return, // 12 - XK_Delete, // 13 - XK_Escape, // 14 - XK_Sys_Req, // 15 - XK_Scroll_Lock, // 16 - 0, // 17 - 0, // 18 - 0, // 19 - 0, // 20 - XK_F1, // 21 - XK_F2, // 22 - XK_F3, // 23 - XK_F4, // 24 - XK_F5, // 25 - XK_F6, // 26 - XK_F7, // 27 - XK_F8, // 28 - XK_F9, // 29 - XK_F10, // 30 - XK_F11, // 31 - XK_F12, // 32 -}; -#endif - -template -size_t arraySize(T(&arr)[N]) { (void)arr; return N; } - MousepadPlugin::MousepadPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) -#if HAVE_X11 - , m_fakekey(nullptr) - , m_x11(QX11Info::isPlatformX11()) -#else - , m_x11(false) -#endif -#if HAVE_WAYLAND - , m_waylandInput(nullptr) - , m_waylandAuthenticationRequested(false) -#endif -{ -#if HAVE_WAYLAND - setupWaylandIntegration(); -#endif -} - -MousepadPlugin::~MousepadPlugin() { -#if HAVE_X11 - if (m_fakekey) { - free(m_fakekey); - m_fakekey = nullptr; - } -#endif -} - -bool MousepadPlugin::receivePacket(const NetworkPacket& np) -{ -#if HAVE_X11 - if (m_x11) { - return handlePacketX11(np); - } -#endif -#if HAVE_WAYLAND - if (m_waylandInput) { - if (!m_waylandAuthenticationRequested) { - m_waylandInput->authenticate(i18n("KDE Connect"), i18n("Use your phone as a touchpad and keyboard")); - m_waylandAuthenticationRequested = true; - } - handPacketWayland(np); - } -#endif - return false; -} - -#if HAVE_X11 -bool isLeftHanded(Display * display) -{ - unsigned char map[20]; - int num_buttons = XGetPointerMapping(display, map, 20); - if( num_buttons == 1 ) { - return false; - } else if( num_buttons == 2 ) { - return ( (int)map[0] == 2 && (int)map[1] == 1 ); +#if HAVE_WINDOWS + m_impl = new WindowsRemoteInput(this); +#else + if (QX11Info::isPlatformX11()) { + #if HAVE_X11 + m_impl = new X11RemoteInput(this); + #else + qDebug() << "KDE Connect was built without X11 support"; + #endif } else { - return ( (int)map[0] == 3 && (int)map[2] == 1 ); + Q_ASSERT(QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)); + #if HAVE_WAYLAND + m_impl = new WaylandRemoteInput(this); + #else + qDebug() << "KDE Connect was built without Wayland support"; + #endif } -} #endif - -#if HAVE_X11 -bool MousepadPlugin::handlePacketX11(const NetworkPacket& np) -{ - //qDebug() << np.serialize(); - - //TODO: Split mouse/keyboard in two different plugins to avoid this big if statement - - float dx = np.get(QStringLiteral("dx"), 0); - float dy = np.get(QStringLiteral("dy"), 0); - - bool isSingleClick = np.get(QStringLiteral("singleclick"), false); - bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false); - bool isMiddleClick = np.get(QStringLiteral("middleclick"), false); - bool isRightClick = np.get(QStringLiteral("rightclick"), false); - bool isSingleHold = np.get(QStringLiteral("singlehold"), false); - bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false); - bool isScroll = np.get(QStringLiteral("scroll"), false); - QString key = np.get(QStringLiteral("key"), QLatin1String("")); - int specialKey = np.get(QStringLiteral("specialKey"), 0); - - if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || !key.isEmpty() || specialKey) { - Display* display = QX11Info::display(); - if(!display) { - return false; - } - - bool leftHanded = isLeftHanded(display); - int mainMouseButton = leftHanded? RightMouseButton : LeftMouseButton; - int secondaryMouseButton = leftHanded? LeftMouseButton : RightMouseButton; - - if (isSingleClick) { - XTestFakeButtonEvent(display, mainMouseButton, True, 0); - XTestFakeButtonEvent(display, mainMouseButton, False, 0); - } else if (isDoubleClick) { - XTestFakeButtonEvent(display, mainMouseButton, True, 0); - XTestFakeButtonEvent(display, mainMouseButton, False, 0); - XTestFakeButtonEvent(display, mainMouseButton, True, 0); - XTestFakeButtonEvent(display, mainMouseButton, False, 0); - } else if (isMiddleClick) { - XTestFakeButtonEvent(display, MiddleMouseButton, True, 0); - XTestFakeButtonEvent(display, MiddleMouseButton, False, 0); - } else if (isRightClick) { - XTestFakeButtonEvent(display, secondaryMouseButton, True, 0); - XTestFakeButtonEvent(display, secondaryMouseButton, False, 0); - } else if (isSingleHold){ - //For drag'n drop - XTestFakeButtonEvent(display, mainMouseButton, True, 0); - } else if (isSingleRelease){ - //For drag'n drop. NEVER USED (release is done by tapping, which actually triggers a isSingleClick). Kept here for future-proofnes. - XTestFakeButtonEvent(display, mainMouseButton, False, 0); - } else if (isScroll) { - if (dy < 0) { - XTestFakeButtonEvent(display, MouseWheelDown, True, 0); - XTestFakeButtonEvent(display, MouseWheelDown, False, 0); - } else if (dy > 0) { - XTestFakeButtonEvent(display, MouseWheelUp, True, 0); - XTestFakeButtonEvent(display, MouseWheelUp, False, 0); - } - } else if (!key.isEmpty() || specialKey) { - - bool ctrl = np.get(QStringLiteral("ctrl"), false); - bool alt = np.get(QStringLiteral("alt"), false); - bool shift = np.get(QStringLiteral("shift"), false); - - if (ctrl) XTestFakeKeyEvent (display, XKeysymToKeycode(display, XK_Control_L), True, 0); - if (alt) XTestFakeKeyEvent (display, XKeysymToKeycode(display, XK_Alt_L), True, 0); - if (shift) XTestFakeKeyEvent (display, XKeysymToKeycode(display, XK_Shift_L), True, 0); - - if (specialKey) - { - if (specialKey >= (int)arraySize(SpecialKeysMap)) { - qWarning() << "Unsupported special key identifier"; - return false; - } - - int keycode = XKeysymToKeycode(display, SpecialKeysMap[specialKey]); - - XTestFakeKeyEvent (display, keycode, True, 0); - XTestFakeKeyEvent (display, keycode, False, 0); - - } else { - - if (!m_fakekey) { - m_fakekey = fakekey_init(display); - if (!m_fakekey) { - qWarning() << "Failed to initialize libfakekey"; - return false; - } - } - - //We use fakekey here instead of XTest (above) because it can handle utf characters instead of keycodes. - for (int i=0;icreate(connection); - connect(registry, &Registry::fakeInputAnnounced, this, - [this, registry] (quint32 name, quint32 version) { - m_waylandInput = registry->createFakeInput(name, version, this); - } - ); - registry->setup(); + delete m_impl; } -bool MousepadPlugin::handPacketWayland(const NetworkPacket& np) +bool MousepadPlugin::receivePacket(const NetworkPacket& np) { - const float dx = np.get(QStringLiteral("dx"), 0); - const float dy = np.get(QStringLiteral("dy"), 0); - - const bool isSingleClick = np.get(QStringLiteral("singleclick"), false); - const bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false); - const bool isMiddleClick = np.get(QStringLiteral("middleclick"), false); - const bool isRightClick = np.get(QStringLiteral("rightclick"), false); - const bool isSingleHold = np.get(QStringLiteral("singlehold"), false); - const bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false); - const bool isScroll = np.get(QStringLiteral("scroll"), false); - const QString key = np.get(QStringLiteral("key"), QLatin1String("")); - const int specialKey = np.get(QStringLiteral("specialKey"), 0); - - if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || !key.isEmpty() || specialKey) { - - if (isSingleClick) { - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - } else if (isDoubleClick) { - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - } else if (isMiddleClick) { - m_waylandInput->requestPointerButtonClick(Qt::MiddleButton); - } else if (isRightClick) { - m_waylandInput->requestPointerButtonClick(Qt::RightButton); - } else if (isSingleHold){ - //For drag'n drop - m_waylandInput->requestPointerButtonPress(Qt::LeftButton); - } else if (isSingleRelease){ - //For drag'n drop. NEVER USED (release is done by tapping, which actually triggers a isSingleClick). Kept here for future-proofnes. - m_waylandInput->requestPointerButtonRelease(Qt::LeftButton); - } else if (isScroll) { - m_waylandInput->requestPointerAxis(Qt::Vertical, dy); - } else if (!key.isEmpty() || specialKey) { - // TODO: implement key support - } - - } else { //Is a mouse move event - m_waylandInput->requestPointerMove(QSizeF(dx, dy)); - } - return true; + return m_impl->handlePacket(np); } -#endif #include "mousepadplugin.moc" diff --git a/plugins/mousepad_windows/mousepadplugin_windows.h b/plugins/mousepad/waylandremoteinput.h copy from plugins/mousepad_windows/mousepadplugin_windows.h copy to plugins/mousepad/waylandremoteinput.h --- a/plugins/mousepad_windows/mousepadplugin_windows.h +++ b/plugins/mousepad/waylandremoteinput.h @@ -1,5 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,25 +18,34 @@ * along with this program. If not, see . */ -#ifndef MOUSEPADPLUGIN_H -#define MOUSEPADPLUGIN_H +#ifndef WAYLANDREMOTEINPUT_H +#define WAYLANDREMOTEINPUT_H -#include -#include +#include "abstractremoteinput.h" -#include +namespace KWayland +{ + namespace Client + { + class FakeInput; + } +} -class MousepadPlugin - : public KdeConnectPlugin +class WaylandRemoteInput + : public AbstractRemoteInput { Q_OBJECT public: - explicit MousepadPlugin(QObject* parent, const QVariantList &args); - ~MousepadPlugin() override; + explicit WaylandRemoteInput(QObject* parent); + + bool handlePacket(const NetworkPacket& np) override; + +private: + void setupWaylandIntegration(); - bool receivePacket(const NetworkPacket& np) override; - void connected() override { } + KWayland::Client::FakeInput* m_waylandInput; + bool m_waylandAuthenticationRequested; }; #endif diff --git a/plugins/mousepad/waylandremoteinput.cpp b/plugins/mousepad/waylandremoteinput.cpp new file mode 100644 --- /dev/null +++ b/plugins/mousepad/waylandremoteinput.cpp @@ -0,0 +1,103 @@ +/** + * Copyright 2015 Martin Gräßlin + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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. If not, see . + */ + +#include "waylandremoteinput.h" + +#include +#include + +#include +#include +#include +#include + +WaylandRemoteInput::WaylandRemoteInput(QObject* parent) + : AbstractRemoteInput(parent) + , m_waylandInput(nullptr) + , m_waylandAuthenticationRequested(false) +{ + using namespace KWayland::Client; + ConnectionThread* connection = ConnectionThread::fromApplication(this); + if (!connection) { + qDebug() << "failed to get the Connection from Qt, Wayland remote input will not work"; + return; + } + Registry* registry = new Registry(this); + registry->create(connection); + connect(registry, &Registry::fakeInputAnnounced, this, + [this, registry] (quint32 name, quint32 version) { + m_waylandInput = registry->createFakeInput(name, version, this); + } + ); + registry->setup(); +} + +bool WaylandRemoteInput::handlePacket(const NetworkPacket& np) +{ + if (!m_waylandInput) { + return false; + } + + if (!m_waylandAuthenticationRequested) { + m_waylandInput->authenticate(i18n("KDE Connect"), i18n("Use your phone as a touchpad and keyboard")); + m_waylandAuthenticationRequested = true; + } + + const float dx = np.get(QStringLiteral("dx"), 0); + const float dy = np.get(QStringLiteral("dy"), 0); + + const bool isSingleClick = np.get(QStringLiteral("singleclick"), false); + const bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false); + const bool isMiddleClick = np.get(QStringLiteral("middleclick"), false); + const bool isRightClick = np.get(QStringLiteral("rightclick"), false); + const bool isSingleHold = np.get(QStringLiteral("singlehold"), false); + const bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false); + const bool isScroll = np.get(QStringLiteral("scroll"), false); + const QString key = np.get(QStringLiteral("key"), QLatin1String("")); + const int specialKey = np.get(QStringLiteral("specialKey"), 0); + + if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || !key.isEmpty() || specialKey) { + + if (isSingleClick) { + m_waylandInput->requestPointerButtonClick(Qt::LeftButton); + } else if (isDoubleClick) { + m_waylandInput->requestPointerButtonClick(Qt::LeftButton); + m_waylandInput->requestPointerButtonClick(Qt::LeftButton); + } else if (isMiddleClick) { + m_waylandInput->requestPointerButtonClick(Qt::MiddleButton); + } else if (isRightClick) { + m_waylandInput->requestPointerButtonClick(Qt::RightButton); + } else if (isSingleHold){ + //For drag'n drop + m_waylandInput->requestPointerButtonPress(Qt::LeftButton); + } else if (isSingleRelease){ + //For drag'n drop. NEVER USED (release is done by tapping, which actually triggers a isSingleClick). Kept here for future-proofnes. + m_waylandInput->requestPointerButtonRelease(Qt::LeftButton); + } else if (isScroll) { + m_waylandInput->requestPointerAxis(Qt::Vertical, dy); + } else if (!key.isEmpty() || specialKey) { + // TODO: implement key support + } + + } else { //Is a mouse move event + m_waylandInput->requestPointerMove(QSizeF(dx, dy)); + } + return true; +} diff --git a/plugins/mousepad_windows/mousepadplugin_windows.h b/plugins/mousepad/windowsremoteinput.h copy from plugins/mousepad_windows/mousepadplugin_windows.h copy to plugins/mousepad/windowsremoteinput.h --- a/plugins/mousepad_windows/mousepadplugin_windows.h +++ b/plugins/mousepad/windowsremoteinput.h @@ -1,5 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,25 +18,20 @@ * along with this program. If not, see . */ -#ifndef MOUSEPADPLUGIN_H -#define MOUSEPADPLUGIN_H +#ifndef WINDOWSREMOTEINPUT_H +#define WINDOWSREMOTEINPUT_H -#include -#include +#include "abstractremoteinput.h" -#include - -class MousepadPlugin - : public KdeConnectPlugin +class WindowsRemoteInput + : public AbstractRemoteInput { Q_OBJECT public: - explicit MousepadPlugin(QObject* parent, const QVariantList &args); - ~MousepadPlugin() override; + explicit WindowsRemoteInput(QObject* parent); - bool receivePacket(const NetworkPacket& np) override; - void connected() override { } + bool handlePacket(const NetworkPacket& np) override; }; #endif diff --git a/plugins/mousepad_windows/mousepadplugin_windows.cpp b/plugins/mousepad/windowsremoteinput.cpp rename from plugins/mousepad_windows/mousepadplugin_windows.cpp rename to plugins/mousepad/windowsremoteinput.cpp --- a/plugins/mousepad_windows/mousepadplugin_windows.cpp +++ b/plugins/mousepad/windowsremoteinput.cpp @@ -1,6 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil - * Copyright 2015 Martin Gräßlin + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -19,27 +18,19 @@ * along with this program. If not, see . */ -#include "mousepadplugin_windows.h" -#include -#include -#include -#include +#include "windowsremoteinput.h" + #include #include -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mousepad.json", registerPlugin< MousepadPlugin >(); ) - -MousepadPlugin::MousepadPlugin(QObject* parent, const QVariantList& args) - : KdeConnectPlugin(parent, args) +WindowsRemoteInput::WindowsRemoteInput(QObject* parent) + : AbstractRemoteInput(parent) { -} -MousepadPlugin::~MousepadPlugin() -{ } -bool MousepadPlugin::receivePacket(const NetworkPacket& np) +bool WindowsRemoteInput::handlePacket(const NetworkPacket& np) { float dx = np.get(QStringLiteral("dx"), 0); float dy = np.get(QStringLiteral("dy"), 0); @@ -93,6 +84,7 @@ input.mi.dwFlags = MOUSEEVENTF_WHEEL; input.mi.mouseData = dy; ::SendInput(1,&input,sizeof(INPUT)); +//TODO: Keyboard input support /* } else if (!key.isEmpty() || specialKey) { @@ -146,5 +138,3 @@ } return true; } - -#include "mousepadplugin_windows.moc" diff --git a/plugins/mousepad_windows/mousepadplugin_windows.h b/plugins/mousepad/x11remoteinput.h rename from plugins/mousepad_windows/mousepadplugin_windows.h rename to plugins/mousepad/x11remoteinput.h --- a/plugins/mousepad_windows/mousepadplugin_windows.h +++ b/plugins/mousepad/x11remoteinput.h @@ -1,5 +1,5 @@ /** - * Copyright 2014 Ahmed I. Khalil + * Copyright 2018 Albert Vaca Cintora * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,25 +18,26 @@ * along with this program. If not, see . */ -#ifndef MOUSEPADPLUGIN_H -#define MOUSEPADPLUGIN_H +#ifndef X11REMOTEINPUT_H +#define X11REMOTEINPUT_H -#include -#include +#include "abstractremoteinput.h" -#include +struct FakeKey; -class MousepadPlugin - : public KdeConnectPlugin +class X11RemoteInput + : public AbstractRemoteInput { Q_OBJECT public: - explicit MousepadPlugin(QObject* parent, const QVariantList &args); - ~MousepadPlugin() override; + explicit X11RemoteInput(QObject* parent); + ~X11RemoteInput() override; - bool receivePacket(const NetworkPacket& np) override; - void connected() override { } + bool handlePacket(const NetworkPacket& np) override; + +private: + FakeKey* m_fakekey; }; #endif diff --git a/plugins/mousepad/mousepadplugin.cpp b/plugins/mousepad/x11remoteinput.cpp copy from plugins/mousepad/mousepadplugin.cpp copy to plugins/mousepad/x11remoteinput.cpp --- a/plugins/mousepad/mousepadplugin.cpp +++ b/plugins/mousepad/x11remoteinput.cpp @@ -1,6 +1,6 @@ /** + * Copyright 2018 Albert Vaca Cintora * Copyright 2014 Ahmed I. Khalil - * Copyright 2015 Martin Gräßlin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -19,26 +19,15 @@ * along with this program. If not, see . */ -#include "mousepadplugin.h" -#include -#include -#include -#include +#include "x11remoteinput.h" -#if HAVE_X11 #include +#include +#include + #include #include #include -#endif - -#if HAVE_WAYLAND -#include -#include -#include -#endif - -K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mousepad.json", registerPlugin< MousepadPlugin >(); ) enum MouseButtons { LeftMouseButton = 1, @@ -48,7 +37,6 @@ MouseWheelDown = 5 }; -#if HAVE_X11 //Translation table to keep in sync within all the implementations int SpecialKeysMap[] = { 0, // Invalid @@ -85,59 +73,26 @@ XK_F11, // 31 XK_F12, // 32 }; -#endif template size_t arraySize(T(&arr)[N]) { (void)arr; return N; } -MousepadPlugin::MousepadPlugin(QObject* parent, const QVariantList& args) - : KdeConnectPlugin(parent, args) -#if HAVE_X11 + +X11RemoteInput::X11RemoteInput(QObject* parent) + : AbstractRemoteInput(parent) , m_fakekey(nullptr) - , m_x11(QX11Info::isPlatformX11()) -#else - , m_x11(false) -#endif -#if HAVE_WAYLAND - , m_waylandInput(nullptr) - , m_waylandAuthenticationRequested(false) -#endif { -#if HAVE_WAYLAND - setupWaylandIntegration(); -#endif + } -MousepadPlugin::~MousepadPlugin() +X11RemoteInput::~X11RemoteInput() { -#if HAVE_X11 if (m_fakekey) { free(m_fakekey); m_fakekey = nullptr; } -#endif -} - -bool MousepadPlugin::receivePacket(const NetworkPacket& np) -{ -#if HAVE_X11 - if (m_x11) { - return handlePacketX11(np); - } -#endif -#if HAVE_WAYLAND - if (m_waylandInput) { - if (!m_waylandAuthenticationRequested) { - m_waylandInput->authenticate(i18n("KDE Connect"), i18n("Use your phone as a touchpad and keyboard")); - m_waylandAuthenticationRequested = true; - } - handPacketWayland(np); - } -#endif - return false; } -#if HAVE_X11 bool isLeftHanded(Display * display) { unsigned char map[20]; @@ -150,15 +105,9 @@ return ( (int)map[0] == 3 && (int)map[2] == 1 ); } } -#endif -#if HAVE_X11 -bool MousepadPlugin::handlePacketX11(const NetworkPacket& np) +bool X11RemoteInput::handlePacket(const NetworkPacket& np) { - //qDebug() << np.serialize(); - - //TODO: Split mouse/keyboard in two different plugins to avoid this big if statement - float dx = np.get(QStringLiteral("dx"), 0); float dy = np.get(QStringLiteral("dy"), 0); @@ -264,74 +213,3 @@ } return true; } -#endif - -#if HAVE_WAYLAND -void MousepadPlugin::setupWaylandIntegration() -{ - if (!QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { - // not wayland - return; - } - using namespace KWayland::Client; - ConnectionThread* connection = ConnectionThread::fromApplication(this); - if (!connection) { - // failed to get the Connection from Qt - return; - } - Registry* registry = new Registry(this); - registry->create(connection); - connect(registry, &Registry::fakeInputAnnounced, this, - [this, registry] (quint32 name, quint32 version) { - m_waylandInput = registry->createFakeInput(name, version, this); - } - ); - registry->setup(); -} - -bool MousepadPlugin::handPacketWayland(const NetworkPacket& np) -{ - const float dx = np.get(QStringLiteral("dx"), 0); - const float dy = np.get(QStringLiteral("dy"), 0); - - const bool isSingleClick = np.get(QStringLiteral("singleclick"), false); - const bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false); - const bool isMiddleClick = np.get(QStringLiteral("middleclick"), false); - const bool isRightClick = np.get(QStringLiteral("rightclick"), false); - const bool isSingleHold = np.get(QStringLiteral("singlehold"), false); - const bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false); - const bool isScroll = np.get(QStringLiteral("scroll"), false); - const QString key = np.get(QStringLiteral("key"), QLatin1String("")); - const int specialKey = np.get(QStringLiteral("specialKey"), 0); - - if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || !key.isEmpty() || specialKey) { - - if (isSingleClick) { - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - } else if (isDoubleClick) { - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - m_waylandInput->requestPointerButtonClick(Qt::LeftButton); - } else if (isMiddleClick) { - m_waylandInput->requestPointerButtonClick(Qt::MiddleButton); - } else if (isRightClick) { - m_waylandInput->requestPointerButtonClick(Qt::RightButton); - } else if (isSingleHold){ - //For drag'n drop - m_waylandInput->requestPointerButtonPress(Qt::LeftButton); - } else if (isSingleRelease){ - //For drag'n drop. NEVER USED (release is done by tapping, which actually triggers a isSingleClick). Kept here for future-proofnes. - m_waylandInput->requestPointerButtonRelease(Qt::LeftButton); - } else if (isScroll) { - m_waylandInput->requestPointerAxis(Qt::Vertical, dy); - } else if (!key.isEmpty() || specialKey) { - // TODO: implement key support - } - - } else { //Is a mouse move event - m_waylandInput->requestPointerMove(QSizeF(dx, dy)); - } - return true; -} -#endif - -#include "mousepadplugin.moc" diff --git a/plugins/mousepad_windows/CMakeLists.txt b/plugins/mousepad_windows/CMakeLists.txt deleted file mode 100644 --- a/plugins/mousepad_windows/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -kdeconnect_add_plugin(kdeconnect_mousepad JSON kdeconnect_mousepad.json SOURCES mousepadplugin_windows.cpp) -target_link_libraries(kdeconnect_mousepad kdeconnectcore Qt5::Gui KF5::I18n) diff --git a/plugins/mousepad_windows/kdeconnect_mousepad.json b/plugins/mousepad_windows/kdeconnect_mousepad.json deleted file mode 100644 --- a/plugins/mousepad_windows/kdeconnect_mousepad.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "KPlugin": { - "Authors": [ - { - "Email": "ahmedibrahimkhali@gmail.com", - "Name": "Ahmed I. Khalil", - "Name[ar]": "أحمد إبراهيم خليل", - "Name[sr@ijekavian]": "Ахмед И. Калил", - "Name[sr@ijekavianlatin]": "Ahmed I. Kalil", - "Name[sr@latin]": "Ahmed I. Kalil", - "Name[sr]": "Ахмед И. Калил", - "Name[x-test]": "xxAhmed I. Khalilxx" - } - ], - "Description": "Use your phone as a touchpad and keyboard", - "Description[ar]": "استخدم الهاتف كفأرة ولوحة مفاتيح", - "Description[ca@valencia]": "Empra el telèfon com un ratolí tàctil i teclat", - "Description[ca]": "Empra el telèfon com un ratolí tàctil i teclat", - "Description[cs]": "Používejte svůj telefon jako touchpad a klávesnici", - "Description[da]": "Brug din telefon som touchpad og tastatur", - "Description[de]": "Verwendet Ihr Handy als Touchpad und Tastatur", - "Description[el]": "Χρήση του τηλεφώνου σας ως οθόνη αφής και πληκτρολογίου", - "Description[es]": "Usar teléfono como panel táctil y teclado", - "Description[et]": "Telefoni kasutamine puutepadja ja klaviatuurina", - "Description[eu]": "Erabili zure telefonoa touchpad eta teklatu gisa", - "Description[fi]": "Käytä puhelintasi kosketuslevynä ja näppäimistönä", - "Description[fr]": "Utilisez votre téléphone comme un pavé tactile et un clavier", - "Description[gl]": "Usar o teléfono móbil como área táctil e teclado.", - "Description[hu]": "A telefon használata érintőtáblaként és billentyűzetként", - "Description[it]": "Usa il telefono come touchpad e tastiera", - "Description[ko]": "휴대폰을 터치패드와 키보드로 사용", - "Description[nl]": "Uw telefoon gebruiken als een touchpad en toetsenbord", - "Description[nn]": "Bruk telefonen som styreplate og tastatur", - "Description[pl]": "Używaj swojego telefonu jako gładzika i klawiatury", - "Description[pt]": "Use o seu telefone como um rato e teclado por toque", - "Description[pt_BR]": "Use seu telefone como um touchpad e teclado", - "Description[ru]": "Использование телефона в качестве сенсорной панели и клавиатуры", - "Description[sk]": "Použite váš telefón ako touchpad a klávesnicu", - "Description[sr@ijekavian]": "Користите телефон као додирник и тастатуру", - "Description[sr@ijekavianlatin]": "Koristite telefon kao dodirnik i tastaturu", - "Description[sr@latin]": "Koristite telefon kao dodirnik i tastaturu", - "Description[sr]": "Користите телефон као додирник и тастатуру", - "Description[sv]": "Använd telefonen som mus och tangentbord", - "Description[tr]": "Telefonunuzu dokunmatik yüzey ve klayve olarak kullanın", - "Description[uk]": "Скористайтеся телефоном як замінником сенсорної панелі і клавіатури", - "Description[x-test]": "xxUse your phone as a touchpad and keyboardxx", - "Description[zh_CN]": "用您的手机作为触摸板和键盘", - "Description[zh_TW]": "讓您的智慧型手機當作觸碰板與鍵盤", - "EnabledByDefault": true, - "Icon": "edit-select", - "Id": "kdeconnect_mousepad", - "License": "GPL", - "Name": "Virtual input", - "Name[ar]": "دخل وهميّ", - "Name[ca@valencia]": "Entrada virtual", - "Name[ca]": "Entrada virtual", - "Name[cs]": "Virtuální vstup", - "Name[da]": "Virtuelt input", - "Name[de]": "Virtuelle Eingabe", - "Name[el]": "Εικονικά στοιχεία εισόδου", - "Name[es]": "Entrada virtual", - "Name[et]": "Virtuaalsisestus", - "Name[eu]": "Sarrera birtuala", - "Name[fi]": "Virtuaalinen syöttö", - "Name[fr]": "Entrée virtuelle", - "Name[gl]": "Entrada virtual", - "Name[hu]": "Virtuális bevitel", - "Name[it]": "Inserimento virtuale", - "Name[ko]": "가상 입력", - "Name[nl]": "Virtuele invoer", - "Name[nn]": "Virtuelt tastatur", - "Name[pl]": "Wirtualna obsługa", - "Name[pt]": "Entrada virtual", - "Name[pt_BR]": "Entrada virtual", - "Name[ru]": "Виртуальный ввод", - "Name[sk]": "Virtuálny vstup", - "Name[sr@ijekavian]": "Виртуелни унос", - "Name[sr@ijekavianlatin]": "Virtuelni unos", - "Name[sr@latin]": "Virtuelni unos", - "Name[sr]": "Виртуелни унос", - "Name[sv]": "Virtuell inmatning", - "Name[tr]": "Sanal içe aktarma", - "Name[uk]": "Віртуальне введення даних", - "Name[x-test]": "xxVirtual inputxx", - "Name[zh_CN]": "虚拟输入", - "Name[zh_TW]": "虛擬輸入", - "ServiceTypes": [ - "KdeConnect/Plugin" - ], - "Version": "0.1" - }, - "X-KdeConnect-OutgoingPacketType": [], - "X-KdeConnect-SupportedPacketType": [ - "kdeconnect.mousepad.request" - ] -}