// gKeyMapper daemon - executes the mapping configured for a G key. #include "action.h" #include #include #include 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 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(nullptr)); execl("/bin/sh", "sh", "-c", command.c_str(), static_cast(nullptr)); _exit(127); } // Parent: children are reaped by the SIGCHLD handler. } } // namespace gkeymapper::daemon