]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/commitdiff
Merge branch 'master' into manpage
authorPhillip Berndt <phillip.berndt@googlemail.com>
Sun, 17 Feb 2019 11:50:55 +0000 (12:50 +0100)
committerGitHub <noreply@github.com>
Sun, 17 Feb 2019 11:50:55 +0000 (12:50 +0100)
Makefile
README.md
autorandr.py
contrib/autorandr_launcher/autorandr_launcher.c [new file with mode: 0644]

index 989c250fb9860427b2e34c7601a08d4086250b0d..a36d2e0311855c5fd0effbfac0195c31fc79096f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,11 @@ all:
        @echo
        @echo 'E.g. "make install TARGETS='autorandr pmutils' PM_UTILS_DIR=/etc/pm/sleep.d".'
        @echo
+       @echo "An additional TARGETS variable \"launcher\" is available. This"
+       @echo "installs a launcher called \"autorandr_launcher\". The launcher"
+       @echo "is able to be run by the user and calls autorandr automatically"
+       @echo "without using udev rules."
+       @echo
        @echo "The following additional targets are available:"
        @echo
        @echo "    make deb        creates a Debian package"
@@ -134,6 +139,14 @@ uninstall_manpage:
        rm -f ${DESTDIR}/${MANDIR}/autorandr.1
        mandb -q
 
+# Rules for launcher
+install_launcher:
+       gcc -Wall contrib/autorandr_launcher/autorandr_launcher.c -o contrib/autorandr_launcher/autorandr_launcher -lxcb -lxcb-randr
+       install -D -m 755 contrib/autorandr_launcher/autorandr_launcher ${DESTDIR}${PREFIX}/bin/autorandr_launcher
+
+uninstall_launcher:
+       rm -f ${DESTDIR}${PREFIX}/bin/autorandr_launcher
+
 TARGETS=$(DEFAULT_TARGETS)
 install: $(patsubst %,install_%,$(TARGETS))
 uninstall: $(patsubst %,uninstall_%,$(TARGETS))
index df8fe4b35e9dd58c77dc93dcbaef505286fc313c..49a6949e2182faee68060688bb6ea92d7c66af08 100644 (file)
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ as root to install it.
 If you prefer to have a system wide install managed by your package manager,
 you can
 
-* Use the [aur package](https://aur.archlinux.org/packages/autorandr-git/) on Arch
+* Use the [official Arch package](https://www.archlinux.org/packages/community/any/autorandr/).
 * Use the [official Debian package](https://packages.debian.org/sid/x11/autorandr) on sid
 * Use the [ebuild from zugaina](https://gpo.zugaina.org/x11-misc/autorandr) on Gentoo.
 * Use the
index 1e980f6f7c0f7bc8f96999e36f5162a3971f5403..e11628c4959e16e2096aa325e70b3eca55617a0b 100755 (executable)
@@ -317,7 +317,7 @@ class XrandrOutput(object):
         else:
             edid = "%s-%s" % (XrandrOutput.EDID_UNAVAILABLE, match["output"])
 
-        if not match["width"]:
+        if not match["connected"]:
             options["off"] = None
         else:
             if match["mode_name"]:
@@ -656,9 +656,9 @@ def get_fb_dimensions(configuration):
         if "panning" in output.options:
             match = re.match("(?P<w>[0-9]+)x(?P<h>[0-9]+)(?:\+(?P<x>[0-9]+))?(?:\+(?P<y>[0-9]+))?.*", output.options["panning"])
             if match:
-                detail = match.groupdict()
-                o_width = int(detail.get("w")) + int(detail.get("x", "0"))
-                o_height = int(detail.get("h")) + int(detail.get("y", "0"))
+                detail = match.groupdict(default="0")
+                o_width = int(detail.get("w")) + int(detail.get("x"))
+                o_height = int(detail.get("h")) + int(detail.get("y"))
         width = max(width, o_width)
         height = max(height, o_height)
     return int(width), int(height)
diff --git a/contrib/autorandr_launcher/autorandr_launcher.c b/contrib/autorandr_launcher/autorandr_launcher.c
new file mode 100644 (file)
index 0000000..923ab98
--- /dev/null
@@ -0,0 +1,165 @@
+#include <signal.h>
+#include <xcb/xcb.h>
+#include <xcb/randr.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <time.h>
+
+// indent -kr -i8
+static int VERBOSE = 0;
+extern char **environ;
+
+static void sigterm_handler(int signum)
+{
+       signal(signum, SIG_DFL);
+       kill(getpid(), signum);
+}
+
+static void ar_log(const char *format, ...)
+{
+       va_list args;
+
+       if (!VERBOSE)
+               return;
+       va_start(args, format);
+       vprintf(format, args);
+       va_end(args);
+       fflush(stdout);
+}
+
+static int ar_launch()
+{
+       pid_t pid = fork();
+       if (pid == 0) {
+               static char *argv[] =
+                   { "/usr/bin/autorandr", "--change", "--default", "default", NULL };
+               execve(argv[0], argv, environ);
+               exit(127);
+       } else {
+               waitpid(pid, 0, 0);
+       }
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int help = 0;
+       int version = 0;
+       int daemonize = 0;
+
+       const struct option long_options[] = {
+               { "help", no_argument, &help, 1 },
+               { "daemonize", no_argument, &daemonize, 1 },
+               { "version", no_argument, &version, 1 },
+               { "verbose", no_argument, &VERBOSE, 1 },
+       };
+       static const char *short_options = "hd";
+
+       const char *help_str =
+           "Usage: autorandr_launcher [OPTION]\n"
+           "\n"
+           "Listens to X server screen change events and launches autorandr after an event occurs.\n"
+           "\n"
+           "\t-h,--help\t\t\tDisplay this help and exit\n"
+           "\t-d, --daemonize\t\t\tDaemonize program\n"
+           "\t--verbose\t\t\tOutput debugging information (prevents daemonizing)\n"
+           "\t--version\t\t\tDisplay version and exit\n";
+       const char *version_str = "v.5\n";
+
+       int option_index = 0;
+       int ch = 0;
+       while (ch != -1) {
+               ch = getopt_long(argc, argv, short_options, long_options,
+                                &option_index);
+               switch (ch) {
+               case 'h':
+                       help = 1;
+                       break;
+               case 'd':
+                       daemonize = 1;
+                       break;
+               }
+
+       }
+
+       if (help == 1) {
+               printf("%s", help_str);
+               exit(0);
+       }
+       if (version == 1) {
+               printf("%s", version_str);
+               exit(0);
+       }
+       // Check for already running daemon?
+
+       // Daemonize
+       if (daemonize == 1 && VERBOSE != 1) {
+               struct sigaction sa;
+               sa.sa_handler = sigterm_handler;
+               sigemptyset(&sa.sa_mask);
+               sa.sa_flags = 0;
+               sigaction(SIGINT, &sa, NULL);
+               sigaction(SIGTERM, &sa, NULL);
+               sigaction(SIGQUIT, &sa, NULL);
+               signal(SIGHUP, SIG_IGN);
+               daemon(0, 0);
+       }
+
+       int screenNum;
+       xcb_connection_t *c = xcb_connect(NULL, &screenNum);
+       int conn_error = xcb_connection_has_error(c);
+       if (conn_error) {
+               fprintf(stderr, "Connection error!\n");
+               exit(conn_error);
+       }
+       // Get the screen whose number is screenNum
+       const xcb_setup_t *setup = xcb_get_setup(c);
+       xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
+
+       // we want the screen at index screenNum of the iterator
+       for (int i = 0; i < screenNum; ++i) {
+               xcb_screen_next(&iter);
+       }
+       xcb_screen_t *default_screen = iter.data;
+       ar_log("Connected to server\n");
+
+       // Subscribe to screen change events
+       xcb_randr_select_input(c, default_screen->root,
+                              XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
+       xcb_flush(c);
+
+       xcb_timestamp_t last_timestamp = (xcb_timestamp_t) 0;
+       time_t last_time = time(NULL);
+       while (1) {
+
+               ar_log("Waiting for event\n");
+               xcb_generic_event_t *evt = xcb_wait_for_event(c);
+               // ar_log("Event type: %" PRIu8 "\n", evt->response_type);
+               // ar_log("screen change masked: %" PRIu8 "\n",
+               //       evt->response_type &
+               //       XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
+
+               if (evt->response_type &
+                   XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE) {
+                       xcb_randr_screen_change_notify_event_t *randr_evt =
+                           (xcb_randr_screen_change_notify_event_t *) evt;
+                       time_t evt_time = time(NULL);
+                       if ((randr_evt->timestamp > last_timestamp)
+                           && (evt_time > last_time + 1)) {
+                               ar_log("Launch autorandr!\n");
+                               ar_launch();
+                               last_time = evt_time;
+                               last_timestamp = randr_evt->timestamp;
+                       }
+               }
+
+               free(evt);
+       }
+
+}