From 1e9b72d85ceb619f601f7c3b8f6b5c07ec88355f Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 24 Jan 2024 12:02:34 -0700 Subject: 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. --- extras/util/automonitor/automonitor.c | 91 +++++++++++++++++++++++++++++++++++ install.sh | 6 +++ 2 files changed, 97 insertions(+) create mode 100644 extras/util/automonitor/automonitor.c 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 +#include +#include +#include +#include +#include +#include +#include + +#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; + } + } +} diff --git a/install.sh b/install.sh index f862fe8..f0bfa14 100755 --- a/install.sh +++ b/install.sh @@ -15,6 +15,12 @@ cc -o \ xmobar/extras/battery/battery.c \ -lm +cc -o \ + build/extras/HOME/.xmonad/automonitor \ + extras/util/automonitor/automonitor.c \ + -ludev + + ln -sf "$(stack path --local-install-root)/bin/xmobar-weather" build/extras/HOME/.xmonad/xmobar-weather ln -sf "$(stack path --local-install-root)/bin/xmobar-weather" extras/HOME/.xmonad/xmobar-weather -- cgit