support sending a keymap

This commit is contained in:
Aleix Pol 2022-07-26 01:56:46 +02:00
parent f38361b57d
commit 87c9281e5e
4 changed files with 76 additions and 7 deletions

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.16)
# KDE Release Service Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "22")

View file

@ -14,10 +14,15 @@ if(UNIX AND NOT APPLE)
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_link_libraries(kdeconnect_mousepad Wayland::Client Qt5::WaylandClient PkgConfig::XkbCommon)
target_link_libraries(kdeconnect_mousepad Wayland::Client Qt5::WaylandClient PkgConfig::XkbCommon Qt::GuiPrivate)
target_sources(kdeconnect_mousepad PUBLIC waylandremoteinput.cpp)
set(HAVE_WAYLAND TRUE)

View file

@ -6,16 +6,23 @@
#include "waylandremoteinput.h"
#include <QSizeF>
#include <QDebug>
#include <QGuiApplication>
#include <QSizeF>
#include <QTemporaryFile>
#include <KLocalizedString>
#include <qpa/qplatformnativeinterface.h>
#include <QtWaylandClient/qwaylandclientextension.h>
#include "qwayland-fake-input.h"
#include "qwayland-wayland.h"
#include "qwayland-wayland.h"
#include <linux/input.h>
#include <xkbcommon/xkbcommon.h>
#include <unistd.h>
#include <sys/mman.h>
namespace
{
@ -66,17 +73,41 @@ public:
}
};
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)
: AbstractRemoteInput(parent)
, m_fakeInput(new FakeInput)
, m_keyboard(new WlKeyboard(this))
, m_waylandAuthenticationRequested(false)
{
m_fakeInput = new FakeInput;
m_keyboard->init(static_cast<wl_keyboard *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_keyboard")));
}
WaylandRemoteInput::~WaylandRemoteInput()
{
delete m_fakeInput;
}
bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
@ -104,7 +135,6 @@ bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
const int specialKey = np.get<int>(QStringLiteral("specialKey"), 0);
if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isSingleRelease || isScroll || !key.isEmpty() || specialKey) {
if (isSingleClick) {
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
m_fakeInput->button(BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
@ -133,6 +163,32 @@ bool WaylandRemoteInput::handlePacket(const NetworkPacket& np)
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;
}
unlink(tmp->fileName().toUtf8().constData());
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);

View file

@ -10,6 +10,7 @@
#include "abstractremoteinput.h"
class FakeInput;
class WlKeyboard;
class WaylandRemoteInput
: public AbstractRemoteInput
@ -20,13 +21,20 @@ public:
explicit WaylandRemoteInput(QObject* parent);
~WaylandRemoteInput();
void setKeymap(const QByteArray &keymap) {
m_keymapSent = false;
m_keymap = keymap;
}
bool handlePacket(const NetworkPacket& np) override;
private:
void setupWaylandIntegration();
FakeInput *m_fakeInput;
QScopedPointer<FakeInput> m_fakeInput;
QScopedPointer<WlKeyboard> m_keyboard;
bool m_waylandAuthenticationRequested;
bool m_keymapSent = false;
QByteArray m_keymap;
};
#endif