Single instance

This commit is contained in:
2026-10-18 16:59:51 +02:00
parent 798708b3e7
commit 74503c27dd
19 changed files with 670 additions and 99 deletions

View File

@@ -2,6 +2,7 @@
#include "uinput_keyboard.h"
#include <algorithm>
#include <cstdio>
#include <fcntl.h>
#include <initializer_list>
@@ -16,10 +17,7 @@
namespace gkeymapper::daemon {
namespace {
// Key code for a single modifier bit (the "left" variants are enough).
unsigned short modifier_code(unsigned bit) {
unsigned short modifier_key_code(unsigned bit) {
switch (bit) {
case gkeymapper::kModCtrl: return KEY_LEFTCTRL;
case gkeymapper::kModAlt: return KEY_LEFTALT;
@@ -30,7 +28,29 @@ unsigned short modifier_code(unsigned bit) {
}
}
} // namespace
std::vector<unsigned short> step_key_codes(const gkeymapper::ShortcutStep& step) {
std::vector<unsigned short> codes;
for (unsigned bit : {gkeymapper::kModCtrl, gkeymapper::kModAlt,
gkeymapper::kModShift, gkeymapper::kModSuper,
gkeymapper::kModAltGr}) {
if ((step.modifiers & bit) == 0) {
continue;
}
unsigned short code = modifier_key_code(bit);
if (code != 0) {
codes.push_back(code);
}
}
if (step.linux_key >= 0) {
// "ctrl+leftctrl" and the like would press the same code twice; keep
// the list unique so press()/release() stay balanced.
unsigned short code = static_cast<unsigned short>(step.linux_key);
if (std::find(codes.begin(), codes.end(), code) == codes.end()) {
codes.push_back(code);
}
}
return codes;
}
UinputKeyboard::~UinputKeyboard() {
close();
@@ -110,40 +130,40 @@ void UinputKeyboard::tap(unsigned short code) {
sync();
}
void UinputKeyboard::press(const std::vector<unsigned short>& codes) {
if (fd_ < 0) {
return;
}
for (unsigned short code : codes) {
key_event(code, true);
}
sync();
}
void UinputKeyboard::release(const std::vector<unsigned short>& codes) {
if (fd_ < 0) {
return;
}
// Reverse order: the modifiers go up last.
for (auto it = codes.rbegin(); it != codes.rend(); ++it) {
key_event(*it, false);
}
sync();
}
void UinputKeyboard::play(const std::vector<gkeymapper::ShortcutStep>& steps) {
if (fd_ < 0) {
return;
}
for (const gkeymapper::ShortcutStep& step : steps) {
std::vector<unsigned short> modifiers;
for (unsigned bit : {gkeymapper::kModCtrl, gkeymapper::kModAlt,
gkeymapper::kModShift, gkeymapper::kModSuper,
gkeymapper::kModAltGr}) {
if ((step.modifiers & bit) != 0) {
unsigned short code = modifier_code(bit);
if (code != 0) {
modifiers.push_back(code);
}
}
const std::vector<unsigned short> codes = step_key_codes(step);
if (codes.empty()) {
continue;
}
for (unsigned short code : modifiers) {
key_event(code, true);
}
if (step.linux_key >= 0) {
key_event(static_cast<unsigned short>(step.linux_key), true);
}
sync();
press(codes);
usleep(2000);
if (step.linux_key >= 0) {
key_event(static_cast<unsigned short>(step.linux_key), false);
}
for (auto it = modifiers.rbegin(); it != modifiers.rend(); ++it) {
key_event(*it, false);
}
sync();
release(codes);
usleep(2000);
}
}