From b55b46fa07bdd92209d0d954fba1aa7d864e2607 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 29 Aug 2017 18:30:02 -0400 Subject: switch to a polling approach, because GtkCurve doesn't do useful signals --- ggamma.c | 110 +++++++++++++++++++++++++++++++-------------------------------- 1 file 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 */ -- cgit v1.2.3