Files
gKeyMapper/daemon/config_watch.h

56 lines
1.8 KiB
C
Raw Normal View History

2026-10-17 03:53:51 +02:00
// gKeyMapper daemon - watches the mappings file for changes (inotify).
#ifndef GKEYMAPPER_DAEMON_CONFIG_WATCH_H
#define GKEYMAPPER_DAEMON_CONFIG_WATCH_H
#include <string>
namespace gkeymapper::daemon {
// Watches mappings.conf so a save in the GUI is picked up without a signal.
//
// The *directory* is watched, not the file: that also catches an atomic save
// (write a temporary file, rename it over the config) and the config appearing
// after it was deleted.
//
// poll_events() collects whatever happened since the last call and take_change()
// reports it once. Because the daemon evaluates this once per loop iteration
// (at least every read timeout, i.e. 500 ms), all events a single save produces
// collapse into one reload, and the file is complete by the time it is read
// (that is what the atomic save in shared/mapping.cpp guarantees).
//
// The daemon still accepts SIGHUP/SIGUSR1 as a fallback when inotify is
// unavailable.
class ConfigWatcher {
public:
ConfigWatcher() = default;
~ConfigWatcher();
ConfigWatcher(const ConfigWatcher&) = delete;
ConfigWatcher& operator=(const ConfigWatcher&) = delete;
// Watches the directory holding `path` (creating it if it does not exist
// yet). Returns false if inotify cannot be set up; the daemon then relies
// on signals only.
bool init(const std::string& path);
bool is_watching() const { return fd_ >= 0; }
// Consumes queued inotify events. Non-blocking and cheap; call it once per
// event-loop iteration.
void poll_events();
// True if the mappings file changed since the last call; clears the mark so
// every change is reported exactly once.
bool take_change();
private:
int fd_ = -1;
std::string directory_;
std::string name_;
bool pending_ = false;
};
} // namespace gkeymapper::daemon
#endif // GKEYMAPPER_DAEMON_CONFIG_WATCH_H