1
Fork 0

Add initial files

This commit is contained in:
Joshua Goins 2024-11-07 22:34:41 -05:00
commit 76dfebe0e8
6 changed files with 330 additions and 0 deletions

10
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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()
}
}
}
}