Single instance
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user