69 lines
2.1 KiB
C++
69 lines
2.1 KiB
C++
// gKeyMapper daemon - executes the mapping configured for a G key.
|
|
|
|
#include "action.h"
|
|
|
|
#include <cstdio>
|
|
#include <vector>
|
|
|
|
#include <unistd.h>
|
|
|
|
namespace gkeymapper::daemon {
|
|
|
|
bool ActionRunner::init() {
|
|
keymap_.init();
|
|
if (!keyboard_.open()) {
|
|
std::fprintf(stderr,
|
|
"gkeymapper-daemon: no virtual keyboard, 'key' mappings disabled\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ActionRunner::run(const gkeymapper::Mapping& mapping) {
|
|
switch (mapping.type) {
|
|
case gkeymapper::ActionType::Key: {
|
|
std::vector<gkeymapper::ShortcutStep> steps;
|
|
// Resolve key names through the active keyboard layout.
|
|
gkeymapper::KeyResolver resolve = [this](const std::string& name) {
|
|
return keymap_.key_code(name);
|
|
};
|
|
if (!gkeymapper::parse_shortcut(mapping.target, steps, resolve)) {
|
|
std::fprintf(stderr, "gkeymapper-daemon: invalid shortcut '%s'\n",
|
|
mapping.target.c_str());
|
|
return;
|
|
}
|
|
keyboard_.play(steps);
|
|
break;
|
|
}
|
|
case gkeymapper::ActionType::Command:
|
|
run_command(mapping.target);
|
|
break;
|
|
case gkeymapper::ActionType::Disabled:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ActionRunner::run_command(const std::string& command) {
|
|
if (command.empty()) {
|
|
return;
|
|
}
|
|
|
|
pid_t pid = fork();
|
|
if (pid < 0) {
|
|
std::fprintf(stderr, "gkeymapper-daemon: fork failed\n");
|
|
return;
|
|
}
|
|
if (pid == 0) {
|
|
// The field may be a bare program path (which may contain spaces) or a
|
|
// command line with arguments. Try the path directly first, then fall
|
|
// back to a shell so arguments and quoting also work.
|
|
execlp(command.c_str(), command.c_str(), static_cast<char*>(nullptr));
|
|
execl("/bin/sh", "sh", "-c", command.c_str(), static_cast<char*>(nullptr));
|
|
_exit(127);
|
|
}
|
|
// Parent: children are reaped by the SIGCHLD handler.
|
|
}
|
|
|
|
} // namespace gkeymapper::daemon
|