Add initial files
This commit is contained in:
commit
76dfebe0e8
6 changed files with 330 additions and 0 deletions
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
.clang-format
|
||||
/build*/
|
||||
CMakeLists.txt.user
|
||||
compile_commands.json
|
||||
.cache
|
||||
src/resources.generated.qrc
|
||||
.flatpak-builder/
|
55
CMakeLists.txt
Normal file
55
CMakeLists.txt
Normal file
|
@ -0,0 +1,55 @@
|
|||
cmake_minimum_required(VERSION 3.30)
|
||||
project(inputfaker)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
set(QT_MIN_VERSION 6.5)
|
||||
set(KF_MIN_VERSION 6.0)
|
||||
|
||||
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(ECMFindQmlModule)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(ECMSetupVersion)
|
||||
include(ECMGenerateHeaders)
|
||||
include(ECMPoQmTools)
|
||||
include(KDEGitCommitHooks)
|
||||
include(KDEClangFormat)
|
||||
include(ECMQmlModule)
|
||||
|
||||
find_package(Qt6 COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Qml
|
||||
QuickControls2
|
||||
REQUIRED)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Kirigami CoreAddons I18n WindowSystem)
|
||||
pkg_check_modules(libevdev REQUIRED IMPORTED_TARGET libevdev)
|
||||
|
||||
add_executable(inputfaker main.cpp devicemanager.cpp)
|
||||
ecm_add_qml_module(inputfaker
|
||||
URI org.kde.inputfaker
|
||||
VERSION 1.0)
|
||||
|
||||
ecm_target_qml_sources(inputfaker SOURCES
|
||||
ui/Main.qml)
|
||||
target_link_libraries(inputfaker PRIVATE
|
||||
Qt::Core
|
||||
Qt::Qml
|
||||
Qt::Quick
|
||||
Qt::QuickControls2
|
||||
KF6::I18n
|
||||
KF6::WindowSystem
|
||||
KF6::CoreAddons
|
||||
PkgConfig::libevdev
|
||||
)
|
||||
|
135
devicemanager.cpp
Normal file
135
devicemanager.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include "devicemanager.h"
|
||||
|
||||
DeviceManager::~DeviceManager() { destroyDevice(); }
|
||||
|
||||
QString DeviceManager::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void DeviceManager::setName(const QString &name)
|
||||
{
|
||||
if (m_name != name)
|
||||
{
|
||||
m_name = name;
|
||||
Q_EMIT nameChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceManager::direct() const
|
||||
{
|
||||
return m_direct;
|
||||
}
|
||||
|
||||
void DeviceManager::setDirect(bool direct)
|
||||
{
|
||||
if (m_direct != direct)
|
||||
{
|
||||
m_direct = direct;
|
||||
Q_EMIT directChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceManager::pad() const
|
||||
{
|
||||
return m_pad;
|
||||
}
|
||||
|
||||
void DeviceManager::setPad(bool pad)
|
||||
{
|
||||
if (m_pad != pad)
|
||||
{
|
||||
m_pad = pad;
|
||||
Q_EMIT padChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::recreateDevice()
|
||||
{
|
||||
destroyDevice();
|
||||
|
||||
input_absinfo xInfo{
|
||||
.value = 28166,
|
||||
.minimum = 0,
|
||||
.maximum = 47664,
|
||||
.resolution = 100,
|
||||
};
|
||||
|
||||
input_absinfo yInfo{
|
||||
.value = 22040,
|
||||
.minimum = 0,
|
||||
.maximum = 26778,
|
||||
.resolution = 100,
|
||||
};
|
||||
|
||||
input_absinfo pressureInfo{
|
||||
.minimum = 0,
|
||||
.maximum = 8191,
|
||||
};
|
||||
|
||||
input_absinfo tiltInfo{
|
||||
.minimum = -127,
|
||||
.maximum = 127,
|
||||
};
|
||||
|
||||
dev = libevdev_new();
|
||||
libevdev_set_name(dev, m_name.toUtf8().constData());
|
||||
libevdev_enable_event_type(dev, EV_SYN);
|
||||
libevdev_enable_event_type(dev, EV_KEY);
|
||||
if (!m_pad)
|
||||
{
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_PEN, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_RUBBER, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_TOUCH, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_STYLUS, NULL);
|
||||
|
||||
libevdev_enable_event_type(dev, EV_ABS);
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_X, &xInfo);
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_Y, &yInfo);
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_PRESSURE, &pressureInfo);
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_TILT_Y, &tiltInfo);
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_TILT_X, &tiltInfo);
|
||||
|
||||
if (m_direct)
|
||||
{
|
||||
libevdev_enable_property(dev, INPUT_PROP_DIRECT);
|
||||
}
|
||||
} else
|
||||
{
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_0, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_1, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_2, NULL);
|
||||
libevdev_enable_event_code(dev, EV_KEY, BTN_3, NULL);
|
||||
|
||||
libevdev_enable_event_type(dev, EV_REL);
|
||||
libevdev_enable_event_code(dev, EV_REL, REL_HWHEEL, NULL);
|
||||
libevdev_enable_event_code(dev, EV_REL, REL_WHEEL, NULL);
|
||||
|
||||
libevdev_enable_event_type(dev, EV_MSC);
|
||||
libevdev_enable_event_code(dev, EV_MSC, MSC_SCAN, NULL);
|
||||
}
|
||||
|
||||
rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev);
|
||||
|
||||
uinput_fd = libevdev_uinput_get_fd(uidev);
|
||||
|
||||
devnode = libevdev_uinput_get_devnode(uidev);
|
||||
|
||||
fd = open(devnode, O_RDONLY);
|
||||
}
|
||||
|
||||
void DeviceManager::testButton()
|
||||
{
|
||||
libevdev_uinput_write_event(uidev, EV_KEY, BTN_TOOL_PEN, 1);
|
||||
libevdev_uinput_write_event(uidev, EV_KEY, BTN_TOOL_PEN, 0);
|
||||
}
|
||||
|
||||
void DeviceManager::destroyDevice()
|
||||
{
|
||||
libevdev_free(dev);
|
||||
libevdev_uinput_destroy(uidev);
|
||||
close(fd);
|
||||
|
||||
/* uinput fd is managed, so make sure it did get closed */
|
||||
close(uinput_fd);
|
||||
}
|
52
devicemanager.h
Normal file
52
devicemanager.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml>
|
||||
#include <libevdev/libevdev-uinput.h>
|
||||
#include <cstdlib>
|
||||
#include <linux/input.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
class DeviceManager : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(QString name WRITE setName READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(bool direct WRITE setDirect READ direct NOTIFY directChanged)
|
||||
Q_PROPERTY(bool pad WRITE setPad READ pad NOTIFY padChanged)
|
||||
|
||||
public:
|
||||
~DeviceManager() override;
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
bool direct() const;
|
||||
void setDirect(bool direct);
|
||||
|
||||
bool pad() const;
|
||||
void setPad(bool pad);
|
||||
|
||||
public Q_SLOTS:
|
||||
void recreateDevice();
|
||||
void testButton();
|
||||
|
||||
Q_SIGNALS:
|
||||
void nameChanged();
|
||||
void directChanged();
|
||||
void padChanged();
|
||||
|
||||
private:
|
||||
void destroyDevice();
|
||||
|
||||
struct libevdev *dev = nullptr;
|
||||
struct libevdev_uinput *uidev = nullptr;
|
||||
int fd = 0, uinput_fd = 0;
|
||||
unsigned int type = 0, code = 0;
|
||||
int rc = 0;
|
||||
const char *devnode = nullptr;
|
||||
|
||||
QString m_name;
|
||||
bool m_direct = false;
|
||||
bool m_pad = false;
|
||||
};
|
12
main.cpp
Normal file
12
main.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication a(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
engine.loadFromModule(QStringLiteral("org.kde.inputfaker"), QStringLiteral("Main"));
|
||||
|
||||
return a.exec();
|
||||
}
|
66
ui/Main.qml
Normal file
66
ui/Main.qml
Normal file
|
@ -0,0 +1,66 @@
|
|||
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import org.kde.kirigami as Kirigami
|
||||
import QtQuick.Controls as Controls
|
||||
import QtQuick.Layouts
|
||||
import org.kde.inputfaker
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
Kirigami.ApplicationWindow {
|
||||
id: appWindow
|
||||
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: "InputFaker"
|
||||
|
||||
property DeviceManager deviceManager: DeviceManager {}
|
||||
|
||||
pageStack.initialPage: FormCard.FormCardPage {
|
||||
id: page
|
||||
|
||||
title: "FAKE!"
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
|
||||
FormCard.FormTextFieldDelegate {
|
||||
label: "Device Name"
|
||||
onTextChanged: deviceManager.name = text
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
text: "Direct"
|
||||
onCheckedChanged: deviceManager.direct = checked
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
text: "Pad"
|
||||
onCheckedChanged: deviceManager.pad = checked
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
text: "Apply & Re-create device"
|
||||
onClicked: deviceManager.recreateDevice()
|
||||
enabled: deviceManager.name.length > 0
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
text: "Test button"
|
||||
onClicked: deviceManager.testButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue