diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | xbacklight.c | 257 |
2 files changed, 157 insertions, 102 deletions
diff --git a/configure.ac b/configure.ac index 2c67604..87c7b26 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ XORG_DEFAULT_OPTIONS AC_CONFIG_HEADERS([config.h]) # Checks for pkg-config packages -PKG_CHECK_MODULES(XRANDR, xrandr >= 1.2.0 x11) +PKG_CHECK_MODULES(XRANDR, [xcb-randr >= 1.2 xcb-atom xcb-aux xcb]) AC_CONFIG_FILES([ Makefile diff --git a/xbacklight.c b/xbacklight.c index 9b68ce8..2189095 100644 --- a/xbacklight.c +++ b/xbacklight.c @@ -21,9 +21,11 @@ */ #include <stdio.h> #include <stdlib.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/extensions/Xrandr.h> + +#include <xcb/xcb.h> +#include <xcb/xcb_util.h> +#include <xcb/xproto.h> +#include <xcb/randr.h> #include <ctype.h> #include <string.h> @@ -33,7 +35,7 @@ typedef enum { Get, Set, Inc, Dec } op_t; static char *program_name; -static Atom backlight, backlight_new, backlight_legacy; +static xcb_atom_t backlight, backlight_new, backlight_legacy; static void usage (void) @@ -53,58 +55,75 @@ usage (void) } static long -backlight_get (Display *dpy, RROutput output) +backlight_get (xcb_connection_t *conn, xcb_randr_output_t output) { - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop; - Atom actual_type; - int actual_format; - long value; + xcb_generic_error_t *error; + xcb_randr_get_output_property_reply_t *prop_reply = NULL; + xcb_randr_get_output_property_cookie_t prop_cookie; + long value; backlight = backlight_new; - if (!backlight || - XRRGetOutputProperty (dpy, output, backlight, - 0, 4, False, False, None, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop) != Success) { - backlight = backlight_legacy; - if (!backlight || - XRRGetOutputProperty (dpy, output, backlight, - 0, 4, False, False, None, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop) != Success) - return -1; + if (backlight != XCB_ATOM_NONE) { + prop_cookie = xcb_randr_get_output_property (conn, output, + backlight, XCB_ATOM_NONE, + 0, 4, 0, 0); + prop_reply = xcb_randr_get_output_property_reply (conn, prop_cookie, &error); + if (error != NULL || prop_reply == NULL) { + backlight = backlight_legacy; + if (backlight != XCB_ATOM_NONE) { + prop_cookie = xcb_randr_get_output_property (conn, output, + backlight, XCB_ATOM_NONE, + 0, 4, 0, 0); + prop_reply = xcb_randr_get_output_property_reply (conn, prop_cookie, &error); + if (error != NULL || prop_reply == NULL) { + return -1; + } + } + } } - if (actual_type != XA_INTEGER || nitems != 1 || actual_format != 32) + if (prop_reply == NULL || + prop_reply->type != XCB_ATOM_INTEGER || + prop_reply->num_items != 1 || + prop_reply->format != 32) { value = -1; - else - value = *((long *) prop); - XFree (prop); + } else { + value = *((long *) xcb_randr_get_output_property_data (prop_reply)); + } + + free (prop_reply); return value; } static void -backlight_set (Display *dpy, RROutput output, long value) +backlight_set (xcb_connection_t *conn, xcb_randr_output_t output, long value) { - XRRChangeOutputProperty (dpy, output, backlight, XA_INTEGER, 32, - PropModeReplace, (unsigned char *) &value, 1); + xcb_randr_change_output_property (conn, output, backlight, XCB_ATOM_INTEGER, + 32, XCB_PROP_MODE_REPLACE, + 1, (unsigned char *)&value); } int main (int argc, char **argv) { char *dpy_name = NULL; - Display *dpy; - int screen; - int major, minor; op_t op = Get; int value = 0; int i; int total_time = 200; /* ms */ int steps = 20; + xcb_connection_t *conn; + xcb_generic_error_t *error; + + xcb_randr_query_version_cookie_t ver_cookie; + xcb_randr_query_version_reply_t *ver_reply; + + xcb_intern_atom_cookie_t backlight_cookie[2]; + xcb_intern_atom_reply_t *backlight_reply; + + xcb_screen_iterator_t iter; + program_name = argv[0]; for (i = 1; i < argc; i++) @@ -177,97 +196,133 @@ main (int argc, char **argv) } usage (); } - dpy = XOpenDisplay (dpy_name); - if (!dpy) - { - fprintf (stderr, "Cannot open display \"%s\"\n", - XDisplayName (dpy_name)); + conn = xcb_connect (dpy_name, NULL); + ver_cookie = xcb_randr_query_version (conn, 1, 2); + ver_reply = xcb_randr_query_version_reply (conn, ver_cookie, &error); + if (error != NULL || ver_reply == NULL) { + int ec = error ? error->error_code : -1; + fprintf (stderr, "RANDR Query Version returned error %d\n", ec); exit (1); } - if (!XRRQueryVersion (dpy, &major, &minor)) - { - fprintf (stderr, "RandR extension missing\n"); + if (ver_reply->major_version != 1 || + ver_reply->minor_version < 2) { + fprintf (stderr, "RandR version %d.%d too old\n", + ver_reply->major_version, ver_reply->minor_version); exit (1); } - if (major < 1 || (major == 1 && minor < 2)) - { - fprintf (stderr, "RandR version %d.%d too old\n", major, minor); + free (ver_reply); + + backlight_cookie[0] = xcb_intern_atom (conn, 1, strlen("Backlight"), "Backlight"); + backlight_cookie[1] = xcb_intern_atom (conn, 1, strlen("BACKLIGHT"), "BACKLIGHT"); + + backlight_reply = xcb_intern_atom_reply (conn, backlight_cookie[0], &error); + if (error != NULL || backlight_reply == NULL) { + int ec = error ? error->error_code : -1; + fprintf (stderr, "Intern Atom returned error %d\n", ec); exit (1); } - backlight_new = XInternAtom (dpy, "Backlight", True); - backlight_legacy = XInternAtom (dpy, "BACKLIGHT", True); - if (backlight_new == None && backlight_legacy == None) - { + backlight_new = backlight_reply->atom; + free (backlight_reply); + + backlight_reply = xcb_intern_atom_reply (conn, backlight_cookie[1], &error); + if (error != NULL || backlight_reply == NULL) { + int ec = error ? error->error_code : -1; + fprintf (stderr, "Intern Atom returned error %d\n", ec); + exit (1); + } + + backlight_legacy = backlight_reply->atom; + free (backlight_reply); + + if (backlight_new == XCB_NONE && backlight_legacy == XCB_NONE) { fprintf (stderr, "No outputs have backlight property\n"); exit (1); } - for (screen = 0; screen < ScreenCount (dpy); screen++) - { - Window root = RootWindow (dpy, screen); - XRRScreenResources *resources = XRRGetScreenResources (dpy, root); - int o; - - if (!resources) continue; - for (o = 0; o < resources->noutput; o++) + + iter = xcb_setup_roots_iterator (xcb_get_setup (conn)); + while (iter.rem) { + xcb_screen_t *screen = iter.data; + xcb_window_t root = screen->root; + xcb_randr_output_t *outputs; + + xcb_randr_get_screen_resources_cookie_t resources_cookie; + xcb_randr_get_screen_resources_reply_t *resources_reply; + + resources_cookie = xcb_randr_get_screen_resources (conn, root); + resources_reply = xcb_randr_get_screen_resources_reply (conn, resources_cookie, &error); + if (error != NULL || resources_reply == NULL) { + int ec = error ? error->error_code : -1; + fprintf (stderr, "RANDR Get Screen Resources returned error %d\n", ec); + continue; + } + + outputs = xcb_randr_get_screen_resources_outputs (resources_reply); + for (int o = 0; o < resources_reply->num_outputs; o++) { - RROutput output = resources->outputs[o]; - XRRPropertyInfo *info; + xcb_randr_output_t output = outputs[o]; double cur, new, step; double min, max; double set; - cur = backlight_get (dpy, output); + cur = backlight_get (conn, output); if (cur != -1) { - info = XRRQueryOutputProperty (dpy, output, backlight); - if (info) - { - if (info->range && info->num_values == 2) - { - min = info->values[0]; - max = info->values[1]; - if (op == Get) { - printf ("%f\n", (cur - min) * 100 / (max - min)); - } else { - set = value * (max - min) / 100; - switch (op) { - case Set: - new = min + set; - break; - case Inc: - new = cur + set; - break; - case Dec: - new = cur - set; - break; - default: - XSync (dpy, False); - return 1; - } - if (new > max) new = max; - if (new < min) new = min; - step = (new - cur) / steps; - for (i = 0; i < steps && step != 0; i++) - { - if (i == steps - 1) - cur = new; - else - cur += step; - backlight_set (dpy, output, (long) cur); - XFlush (dpy); - usleep (total_time * 1000 / steps); - } + xcb_randr_query_output_property_cookie_t prop_cookie; + xcb_randr_query_output_property_reply_t *prop_reply; + + prop_cookie = xcb_randr_query_output_property (conn, output, backlight); + prop_reply = xcb_randr_query_output_property_reply (conn, prop_cookie, &error); + + if (error != NULL || prop_reply == NULL) continue; + + if (prop_reply->range && + xcb_randr_query_output_property_valid_values_length (prop_reply) == 2) { + int32_t *values = xcb_randr_query_output_property_valid_values (prop_reply); + min = values[0]; + max = values[1]; + + if (op == Get) { + printf ("%f\n", (cur - min) * 100 / (max - min)); + } else { + set = value * (max - min) / 100; + switch (op) { + case Set: + new = min + set; + break; + case Inc: + new = cur + set; + break; + case Dec: + new = cur - set; + break; + default: + xcb_aux_sync (conn); + return 1; + } + if (new > max) new = max; + if (new < min) new = min; + step = (new - cur) / steps; + for (i = 0; i < steps && step != 0; i++) + { + if (i == steps - 1) + cur = new; + else + cur += step; + backlight_set (conn, output, (long) cur); + xcb_flush (conn); + usleep (total_time * 1000 / steps); } } - XFree (info); } + free (prop_reply); } } - - XRRFreeScreenResources (resources); + + free (resources_reply); + xcb_screen_next (&iter); } - XSync (dpy, False); + xcb_aux_sync (conn); return 0; } |