aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/randr.c295
-rw-r--r--src/randr.h23
-rw-r--r--src/redshift.c191
-rw-r--r--src/vidmode.c75
-rw-r--r--src/vidmode.h13
5 files changed, 395 insertions, 202 deletions
diff --git a/src/randr.c b/src/randr.c
index 99ac9ec..b67484c 100644
--- a/src/randr.c
+++ b/src/randr.c
@@ -19,169 +19,270 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <xcb/xcb.h>
#include <xcb/randr.h>
+#include "randr.h"
#include "colorramp.h"
+#define RANDR_VERSION_MAJOR 1
+#define RANDR_VERSION_MINOR 3
+
+
int
-randr_check_extension()
+randr_init(randr_state_t *state, int screen_num)
{
xcb_generic_error_t *error;
/* Open X server connection */
- xcb_connection_t *conn = xcb_connect(NULL, NULL);
+ int preferred_screen;
+ state->conn = xcb_connect(NULL, &preferred_screen);
+
+ if (screen_num < 0) screen_num = preferred_screen;
/* Query RandR version */
xcb_randr_query_version_cookie_t ver_cookie =
- xcb_randr_query_version(conn, 1, 3);
+ xcb_randr_query_version(state->conn, RANDR_VERSION_MAJOR,
+ RANDR_VERSION_MINOR);
xcb_randr_query_version_reply_t *ver_reply =
- xcb_randr_query_version_reply(conn, ver_cookie, &error);
+ xcb_randr_query_version_reply(state->conn, ver_cookie, &error);
if (error) {
fprintf(stderr, "RANDR Query Version, error: %d\n",
error->error_code);
- xcb_disconnect(conn);
+ xcb_disconnect(state->conn);
return -1;
}
- if (ver_reply->major_version < 1 || ver_reply->minor_version < 3) {
+ if (ver_reply->major_version < RANDR_VERSION_MAJOR ||
+ ver_reply->minor_version < RANDR_VERSION_MINOR) {
fprintf(stderr, "Unsupported RANDR version (%u.%u)\n",
ver_reply->major_version, ver_reply->minor_version);
free(ver_reply);
- xcb_disconnect(conn);
+ xcb_disconnect(state->conn);
return -1;
}
free(ver_reply);
- /* Close connection */
- xcb_disconnect(conn);
+ /* Get screen */
+ const xcb_setup_t *setup = xcb_get_setup(state->conn);
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
+ state->screen = NULL;
- return 0;
-}
+ for (int i = 0; iter.rem > 0; i++) {
+ if (i == screen_num) {
+ state->screen = iter.data;
+ break;
+ }
+ xcb_screen_next(&iter);
+ }
-static int
-randr_crtc_set_temperature(xcb_connection_t *conn, xcb_randr_crtc_t crtc,
- int temp, float gamma[3])
-{
- xcb_generic_error_t *error;
+ if (state->screen == NULL) {
+ fprintf(stderr, "Screen %i could not be found.\n",
+ screen_num);
+ xcb_disconnect(state->conn);
+ return -1;
+ }
- /* Request size of gamma ramps */
- xcb_randr_get_crtc_gamma_size_cookie_t gamma_size_cookie =
- xcb_randr_get_crtc_gamma_size(conn, crtc);
- xcb_randr_get_crtc_gamma_size_reply_t *gamma_size_reply =
- xcb_randr_get_crtc_gamma_size_reply(conn, gamma_size_cookie,
- &error);
+ /* Get list of CRTCs for the screen */
+ xcb_randr_get_screen_resources_current_cookie_t res_cookie =
+ xcb_randr_get_screen_resources_current(state->conn,
+ state->screen->root);
+ xcb_randr_get_screen_resources_current_reply_t *res_reply =
+ xcb_randr_get_screen_resources_current_reply(state->conn,
+ res_cookie,
+ &error);
if (error) {
- fprintf(stderr, "RANDR Get CRTC Gamma Size, error: %d\n",
- error->error_code);
+ fprintf(stderr, "RANDR Get Screen Resources Current,"
+ " error: %d\n", error->error_code);
+ xcb_disconnect(state->conn);
return -1;
}
- int gamma_ramp_size = gamma_size_reply->size;
+ state->crtc_count = res_reply->num_crtcs;
+ state->crtcs = malloc(state->crtc_count * sizeof(randr_crtc_state_t));
+ if (state->crtcs == NULL) {
+ perror("malloc");
+ xcb_disconnect(state->conn);
+ return -1;
+ }
- free(gamma_size_reply);
+ xcb_randr_crtc_t *crtcs =
+ xcb_randr_get_screen_resources_current_crtcs(res_reply);
- if (gamma_ramp_size == 0) {
- fprintf(stderr, "Gamma ramp size too small: %i\n",
- gamma_ramp_size);
- return -1;
+ /* Save CRTC identifier in state */
+ for (int i = 0; i < state->crtc_count; i++) {
+ state->crtcs[i].crtc = crtcs[i];
}
- /* Create new gamma ramps */
- uint16_t *gamma_ramps = malloc(3*gamma_ramp_size*sizeof(uint16_t));
- if (gamma_ramps == NULL) abort();
+ free(res_reply);
- uint16_t *gamma_r = &gamma_ramps[0*gamma_ramp_size];
- uint16_t *gamma_g = &gamma_ramps[1*gamma_ramp_size];
- uint16_t *gamma_b = &gamma_ramps[2*gamma_ramp_size];
+ /* Save size and gamma ramps of all CRTCs.
+ Current gamma ramps are saved so we can restore them
+ at program exit. */
+ for (int i = 0; i < state->crtc_count; i++) {
+ xcb_randr_crtc_t crtc = state->crtcs[i].crtc;
+
+ /* Request size of gamma ramps */
+ xcb_randr_get_crtc_gamma_size_cookie_t gamma_size_cookie =
+ xcb_randr_get_crtc_gamma_size(state->conn, crtc);
+ xcb_randr_get_crtc_gamma_size_reply_t *gamma_size_reply =
+ xcb_randr_get_crtc_gamma_size_reply(state->conn,
+ gamma_size_cookie,
+ &error);
+
+ if (error) {
+ fprintf(stderr, "RANDR Get CRTC Gamma Size,"
+ " error: %d\n", error->error_code);
+ xcb_disconnect(state->conn);
+ return -1;
+ }
- colorramp_fill(gamma_r, gamma_g, gamma_b, gamma_ramp_size,
- temp, gamma);
+ unsigned int ramp_size = gamma_size_reply->size;
+ state->crtcs[i].ramp_size = ramp_size;
- /* Set new gamma ramps */
- xcb_void_cookie_t gamma_set_cookie =
- xcb_randr_set_crtc_gamma_checked(conn, crtc, gamma_ramp_size,
- gamma_r, gamma_g, gamma_b);
- error = xcb_request_check(conn, gamma_set_cookie);
+ free(gamma_size_reply);
- if (error) {
- fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n",
- error->error_code);
- free(gamma_ramps);
- return -1;
- }
+ if (ramp_size == 0) {
+ fprintf(stderr, "Gamma ramp size too small: %i\n",
+ ramp_size);
+ xcb_disconnect(state->conn);
+ return -1;
+ }
+
+ /* Request current gamma ramps */
+ xcb_randr_get_crtc_gamma_cookie_t gamma_get_cookie =
+ xcb_randr_get_crtc_gamma(state->conn, crtc);
+ xcb_randr_get_crtc_gamma_reply_t *gamma_get_reply =
+ xcb_randr_get_crtc_gamma_reply(state->conn,
+ gamma_get_cookie,
+ &error);
+
+ if (error) {
+ fprintf(stderr, "RANDR Get CRTC Gamma, error: %d\n",
+ error->error_code);
+ xcb_disconnect(state->conn);
+ return -1;
+ }
- free(gamma_ramps);
+ uint16_t *gamma_r =
+ xcb_randr_get_crtc_gamma_red(gamma_get_reply);
+ uint16_t *gamma_g =
+ xcb_randr_get_crtc_gamma_green(gamma_get_reply);
+ uint16_t *gamma_b =
+ xcb_randr_get_crtc_gamma_blue(gamma_get_reply);
+
+ /* Allocate space for saved gamma ramps */
+ state->crtcs[i].saved_ramps =
+ malloc(3*ramp_size*sizeof(uint16_t));
+ if (state->crtcs[i].saved_ramps == NULL) {
+ perror("malloc");
+ free(gamma_get_reply);
+ xcb_disconnect(state->conn);
+ return -1;
+ }
+
+ /* Copy gamma ramps into CRTC state */
+ memcpy(&state->crtcs[i].saved_ramps[0*ramp_size], gamma_r,
+ ramp_size*sizeof(uint16_t));
+ memcpy(&state->crtcs[i].saved_ramps[1*ramp_size], gamma_g,
+ ramp_size*sizeof(uint16_t));
+ memcpy(&state->crtcs[i].saved_ramps[2*ramp_size], gamma_b,
+ ramp_size*sizeof(uint16_t));
+
+ free(gamma_get_reply);
+ }
return 0;
}
-int
-randr_set_temperature(int screen_num, int temp, float gamma[3])
+void
+randr_restore(randr_state_t *state)
{
xcb_generic_error_t *error;
- /* Open X server connection */
- int preferred_screen;
- xcb_connection_t *conn = xcb_connect(NULL, &preferred_screen);
-
- if (screen_num < 0) screen_num = preferred_screen;
-
- /* Get screen */
- const xcb_setup_t *setup = xcb_get_setup(conn);
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
- xcb_screen_t *screen = NULL;
-
- for (int i = 0; iter.rem > 0; i++) {
- if (i == screen_num) {
- screen = iter.data;
- break;
+ /* Restore CRTC gamma ramps */
+ for (int i = 0; i < state->crtc_count; i++) {
+ xcb_randr_crtc_t crtc = state->crtcs[i].crtc;
+
+ unsigned int ramp_size = state->crtcs[i].ramp_size;
+ uint16_t *gamma_r = &state->crtcs[i].saved_ramps[0*ramp_size];
+ uint16_t *gamma_g = &state->crtcs[i].saved_ramps[1*ramp_size];
+ uint16_t *gamma_b = &state->crtcs[i].saved_ramps[2*ramp_size];
+
+ /* Set gamma ramps */
+ xcb_void_cookie_t gamma_set_cookie =
+ xcb_randr_set_crtc_gamma_checked(state->conn, crtc,
+ ramp_size, gamma_r,
+ gamma_g, gamma_b);
+ error = xcb_request_check(state->conn, gamma_set_cookie);
+
+ if (error) {
+ fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n"
+ "Unable to restore CRTC %i\n",
+ error->error_code, i);
}
- xcb_screen_next(&iter);
}
+}
- if (screen == NULL) {
- fprintf(stderr, "Screen %i could not be found.\n",
- screen_num);
- xcb_disconnect(conn);
- return -1;
+void
+randr_free(randr_state_t *state)
+{
+ /* Free CRTC state */
+ for (int i = 0; i < state->crtc_count; i++) {
+ free(state->crtcs[i].saved_ramps);
}
+ free(state->crtcs);
- /* Get list of CRTCs for the screen */
- xcb_randr_get_screen_resources_current_cookie_t res_cookie =
- xcb_randr_get_screen_resources_current(conn, screen->root);
- xcb_randr_get_screen_resources_current_reply_t *res_reply =
- xcb_randr_get_screen_resources_current_reply(conn, res_cookie,
- &error);
+ /* Close connection */
+ xcb_disconnect(state->conn);
+}
- if (error) {
- fprintf(stderr, "RANDR Get Screen Resources Current,"
- " error: %d\n", error->error_code);
- xcb_disconnect(conn);
- return -1;
- }
+int
+randr_set_temperature(randr_state_t *state, int temp, float gamma[3])
+{
+ xcb_generic_error_t *error;
- xcb_randr_crtc_t *crtcs =
- xcb_randr_get_screen_resources_current_crtcs(res_reply);
+ /* Set temperature on all CRTCs */
+ for (int i = 0; i < state->crtc_count; i++) {
+ xcb_randr_crtc_t crtc = state->crtcs[i].crtc;
+ unsigned int ramp_size = state->crtcs[i].ramp_size;
- for (int i = 0; i < res_reply->num_crtcs; i++) {
- int r = randr_crtc_set_temperature(conn, crtcs[i],
- temp, gamma);
- if (r < 0) {
- fprintf(stderr, "WARNING: Unable to adjust"
- " CRTC %i.\n", i);
+ /* Create new gamma ramps */
+ uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t));
+ if (gamma_ramps == NULL) {
+ perror("malloc");
+ return -1;
}
- }
- free(res_reply);
+ uint16_t *gamma_r = &gamma_ramps[0*ramp_size];
+ uint16_t *gamma_g = &gamma_ramps[1*ramp_size];
+ uint16_t *gamma_b = &gamma_ramps[2*ramp_size];
+
+ colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size,
+ temp, gamma);
+
+ /* Set new gamma ramps */
+ xcb_void_cookie_t gamma_set_cookie =
+ xcb_randr_set_crtc_gamma_checked(state->conn, crtc,
+ ramp_size, gamma_r,
+ gamma_g, gamma_b);
+ error = xcb_request_check(state->conn, gamma_set_cookie);
+
+ if (error) {
+ fprintf(stderr, "RANDR Set CRTC Gamma, error: %d\n",
+ error->error_code);
+ free(gamma_ramps);
+ return -1;
+ }
- /* Close connection */
- xcb_disconnect(conn);
+ free(gamma_ramps);
+ }
return 0;
}
diff --git a/src/randr.h b/src/randr.h
index d03f766..404bc29 100644
--- a/src/randr.h
+++ b/src/randr.h
@@ -20,7 +20,26 @@
#ifndef _REDSHIFT_RANDR_H
#define _REDSHIFT_RANDR_H
-int randr_check_extension();
-int randr_set_temperature(int screen_num, int temp, float gamma[3]);
+#include <xcb/xcb.h>
+#include <xcb/randr.h>
+
+typedef struct {
+ xcb_randr_crtc_t crtc;
+ unsigned int ramp_size;
+ uint16_t *saved_ramps;
+} randr_crtc_state_t;
+
+typedef struct {
+ xcb_connection_t *conn;
+ xcb_screen_t *screen;
+ unsigned int crtc_count;
+ randr_crtc_state_t *crtcs;
+} randr_state_t;
+
+
+int randr_init(randr_state_t *state, int screen_num);
+void randr_free(randr_state_t *state);
+void randr_restore(randr_state_t *state);
+int randr_set_temperature(randr_state_t *state, int temp, float gamma[3]);
#endif /* ! _REDSHIFT_RANDR_H */
diff --git a/src/redshift.c b/src/redshift.c
index c9904d2..d34009f 100644
--- a/src/redshift.c
+++ b/src/redshift.c
@@ -28,9 +28,14 @@
#include <time.h>
#include <math.h>
#include <locale.h>
+#include <sys/signal.h>
#include "solar.h"
+#if !(defined(ENABLE_RANDR) || defined(ENABLE_VIDMODE))
+# error "At least one of RANDR or VidMode must be enabled."
+#endif
+
#ifdef ENABLE_RANDR
# include "randr.h"
#endif
@@ -39,9 +44,16 @@
# include "vidmode.h"
#endif
-#if !(defined(ENABLE_RANDR) || defined(ENABLE_VIDMODE))
-# error "Either RANDR or VidMode must be enabled."
+
+/* Union of state data for gamma adjustment methods */
+typedef union {
+#ifdef ENABLE_RANDR
+ randr_state_t randr;
#endif
+#ifdef ENABLE_VIDMODE
+ vidmode_state_t vidmode;
+#endif
+} gamma_state_t;
/* Bounds for parameters. */
@@ -88,6 +100,60 @@
#define DEG_CHAR 0xb0
+static volatile sig_atomic_t exiting = 0;
+
+/* Signal handler for exit signals */
+static void
+sigexit(int signo)
+{
+ exiting = 1;
+}
+
+static void
+gamma_state_restore(gamma_state_t *state, int use_randr)
+{
+#ifdef ENABLE_RANDR
+ if (use_randr == 1) randr_restore(&state->randr);
+#endif
+
+#ifdef ENABLE_VIDMODE
+ if (use_randr == 0) vidmode_restore(&state->vidmode);
+#endif
+}
+
+static void
+gamma_state_free(gamma_state_t *state, int use_randr)
+{
+#ifdef ENABLE_RANDR
+ if (use_randr == 1) randr_free(&state->randr);
+#endif
+
+#ifdef ENABLE_VIDMODE
+ if (use_randr == 0) vidmode_free(&state->vidmode);
+#endif
+}
+
+static int
+gamma_state_set_temperature(gamma_state_t *state, int use_randr,
+ int temp, float gamma[3])
+{
+#ifdef ENABLE_RANDR
+ if (use_randr == 1) {
+ return randr_set_temperature(&state->randr, temp, gamma);
+ }
+#endif
+
+#ifdef ENABLE_VIDMODE
+ if (use_randr == 0) {
+ return vidmode_set_temperature(&state->vidmode, temp, gamma);
+ }
+#endif
+
+ return -1;
+}
+
+
+/* Calculate color temperature for the specified solar elevation. */
static int
calculate_temp(double elevation, int temp_day, int temp_night,
int verbose)
@@ -112,58 +178,6 @@ calculate_temp(double elevation, int temp_day, int temp_night,
return temp;
}
-static int
-adjust_temperature(int screen_num, int use_randr, int temp, float gamma[3])
-{
- /* Set color temperature */
- int failed = 0;
-#ifdef ENABLE_RANDR
- if (use_randr) {
- /* Check RANDR extension. */
- int r = randr_check_extension();
- if (r < 0) {
- fprintf(stderr, "RANDR 1.3 extension is"
- " not available.\n");
- failed = 1;
- } else {
- r = randr_set_temperature(screen_num, temp, gamma);
- if (r < 0) {
- fprintf(stderr, "Unable to set color"
- " temperature with RANDR.\n");
- failed = 1;
- }
- }
- }
-#endif
-
-#ifdef ENABLE_VIDMODE
- if (!use_randr || failed) {
- failed = 0;
- /* Check VidMode extension */
- int r = vidmode_check_extension();
- if (r < 0) {
- fprintf(stderr, "VidMode extension is"
- " not available.\n");
- failed = 1;
- } else {
- r = vidmode_set_temperature(screen_num, temp, gamma);
- if (r < 0) {
- fprintf(stderr, "Unable to set color"
- " temperature with VidMode.\n");
- failed = 1;
- }
- }
- }
-#endif
-
- if (failed) {
- fprintf(stderr, "Color temperature adjustment failed.\n");
- return -1;
- }
-
- return 0;
-}
-
int
main(int argc, char *argv[])
@@ -183,18 +197,13 @@ main(int argc, char *argv[])
int temp_day = DEFAULT_DAY_TEMP;
int temp_night = DEFAULT_NIGHT_TEMP;
float gamma[3] = { DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA };
- int use_randr = 1;
+ int use_randr = -1;
int screen_num = -1;
int init_trans = 1;
int one_shot = 0;
int verbose = 0;
char *s;
-#ifndef ENABLE_RANDR
- /* Don't use RANDR if it has been disabled. */
- use_randr = 0;
-#endif
-
/* Parse arguments. */
int opt;
while ((opt = getopt(argc, argv, "g:hl:m:ors:t:v")) != -1) {
@@ -345,12 +354,46 @@ main(int argc, char *argv[])
gamma[0], gamma[1], gamma[2]);
}
+ /* Initialize gamma adjustment method. If use_randr is negative
+ try all methods until one that works is found. */
+ gamma_state_t state;
+#ifdef ENABLE_RANDR
+ if (use_randr < 0 || use_randr == 1) {
+ /* Initialize RANDR state */
+ r = randr_init(&state.randr, screen_num);
+ if (r < 0) {
+ fprintf(stderr, "Initialization of RANDR failed.\n");
+ if (use_randr < 0) {
+ fprintf(stderr, "Trying other method...\n");
+ } else {
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ use_randr = 1;
+ }
+ }
+#endif
+
+#ifdef ENABLE_VIDMODE
+ if (use_randr < 0 || use_randr == 0) {
+ /* Initialize VidMode state */
+ r = vidmode_init(&state.vidmode, screen_num);
+ if (r < 0) {
+ fprintf(stderr, "Initialization of VidMode failed.\n");
+ exit(EXIT_FAILURE);
+ } else {
+ use_randr = 0;
+ }
+ }
+#endif
+
if (one_shot) {
/* Current angular elevation of the sun */
struct timespec now;
r = clock_gettime(CLOCK_REALTIME, &now);
if (r < 0) {
perror("clock_gettime");
+ gamma_state_free(&state, use_randr);
exit(EXIT_FAILURE);
}
@@ -368,9 +411,11 @@ main(int argc, char *argv[])
if (verbose) printf("Color temperature: %uK\n", temp);
/* Adjust temperature */
- r = adjust_temperature(screen_num, use_randr, temp, gamma);
+ r = gamma_state_set_temperature(&state, use_randr,
+ temp, gamma);
if (r < 0) {
fprintf(stderr, "Temperature adjustment failed.\n");
+ gamma_state_free(&state, use_randr);
exit(EXIT_FAILURE);
}
} else {
@@ -379,18 +424,31 @@ main(int argc, char *argv[])
r = clock_gettime(CLOCK_REALTIME, &short_trans_end);
if (r < 0) {
perror("clock_gettime");
+ gamma_state_free(&state, use_randr);
exit(EXIT_FAILURE);
}
int short_trans_len = 10;
short_trans_end.tv_sec += short_trans_len;
- while (1) {
+ /* Install signal handler for SIGINT */
+ struct sigaction sigact;
+ sigset_t sigset;
+
+ sigemptyset(&sigset);
+ sigact.sa_handler = sigexit;
+ sigact.sa_mask = sigset;
+ sigact.sa_flags = 0;
+ sigaction(SIGINT, &sigact, NULL);
+
+ /* Continously adjust color temperature */
+ while (!exiting) {
/* Current angular elevation of the sun */
struct timespec now;
r = clock_gettime(CLOCK_REALTIME, &now);
if (r < 0) {
perror("clock_gettime");
+ gamma_state_free(&state, use_randr);
exit(EXIT_FAILURE);
}
@@ -417,18 +475,23 @@ main(int argc, char *argv[])
}
/* Adjust temperature */
- r = adjust_temperature(screen_num, use_randr,
- temp, gamma);
+ r = gamma_state_set_temperature(&state, use_randr,
+ temp, gamma);
if (r < 0) {
fprintf(stderr, "Temperature adjustment"
" failed.\n");
+ gamma_state_free(&state, use_randr);
exit(EXIT_FAILURE);
}
if (init_trans) usleep(100000);
else usleep(5000000);
}
+
+ gamma_state_restore(&state, use_randr);
}
+ gamma_state_free(&state, use_randr);
+
return EXIT_SUCCESS;
}
diff --git a/src/vidmode.c b/src/vidmode.c
index 93f7bdb..7d7dda7 100644
--- a/src/vidmode.c
+++ b/src/vidmode.c
@@ -24,91 +24,92 @@
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
+#include "vidmode.h"
#include "colorramp.h"
int
-vidmode_check_extension()
+vidmode_init(vidmode_state_t *state, int screen_num)
{
int r;
/* Open display */
- Display *dpy = XOpenDisplay(NULL);
- if (dpy == NULL) {
+ state->display = XOpenDisplay(NULL);
+ if (state->display == NULL) {
fprintf(stderr, "XOpenDisplay failed.\n");
return -1;
}
+ if (screen_num < 0) screen_num = DefaultScreen(state->display);
+ state->screen_num = screen_num;
+
/* Query extension version */
int major, minor;
- r = XF86VidModeQueryVersion(dpy, &major, &minor);
+ r = XF86VidModeQueryVersion(state->display, &major, &minor);
if (!r) {
fprintf(stderr, "XF86VidModeQueryVersion failed.\n");
+ XCloseDisplay(state->display);
return -1;
}
- /* TODO Check major/minor */
+ return 0;
+}
- /* Close display */
- XCloseDisplay(dpy);
+void
+vidmode_free(vidmode_state_t *state)
+{
+ /* Close display connection */
+ XCloseDisplay(state->display);
+}
- return 0;
+void
+vidmode_restore(vidmode_state_t *state)
+{
}
int
-vidmode_set_temperature(int screen_num, int temp, float gamma[3])
+vidmode_set_temperature(vidmode_state_t *state, int temp, float gamma[3])
{
int r;
- /* Open display */
- Display *dpy = XOpenDisplay(NULL);
- if (dpy == NULL) {
- fprintf(stderr, "XOpenDisplay failed.\n");
- return -1;
- }
-
- if (screen_num < 0) screen_num = DefaultScreen(dpy);
-
/* Request size of gamma ramps */
- int gamma_ramp_size;
- r = XF86VidModeGetGammaRampSize(dpy, screen_num, &gamma_ramp_size);
+ int ramp_size;
+ r = XF86VidModeGetGammaRampSize(state->display, state->screen_num,
+ &ramp_size);
if (!r) {
fprintf(stderr, "XF86VidModeGetGammaRampSize failed.\n");
- XCloseDisplay(dpy);
return -1;
}
- if (gamma_ramp_size == 0) {
+ if (ramp_size == 0) {
fprintf(stderr, "Gamma ramp size too small: %i\n",
- gamma_ramp_size);
- XCloseDisplay(dpy);
+ ramp_size);
return -1;
}
/* Create new gamma ramps */
- uint16_t *gamma_ramps = malloc(3*gamma_ramp_size*sizeof(uint16_t));
- if (gamma_ramps == NULL) abort();
+ uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t));
+ if (gamma_ramps == NULL) {
+ perror("malloc");
+ return -1;
+ }
- uint16_t *gamma_r = &gamma_ramps[0*gamma_ramp_size];
- uint16_t *gamma_g = &gamma_ramps[1*gamma_ramp_size];
- uint16_t *gamma_b = &gamma_ramps[2*gamma_ramp_size];
+ uint16_t *gamma_r = &gamma_ramps[0*ramp_size];
+ uint16_t *gamma_g = &gamma_ramps[1*ramp_size];
+ uint16_t *gamma_b = &gamma_ramps[2*ramp_size];
- colorramp_fill(gamma_r, gamma_g, gamma_b, gamma_ramp_size,
- temp, gamma);
+ colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size, temp, gamma);
/* Set new gamma ramps */
- r = XF86VidModeSetGammaRamp(dpy, screen_num, gamma_ramp_size,
- gamma_r, gamma_g, gamma_b);
+ r = XF86VidModeSetGammaRamp(state->display, state->screen_num,
+ ramp_size, gamma_r, gamma_g, gamma_b);
if (!r) {
fprintf(stderr, "XF86VidModeSetGammaRamp failed.\n");
- XCloseDisplay(dpy);
+ free(gamma_ramps);
return -1;
}
free(gamma_ramps);
- /* Close display */
- XCloseDisplay(dpy);
-
return 0;
}
diff --git a/src/vidmode.h b/src/vidmode.h
index cf5516c..b342254 100644
--- a/src/vidmode.h
+++ b/src/vidmode.h
@@ -20,7 +20,16 @@
#ifndef _REDSHIFT_VIDMODE_H
#define _REDSHIFT_VIDMODE_H
-int vidmode_check_extension();
-int vidmode_set_temperature(int screen_num, int temp, float gamma[3]);
+#include <X11/Xlib.h>
+
+typedef struct {
+ Display *display;
+ int screen_num;
+} vidmode_state_t;
+
+int vidmode_init(vidmode_state_t *state, int screen_num);
+void vidmode_free(vidmode_state_t *state);
+void vidmode_restore(vidmode_state_t *state);
+int vidmode_set_temperature(vidmode_state_t *state, int temp, float gamma[3]);
#endif /* ! _REDSHIFT_VIDMODE_H */