summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ggamma.c110
1 files changed, 55 insertions, 55 deletions
diff --git a/ggamma.c b/ggamma.c
index a30c9b7..de0192e 100644
--- a/ggamma.c
+++ b/ggamma.c
@@ -10,56 +10,70 @@
#define UNUSED __attribute__((unused))
-struct gamma_channel {
- int size;
- uint16_t *data;
- void (*flush)(void);
-};
+/* Technically, the range of the curve should be [0,2¹⁶), but the X
+ * server will just divide it to fit in [0,gamma_size). So there's no
+ * point in making it awkwardly tall to get the extra precision; just
+ * make it a square, we're not really loosing anything. */
+
+void gtkgamma_set(GtkGammaCurve *widget, int gamma_size, uint16_t *gamma_chan) {
+ gfloat vec[gamma_size];
+
+ for (int i = 0; i < gamma_size; i++)
+ vec[i] = gamma_chan[i] * gamma_size / 65535.0;
+ gtk_curve_set_vector(GTK_CURVE(widget->curve),
+ gamma_size, vec);
+}
-void curve_edited(GtkWidget *raw_curve, UNUSED GdkEvent *event, struct gamma_channel *gamma) {
- gfloat vec[gamma->size];
+gboolean gtkgamma_get(GtkGammaCurve *widget, int gamma_size, uint16_t *gamma_chan) {
+ gfloat vec[gamma_size];
gboolean dirty = FALSE;
- gtk_curve_get_vector(GTK_CURVE(raw_curve), gamma->size, vec);
- for (int i = 0; i < gamma->size; i++) {
- uint16_t y = vec[i] * 65535.0 / gamma->size;
- if (y != gamma->data[i]) {
- gamma->data[i] = y;
+ gtk_curve_get_vector(GTK_CURVE(widget->curve), gamma_size, vec);
+ for (int i = 0; i < gamma_size; i++) {
+ uint16_t y = vec[i] * 65535.0 / gamma_size;
+ if (y != gamma_chan[i]) {
+ gamma_chan[i] = y;
dirty = TRUE;
}
}
-
- if (dirty && gamma->flush)
- gamma->flush();
+ return dirty;
}
-void curve_set(GtkGammaCurve *curve, struct gamma_channel *gamma) {
- gfloat vec[gamma->size];
- for (int i = 0; i < gamma->size; i++)
- vec[i] = gamma->data[i] * gamma->size / 65535.0;
- gtk_curve_set_vector(GTK_CURVE(curve->curve),
- gamma->size, vec);
+struct gtkgamma_data {
+ GtkGammaCurve *widget;
+ int gamma_size;
+ uint16_t *gamma_chan;
+ void (*cb)(void);
+ guint poll_id;
+};
+
+gboolean _gtkgamma_poll(struct gtkgamma_data *data) {
+ if (gtkgamma_get(data->widget, data->gamma_size, data->gamma_chan) && data->cb)
+ data->cb();
+ return TRUE;
}
+void _gtkgamma_destroy(UNUSED GtkObject *object, struct gtkgamma_data *data) {
+ g_source_remove(data->poll_id);
+ free(data);
+}
+GtkWidget *gtkgamma_new(int gamma_size, uint16_t *gamma_chan, void (*cb)(void)) {
+ GtkGammaCurve *widget = GTK_GAMMA_CURVE(gtk_gamma_curve_new());
-GtkWidget *curve_new(struct gamma_channel *gamma) {
- GtkWidget *curve = gtk_gamma_curve_new();
- GtkWidget *raw_curve = GTK_GAMMA_CURVE(curve)->curve;
-
- /* Technically, the range of the curve should be [0,2¹⁶), but
- * the X server will just divide it to fit in [0,gamma_size).
- * So there's no point in making it awkwardly tall to get the
- * extra precision; just make it a square, we're not really
- * loosing anything. */
- gtk_curve_set_range(GTK_CURVE(raw_curve),
- /* x */0, gamma->size-1,
- /* y */0, gamma->size-1);
+ gtk_curve_set_range(GTK_CURVE(widget->curve),
+ /* x */0, gamma_size-1,
+ /* y */0, gamma_size-1);
- curve_set(GTK_GAMMA_CURVE(curve), gamma);
+ gtkgamma_set(widget, gamma_size, gamma_chan);
- // TODO: find a better signal
- g_signal_connect(raw_curve, "event-after", G_CALLBACK(curve_edited), gamma);
+ struct gtkgamma_data *data = malloc(sizeof(struct gtkgamma_data));
+ data->widget = widget;
+ data->gamma_size = gamma_size;
+ data->gamma_chan = gamma_chan;
+ data->cb = cb;
+ data->poll_id = g_timeout_add(100, (gboolean (*)(gpointer))_gtkgamma_poll, data);
+ g_signal_connect(widget, "destroy", G_CALLBACK(_gtkgamma_destroy), data);
- return curve;
+ return GTK_WIDGET(widget);
}
int main(int argc, char *argv[]) {
@@ -108,36 +122,22 @@ int main(int argc, char *argv[]) {
void flush(void) {
XRRSetCrtcGamma(display, crtc, gamma);
}
+ GtkWidget *curve;
/* start red */
- struct gamma_channel r = {
- .size = gamma_size,
- .data = gamma->red,
- .flush = flush,
- };
- GtkWidget *curve = curve_new(&r);
+ curve = gtkgamma_new(gamma_size, gamma->red, flush);
gtk_container_add(GTK_CONTAINER(layout), curve);
gtk_widget_show(curve);
/* end red */
/* start green */
- struct gamma_channel g = {
- .size = gamma_size,
- .data = gamma->green,
- .flush = flush,
- };
- curve = curve_new(&g);
+ curve = gtkgamma_new(gamma_size, gamma->green, flush);
gtk_container_add(GTK_CONTAINER(layout), curve);
gtk_widget_show(curve);
/* end green */
/* start blue */
- struct gamma_channel b = {
- .size = gamma_size,
- .data = gamma->blue,
- .flush = flush,
- };
- curve = curve_new(&b);
+ curve = gtkgamma_new(gamma_size, gamma->blue, flush);
gtk_container_add(GTK_CONTAINER(layout), curve);
gtk_widget_show(curve);
/* end blue */