diff options
| author | Josh Rahm <rahm@google.com> | 2024-01-24 12:02:34 -0700 |
|---|---|---|
| committer | Josh Rahm <rahm@google.com> | 2024-01-24 12:02:34 -0700 |
| commit | 1e9b72d85ceb619f601f7c3b8f6b5c07ec88355f (patch) | |
| tree | 1ceceefdcd01e1915a8299bcfbc5146f21875be5 /extras | |
| parent | 836991558eefc53e7ff1f1db6a8faaf59aee9bb8 (diff) | |
| download | rde-1e9b72d85ceb619f601f7c3b8f6b5c07ec88355f.tar.gz rde-1e9b72d85ceb619f601f7c3b8f6b5c07ec88355f.tar.bz2 rde-1e9b72d85ceb619f601f7c3b8f6b5c07ec88355f.zip | |
Added automonitor.
Automonitor is a program that calls a bash script to configure displays
when it detects a change in the drm subsystem.
It's experimental and is not set up by default. It would need to be set
up explicitly somewhere for it to work.
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/util/automonitor/automonitor.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/extras/util/automonitor/automonitor.c b/extras/util/automonitor/automonitor.c new file mode 100644 index 0000000..f55e2f4 --- /dev/null +++ b/extras/util/automonitor/automonitor.c @@ -0,0 +1,91 @@ +#include <libudev.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/select.h> +#include <sys/wait.h> +#include <unistd.h> + +#define BLOCK_SIZE 512 +#define STRNCMP(s, cs) strncmp(s, cs, strlen(cs)) + +int execute_shell_script() { + char *home = getenv("HOME"); + + if (!home) { + fprintf(stderr, "No home environment variable."); + return 1; + } + + char script_path[4096]; + + snprintf(script_path, sizeof(script_path) - 1, + "%s/.xmonad/configure-displays", home); + + int f = fork(); + if (f == 0) { + // child process. + execl(script_path, script_path, "change", NULL); + perror("Exec failed"); + exit(1); + } else { + if (f == -1) { + perror("Forking failed"); + return 1; + } else { + waitpid(f, NULL, 0); + } + } + + return 0; +} + +int main() { + struct udev *udev; + struct udev_device *dev; + struct udev_monitor *mon; + int fd; + + udev = udev_new(); + if (!udev) { + fprintf(stderr, "Cannot create new udev context\n"); + return 1; + } + + mon = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", NULL); + udev_monitor_enable_receiving(mon); + fd = udev_monitor_get_fd(mon); + + int found_event = 0; + while (1) { + fd_set fds; + struct timeval to = {0}; + if (found_event) { + to.tv_usec = 100000; + } + int ret; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + ret = select(fd + 1, &fds, NULL, NULL, found_event ? &to : NULL); + if (ret > 0 && FD_ISSET(fd, &fds)) { + dev = udev_monitor_receive_device(mon); + if (dev) { + if (STRNCMP(udev_device_get_action(dev), "change") == 0) { + printf("I: Change detected.\n"); + found_event = 1; + // Still need to clean up some trailing detected changes. + } + } + } else if (ret == 0 && found_event) { + printf("Executing shell script hook.\n"); + if (execute_shell_script()) { + fprintf(stderr, "Unable to execute shell script."); + }; + found_event = 0; + } + } +} |