Compare commits
2 commits
master
...
work/wayla
Author | SHA1 | Date | |
---|---|---|---|
|
87c9281e5e | ||
|
f38361b57d |
4 changed files with 128 additions and 11 deletions
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
# KDE Release Service Version, managed by release script
|
# KDE Release Service Version, managed by release script
|
||||||
set (RELEASE_SERVICE_VERSION_MAJOR "22")
|
set (RELEASE_SERVICE_VERSION_MAJOR "22")
|
||||||
|
|
|
@ -14,8 +14,15 @@ if(UNIX AND NOT APPLE)
|
||||||
BASENAME fake-input
|
BASENAME fake-input
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ecm_add_qtwayland_client_protocol(wayland_SRCS
|
||||||
|
PROTOCOL ${Wayland_DATADIR}/wayland.xml
|
||||||
|
BASENAME wayland
|
||||||
|
)
|
||||||
|
|
||||||
|
pkg_check_modules(XkbCommon IMPORTED_TARGET xkbcommon)
|
||||||
|
|
||||||
target_sources(kdeconnect_mousepad PRIVATE ${wayland_SRCS})
|
target_sources(kdeconnect_mousepad PRIVATE ${wayland_SRCS})
|
||||||
target_link_libraries(kdeconnect_mousepad Wayland::Client Qt5::WaylandClient)
|
target_link_libraries(kdeconnect_mousepad Wayland::Client Qt5::WaylandClient PkgConfig::XkbCommon Qt::GuiPrivate)
|
||||||
target_sources(kdeconnect_mousepad PUBLIC waylandremoteinput.cpp)
|
target_sources(kdeconnect_mousepad PUBLIC waylandremoteinput.cpp)
|
||||||
set(HAVE_WAYLAND TRUE)
|
set(HAVE_WAYLAND TRUE)
|
||||||
|
|
||||||
|
|
|
@ -6,36 +6,108 @@
|
||||||
|
|
||||||
#include "waylandremoteinput.h"
|
#include "waylandremoteinput.h"
|
||||||
|
|
||||||
#include <QSizeF>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QSizeF>
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
#include <QtWaylandClient/qwaylandclientextension.h>
|
#include <QtWaylandClient/qwaylandclientextension.h>
|
||||||
#include "qwayland-fake-input.h"
|
#include "qwayland-fake-input.h"
|
||||||
|
#include "qwayland-wayland.h"
|
||||||
|
#include "qwayland-wayland.h"
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//Translation table to keep in sync within all the implementations
|
||||||
|
int SpecialKeysMap[] = {
|
||||||
|
0, // Invalid
|
||||||
|
KEY_BACKSPACE, // 1
|
||||||
|
KEY_TAB, // 2
|
||||||
|
KEY_LINEFEED, // 3
|
||||||
|
KEY_LEFT, // 4
|
||||||
|
KEY_UP, // 5
|
||||||
|
KEY_RIGHT, // 6
|
||||||
|
KEY_DOWN, // 7
|
||||||
|
KEY_PAGEUP, // 8
|
||||||
|
KEY_PAGEDOWN, // 9
|
||||||
|
KEY_HOME, // 10
|
||||||
|
KEY_END, // 11
|
||||||
|
KEY_ENTER, // 12
|
||||||
|
KEY_DELETE, // 13
|
||||||
|
KEY_ESC, // 14
|
||||||
|
KEY_SYSRQ, // 15
|
||||||
|
KEY_SCROLLLOCK, // 16
|
||||||
|
0, // 17
|
||||||
|
0, // 18
|
||||||
|
0, // 19
|
||||||
|
0, // 20
|
||||||
|
KEY_F1, // 21
|
||||||
|
KEY_F2, // 22
|
||||||
|
KEY_F3, // 23
|
||||||
|
KEY_F4, // 24
|
||||||
|
KEY_F5, // 25
|
||||||
|
KEY_F6, // 26
|
||||||
|
KEY_F7, // 27
|
||||||
|
KEY_F8, // 28
|
||||||
|
KEY_F9, // 29
|
||||||
|
KEY_F10, // 30
|
||||||
|
KEY_F11, // 31
|
||||||
|
KEY_F12, // 32
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class FakeInput : public QWaylandClientExtensionTemplate<FakeInput>, public QtWayland::org_kde_kwin_fake_input
|
class FakeInput : public QWaylandClientExtensionTemplate<FakeInput>, public QtWayland::org_kde_kwin_fake_input
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FakeInput()
|
FakeInput()
|
||||||
: QWaylandClientExtensionTemplate<FakeInput>(4)
|
: QWaylandClientExtensionTemplate<FakeInput>(5)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WlKeyboard : public QtWayland::wl_keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WlKeyboard(WaylandRemoteInput *input)
|
||||||
|
: m_input(input)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void keyboard_keymap(uint32_t format, int32_t fd, uint32_t size) override {
|
||||||
|
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
|
||||||
|
if (map_str == MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_input->setKeymap(QByteArray(map_str, size));
|
||||||
|
}
|
||||||
|
WaylandRemoteInput *const m_input;
|
||||||
|
};
|
||||||
|
|
||||||
WaylandRemoteInput::WaylandRemoteInput(QObject* parent)
|
WaylandRemoteInput::WaylandRemoteInput(QObject* parent)
|
||||||
: AbstractRemoteInput(parent)
|
: AbstractRemoteInput(parent)
|
||||||
|
, m_fakeInput(new FakeInput)
|
||||||
|
, m_keyboard(new WlKeyboard(this))
|
||||||
, m_waylandAuthenticationRequested(false)
|
, m_waylandAuthenticationRequested(false)
|
||||||
{
|
{
|
||||||
m_fakeInput = new FakeInput;
|
m_keyboard->init(static_cast<wl_keyboard *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_keyboard")));
|
||||||
}
|
}
|
||||||
|
|
||||||
WaylandRemoteInput::~WaylandRemoteInput()
|
WaylandRemoteInput::~WaylandRemoteInput()
|
||||||
{
|
{
|
||||||
delete m_fakeInput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
|
bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
|
||||||
|
@ -63,7 +135,6 @@ bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
|
||||||
const int specialKey = np.get<int>(QStringLiteral("specialKey"), 0);
|
const int specialKey = np.get<int>(QStringLiteral("specialKey"), 0);
|
||||||
|
|
||||||
if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isSingleRelease || isScroll || !key.isEmpty() || specialKey) {
|
if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isSingleRelease || isScroll || !key.isEmpty() || specialKey) {
|
||||||
|
|
||||||
if (isSingleClick) {
|
if (isSingleClick) {
|
||||||
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
|
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
|
||||||
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||||
|
@ -88,11 +159,42 @@ bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
|
||||||
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||||
} else if (isScroll) {
|
} else if (isScroll) {
|
||||||
m_fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(-dy));
|
m_fakeInput->axis(WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(-dy));
|
||||||
|
} else if (specialKey) {
|
||||||
|
m_fakeInput->keyboard_key(SpecialKeysMap[specialKey], 1);
|
||||||
|
m_fakeInput->keyboard_key(SpecialKeysMap[specialKey], 0);
|
||||||
|
} else if (!key.isEmpty()) {
|
||||||
|
if (!m_keymapSent && !m_keymap.isEmpty()) {
|
||||||
|
m_keymapSent = true;
|
||||||
|
auto sendKeymap = [this] {
|
||||||
|
QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
|
||||||
|
if (!tmp->open()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (!key.isEmpty() || specialKey) {
|
unlink(tmp->fileName().toUtf8().constData());
|
||||||
// TODO: implement key support
|
if (!tmp->resize(m_keymap.size())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *address = tmp->map(0, m_keymap.size());
|
||||||
|
if (!address) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qstrncpy(reinterpret_cast<char *>(address), m_keymap.constData(), m_keymap.size() + 1);
|
||||||
|
tmp->unmap(address);
|
||||||
|
|
||||||
|
m_fakeInput->keyboard_keymap(tmp->handle(), tmp->size());
|
||||||
|
};
|
||||||
|
sendKeymap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QChar character : key) {
|
||||||
|
const auto keysym = xkb_utf32_to_keysym(character.unicode());
|
||||||
|
m_fakeInput->keyboard_keysym(keysym, 1);
|
||||||
|
m_fakeInput->keyboard_keysym(keysym, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { //Is a mouse move event
|
} else { //Is a mouse move event
|
||||||
m_fakeInput->pointer_motion(wl_fixed_from_double(dx), wl_fixed_from_double(dy));
|
m_fakeInput->pointer_motion(wl_fixed_from_double(dx), wl_fixed_from_double(dy));
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "abstractremoteinput.h"
|
#include "abstractremoteinput.h"
|
||||||
|
|
||||||
class FakeInput;
|
class FakeInput;
|
||||||
|
class WlKeyboard;
|
||||||
|
|
||||||
class WaylandRemoteInput
|
class WaylandRemoteInput
|
||||||
: public AbstractRemoteInput
|
: public AbstractRemoteInput
|
||||||
|
@ -20,13 +21,20 @@ public:
|
||||||
explicit WaylandRemoteInput(QObject* parent);
|
explicit WaylandRemoteInput(QObject* parent);
|
||||||
~WaylandRemoteInput();
|
~WaylandRemoteInput();
|
||||||
|
|
||||||
|
void setKeymap(const QByteArray &keymap) {
|
||||||
|
m_keymapSent = false;
|
||||||
|
m_keymap = keymap;
|
||||||
|
}
|
||||||
bool handlePacket(const NetworkPacket& np) override;
|
bool handlePacket(const NetworkPacket& np) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupWaylandIntegration();
|
void setupWaylandIntegration();
|
||||||
|
|
||||||
FakeInput *m_fakeInput;
|
QScopedPointer<FakeInput> m_fakeInput;
|
||||||
|
QScopedPointer<WlKeyboard> m_keyboard;
|
||||||
bool m_waylandAuthenticationRequested;
|
bool m_waylandAuthenticationRequested;
|
||||||
|
bool m_keymapSent = false;
|
||||||
|
QByteArray m_keymap;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue