Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2012 Richard Hughes <richard@hughsie.com> |
4 |
|
|
* |
5 |
|
|
* Licensed under the GNU General Public License Version 2 |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* This program is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
|
* GNU General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include "config.h" |
23 |
|
|
|
24 |
|
|
#include <colord-gtk.h> |
25 |
|
|
#include <gio/gunixfdlist.h> |
26 |
|
|
#include <glib/gi18n.h> |
27 |
|
|
#include <glib-object.h> |
28 |
|
|
#include <math.h> |
29 |
|
|
#include <colord-session/cd-session.h> |
30 |
|
|
|
31 |
|
|
#define GNOME_DESKTOP_USE_UNSTABLE_API |
32 |
|
|
#include <gnome-rr/gnome-rr.h> |
33 |
|
|
|
34 |
|
|
#include "cc-color-calibrate.h" |
35 |
|
|
|
36 |
|
|
#define CALIBRATE_WINDOW_OPACITY 0.9 |
37 |
|
|
|
38 |
|
|
struct _CcColorCalibrate |
39 |
|
|
{ |
40 |
|
|
GObject parent_instance; |
41 |
|
|
|
42 |
|
|
CdDevice *device; |
43 |
|
|
CdSensorCap device_kind; |
44 |
|
|
CdSensor *sensor; |
45 |
|
|
CdProfile *profile; |
46 |
|
|
gchar *title; |
47 |
|
|
GDBusProxy *proxy_helper; |
48 |
|
|
GDBusProxy *proxy_inhibit; |
49 |
|
|
GMainLoop *loop; |
50 |
|
|
GnomeRROutput *output; |
51 |
|
|
GnomeRRScreen *x11_screen; |
52 |
|
|
GtkBuilder *builder; |
53 |
|
|
GtkWindow *window; |
54 |
|
|
GtkWidget *sample_widget; |
55 |
|
|
guint gamma_size; |
56 |
|
|
CdProfileQuality quality; |
57 |
|
|
guint target_whitepoint; /* in Kelvin */ |
58 |
|
|
gdouble target_gamma; |
59 |
|
|
gint inhibit_fd; |
60 |
|
|
gint inhibit_cookie; |
61 |
|
|
CdSessionError session_error_code; |
62 |
|
|
}; |
63 |
|
|
|
64 |
|
|
#define CD_SESSION_ERROR cc_color_calibrate_error_quark() |
65 |
|
|
|
66 |
|
|
#define COLORD_SETTINGS_SCHEMA "org.freedesktop.ColorHelper" |
67 |
|
|
|
68 |
|
✗ |
G_DEFINE_TYPE (CcColorCalibrate, cc_color_calibrate, G_TYPE_OBJECT) |
69 |
|
|
|
70 |
|
|
static GQuark |
71 |
|
✗ |
cc_color_calibrate_error_quark (void) |
72 |
|
|
{ |
73 |
|
|
static GQuark quark = 0; |
74 |
|
✗ |
if (!quark) |
75 |
|
✗ |
quark = g_quark_from_static_string ("CcColorCalibrateError"); |
76 |
|
✗ |
return quark; |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
void |
80 |
|
✗ |
cc_color_calibrate_set_kind (CcColorCalibrate *calibrate, |
81 |
|
|
CdSensorCap kind) |
82 |
|
|
{ |
83 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
84 |
|
✗ |
calibrate->device_kind = kind; |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
void |
88 |
|
✗ |
cc_color_calibrate_set_temperature (CcColorCalibrate *calibrate, |
89 |
|
|
guint temperature) |
90 |
|
|
{ |
91 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
92 |
|
✗ |
g_return_if_fail (temperature < 10000); |
93 |
|
✗ |
calibrate->target_whitepoint = temperature; |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
void |
97 |
|
✗ |
cc_color_calibrate_set_quality (CcColorCalibrate *calibrate, |
98 |
|
|
CdProfileQuality quality) |
99 |
|
|
{ |
100 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
101 |
|
✗ |
calibrate->quality = quality; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
CdProfileQuality |
105 |
|
✗ |
cc_color_calibrate_get_quality (CcColorCalibrate *calibrate) |
106 |
|
|
{ |
107 |
|
✗ |
g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), 0); |
108 |
|
✗ |
return calibrate->quality; |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
void |
112 |
|
✗ |
cc_color_calibrate_set_device (CcColorCalibrate *calibrate, |
113 |
|
|
CdDevice *device) |
114 |
|
|
{ |
115 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
116 |
|
✗ |
g_return_if_fail (CD_IS_DEVICE (device)); |
117 |
|
✗ |
if (calibrate->device != NULL) |
118 |
|
✗ |
g_object_unref (calibrate->device); |
119 |
|
✗ |
calibrate->device = g_object_ref (device); |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
void |
123 |
|
✗ |
cc_color_calibrate_set_sensor (CcColorCalibrate *calibrate, |
124 |
|
|
CdSensor *sensor) |
125 |
|
|
{ |
126 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
127 |
|
✗ |
g_return_if_fail (CD_IS_SENSOR (sensor)); |
128 |
|
✗ |
if (calibrate->sensor != NULL) |
129 |
|
✗ |
g_object_unref (calibrate->sensor); |
130 |
|
✗ |
calibrate->sensor = g_object_ref (sensor); |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
void |
134 |
|
✗ |
cc_color_calibrate_set_title (CcColorCalibrate *calibrate, |
135 |
|
|
const gchar *title) |
136 |
|
|
{ |
137 |
|
✗ |
g_return_if_fail (CC_IS_COLOR_CALIBRATE (calibrate)); |
138 |
|
✗ |
g_return_if_fail (title != NULL); |
139 |
|
✗ |
g_free (calibrate->title); |
140 |
|
✗ |
calibrate->title = g_strdup (title); |
141 |
|
|
} |
142 |
|
|
|
143 |
|
|
CdProfile * |
144 |
|
✗ |
cc_color_calibrate_get_profile (CcColorCalibrate *calibrate) |
145 |
|
|
{ |
146 |
|
✗ |
g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), NULL); |
147 |
|
✗ |
return calibrate->profile; |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
static guint |
151 |
|
✗ |
_gnome_rr_output_get_gamma_size (GnomeRROutput *output) |
152 |
|
|
{ |
153 |
|
|
GnomeRRCrtc *crtc; |
154 |
|
✗ |
gint len = 0; |
155 |
|
|
|
156 |
|
✗ |
crtc = gnome_rr_output_get_crtc (output); |
157 |
|
✗ |
if (crtc == NULL) |
158 |
|
✗ |
return 0; |
159 |
|
✗ |
gnome_rr_crtc_get_gamma (crtc, |
160 |
|
|
&len, |
161 |
|
|
NULL, NULL, NULL); |
162 |
|
✗ |
return (guint) len; |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
static gboolean |
166 |
|
✗ |
cc_color_calibrate_calib_setup_screen (CcColorCalibrate *calibrate, |
167 |
|
|
const gchar *name, |
168 |
|
|
GError **error) |
169 |
|
|
{ |
170 |
|
✗ |
gboolean ret = TRUE; |
171 |
|
|
|
172 |
|
|
/* get screen */ |
173 |
|
✗ |
calibrate->x11_screen = gnome_rr_screen_new (gdk_display_get_default (), error); |
174 |
|
✗ |
if (calibrate->x11_screen == NULL) |
175 |
|
|
{ |
176 |
|
✗ |
ret = FALSE; |
177 |
|
✗ |
goto out; |
178 |
|
|
} |
179 |
|
|
|
180 |
|
|
/* get the output */ |
181 |
|
✗ |
calibrate->output = gnome_rr_screen_get_output_by_name (calibrate->x11_screen, |
182 |
|
|
name); |
183 |
|
✗ |
if (calibrate->output == NULL) |
184 |
|
|
{ |
185 |
|
✗ |
ret = FALSE; |
186 |
|
✗ |
g_set_error_literal (error, |
187 |
|
|
CD_SESSION_ERROR, |
188 |
|
|
CD_SESSION_ERROR_INTERNAL, |
189 |
|
|
"failed to get output"); |
190 |
|
✗ |
goto out; |
191 |
|
|
} |
192 |
|
|
|
193 |
|
|
/* create a lookup table */ |
194 |
|
✗ |
calibrate->gamma_size = _gnome_rr_output_get_gamma_size (calibrate->output); |
195 |
|
✗ |
if (calibrate->gamma_size == 0) |
196 |
|
|
{ |
197 |
|
✗ |
ret = FALSE; |
198 |
|
✗ |
g_set_error_literal (error, |
199 |
|
|
CD_SESSION_ERROR, |
200 |
|
|
CD_SESSION_ERROR_INTERNAL, |
201 |
|
|
"gamma size is zero"); |
202 |
|
|
} |
203 |
|
✗ |
out: |
204 |
|
✗ |
return ret; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
/** |
208 |
|
|
* cc_color_calibrate_calib_set_output_gamma: |
209 |
|
|
* |
210 |
|
|
* Handle this here rather than in gnome-settings-daemon for two reasons: |
211 |
|
|
* |
212 |
|
|
* - We don't want to create a profile each time the video card gamma |
213 |
|
|
* table is created, as that would mean ~15 DBus requests each time |
214 |
|
|
* we get UpdateGamma from the session helper. |
215 |
|
|
* |
216 |
|
|
* - We only have 100ms to process the request before the next update |
217 |
|
|
* could be scheduled. |
218 |
|
|
**/ |
219 |
|
|
static gboolean |
220 |
|
✗ |
cc_color_calibrate_calib_set_output_gamma (CcColorCalibrate *calibrate, |
221 |
|
|
GPtrArray *array, |
222 |
|
|
GError **error) |
223 |
|
|
{ |
224 |
|
|
CdColorRGB *p1; |
225 |
|
|
CdColorRGB *p2; |
226 |
|
|
CdColorRGB result; |
227 |
|
|
gdouble mix; |
228 |
|
|
GnomeRRCrtc *crtc; |
229 |
|
✗ |
g_autofree guint16 *blue = NULL; |
230 |
|
✗ |
g_autofree guint16 *green = NULL; |
231 |
|
✗ |
g_autofree guint16 *red = NULL; |
232 |
|
|
guint i; |
233 |
|
|
|
234 |
|
|
/* no length? */ |
235 |
|
✗ |
if (array->len == 0) |
236 |
|
|
{ |
237 |
|
✗ |
g_set_error_literal (error, |
238 |
|
|
CD_SESSION_ERROR, |
239 |
|
|
CD_SESSION_ERROR_INTERNAL, |
240 |
|
|
"no data in the CLUT array"); |
241 |
|
✗ |
return FALSE; |
242 |
|
|
} |
243 |
|
|
|
244 |
|
|
/* convert to a type X understands of the right size */ |
245 |
|
✗ |
red = g_new (guint16, calibrate->gamma_size); |
246 |
|
✗ |
green = g_new (guint16, calibrate->gamma_size); |
247 |
|
✗ |
blue = g_new (guint16, calibrate->gamma_size); |
248 |
|
✗ |
cd_color_rgb_set (&result, 1.0, 1.0, 1.0); |
249 |
|
✗ |
for (i = 0; i < calibrate->gamma_size; i++) |
250 |
|
|
{ |
251 |
|
✗ |
mix = (gdouble) (array->len - 1) / |
252 |
|
✗ |
(gdouble) (calibrate->gamma_size - 1) * |
253 |
|
✗ |
(gdouble) i; |
254 |
|
✗ |
p1 = g_ptr_array_index (array, (guint) floor (mix)); |
255 |
|
✗ |
p2 = g_ptr_array_index (array, (guint) ceil (mix)); |
256 |
|
✗ |
cd_color_rgb_interpolate (p1, |
257 |
|
|
p2, |
258 |
|
✗ |
mix - (gint) mix, |
259 |
|
|
&result); |
260 |
|
✗ |
red[i] = result.R * 0xffff; |
261 |
|
✗ |
green[i] = result.G * 0xffff; |
262 |
|
✗ |
blue[i] = result.B * 0xffff; |
263 |
|
|
} |
264 |
|
|
|
265 |
|
|
/* send to LUT */ |
266 |
|
✗ |
crtc = gnome_rr_output_get_crtc (calibrate->output); |
267 |
|
✗ |
if (crtc == NULL) |
268 |
|
|
{ |
269 |
|
✗ |
g_set_error (error, |
270 |
|
|
CD_SESSION_ERROR, |
271 |
|
|
CD_SESSION_ERROR_INTERNAL, |
272 |
|
|
"failed to get ctrc for %s", |
273 |
|
✗ |
gnome_rr_output_get_name (calibrate->output)); |
274 |
|
✗ |
return FALSE; |
275 |
|
|
} |
276 |
|
✗ |
gnome_rr_crtc_set_gamma (crtc, calibrate->gamma_size, |
277 |
|
|
red, green, blue); |
278 |
|
✗ |
return TRUE; |
279 |
|
|
} |
280 |
|
|
|
281 |
|
|
static void |
282 |
|
✗ |
cc_color_calibrate_property_changed_cb (CcColorCalibrate *calibrate, |
283 |
|
|
GVariant *changed_properties, |
284 |
|
|
GStrv invalidated_properties) |
285 |
|
|
{ |
286 |
|
|
gboolean ret; |
287 |
|
|
GtkWidget *widget; |
288 |
|
|
guint value; |
289 |
|
|
|
290 |
|
✗ |
ret = g_variant_lookup (changed_properties, |
291 |
|
|
"Progress", |
292 |
|
|
"u", &value); |
293 |
|
✗ |
if (ret) |
294 |
|
|
{ |
295 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
296 |
|
|
"progressbar_status")); |
297 |
|
✗ |
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), |
298 |
|
✗ |
value / 100.0f); |
299 |
|
|
} |
300 |
|
✗ |
} |
301 |
|
|
|
302 |
|
|
static void |
303 |
|
✗ |
cc_color_calibrate_interaction_required (CcColorCalibrate *calibrate, |
304 |
|
|
CdSessionInteraction code, |
305 |
|
|
const gchar *message, |
306 |
|
|
const gchar *image_path) |
307 |
|
|
{ |
308 |
|
|
const gchar *message_transl; |
309 |
|
✗ |
gboolean show_button_start = FALSE; |
310 |
|
|
GtkImage *img; |
311 |
|
|
GtkLabel *label; |
312 |
|
|
GtkWidget *widget; |
313 |
|
|
|
314 |
|
|
/* the client helper does not ship an icon for this */ |
315 |
|
✗ |
if (code == CD_SESSION_INTERACTION_SHUT_LAPTOP_LID) |
316 |
|
✗ |
image_path = "org.gnome.Settings-color-symbolic"; |
317 |
|
|
|
318 |
|
|
/* set image */ |
319 |
|
✗ |
img = GTK_IMAGE (gtk_builder_get_object (calibrate->builder, |
320 |
|
|
"image_status")); |
321 |
|
✗ |
if (image_path != NULL && image_path[0] != '\0') |
322 |
|
✗ |
{ |
323 |
|
✗ |
g_autoptr(GdkPixbuf) pixbuf = NULL; |
324 |
|
|
|
325 |
|
✗ |
g_debug ("showing image %s", image_path); |
326 |
|
✗ |
pixbuf = gdk_pixbuf_new_from_file_at_size (image_path, |
327 |
|
|
400, 400, |
328 |
|
|
NULL); |
329 |
|
✗ |
if (pixbuf != NULL) |
330 |
|
✗ |
gtk_image_set_from_pixbuf (img, pixbuf); |
331 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (img), TRUE); |
332 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), FALSE); |
333 |
|
|
} |
334 |
|
|
else |
335 |
|
|
{ |
336 |
|
✗ |
g_debug ("hiding image"); |
337 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (img), FALSE); |
338 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), TRUE); |
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
/* set new status */ |
342 |
|
✗ |
switch (code) |
343 |
|
|
{ |
344 |
|
✗ |
case CD_SESSION_INTERACTION_ATTACH_TO_SCREEN: |
345 |
|
✗ |
show_button_start = TRUE; |
346 |
|
|
/* TRANSLATORS: The user has to attach the sensor to the screen */ |
347 |
|
✗ |
message_transl = _("Place your calibration device over the square and press “Start”"); |
348 |
|
✗ |
break; |
349 |
|
✗ |
case CD_SESSION_INTERACTION_MOVE_TO_CALIBRATION: |
350 |
|
|
/* TRANSLATORS: Some calibration devices need the user to move a |
351 |
|
|
* dial or switch manually. We also show a picture showing them |
352 |
|
|
* what to do... */ |
353 |
|
✗ |
message_transl = _("Move your calibration device to the calibrate position and press “Continue”"); |
354 |
|
✗ |
break; |
355 |
|
✗ |
case CD_SESSION_INTERACTION_MOVE_TO_SURFACE: |
356 |
|
|
/* TRANSLATORS: Some calibration devices need the user to move a |
357 |
|
|
* dial or switch manually. We also show a picture showing them |
358 |
|
|
* what to do... */ |
359 |
|
✗ |
message_transl = _("Move your calibration device to the surface position and press “Continue”"); |
360 |
|
✗ |
break; |
361 |
|
✗ |
case CD_SESSION_INTERACTION_SHUT_LAPTOP_LID: |
362 |
|
|
/* TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor |
363 |
|
|
* is built into the palmrest and we need to fullscreen the |
364 |
|
|
* sample widget and shut the lid. */ |
365 |
|
✗ |
message_transl = _("Shut the laptop lid"); |
366 |
|
✗ |
break; |
367 |
|
✗ |
default: |
368 |
|
✗ |
message_transl = message; |
369 |
|
✗ |
break; |
370 |
|
|
} |
371 |
|
✗ |
label = GTK_LABEL (gtk_builder_get_object (calibrate->builder, |
372 |
|
|
"label_status")); |
373 |
|
✗ |
gtk_label_set_label (label, message_transl); |
374 |
|
|
|
375 |
|
|
/* show the correct button */ |
376 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
377 |
|
|
"button_start")); |
378 |
|
✗ |
gtk_widget_set_visible (widget, show_button_start); |
379 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
380 |
|
|
"button_resume")); |
381 |
|
✗ |
gtk_widget_set_visible (widget, !show_button_start); |
382 |
|
✗ |
} |
383 |
|
|
|
384 |
|
|
static const gchar * |
385 |
|
✗ |
cc_color_calibrate_get_error_translation (CdSessionError code) |
386 |
|
|
{ |
387 |
|
✗ |
const gchar *str = NULL; |
388 |
|
✗ |
switch (code) |
389 |
|
|
{ |
390 |
|
✗ |
case CD_SESSION_ERROR_FAILED_TO_FIND_DEVICE: |
391 |
|
|
case CD_SESSION_ERROR_FAILED_TO_FIND_SENSOR: |
392 |
|
|
case CD_SESSION_ERROR_INTERNAL: |
393 |
|
|
case CD_SESSION_ERROR_INVALID_VALUE: |
394 |
|
|
/* TRANSLATORS: We suck, the calibration failed and we have no |
395 |
|
|
* good idea why or any suggestions */ |
396 |
|
✗ |
str = _("An internal error occurred that could not be recovered."); |
397 |
|
✗ |
break; |
398 |
|
✗ |
case CD_SESSION_ERROR_FAILED_TO_FIND_TOOL: |
399 |
|
|
/* TRANSLATORS: Some required-at-runtime tools were not |
400 |
|
|
* installed, which should only affect insane distros */ |
401 |
|
✗ |
str = _("Tools required for calibration are not installed."); |
402 |
|
✗ |
break; |
403 |
|
✗ |
case CD_SESSION_ERROR_FAILED_TO_GENERATE_PROFILE: |
404 |
|
|
case CD_SESSION_ERROR_FAILED_TO_OPEN_PROFILE: |
405 |
|
|
case CD_SESSION_ERROR_FAILED_TO_SAVE_PROFILE: |
406 |
|
|
/* TRANSLATORS: The profile failed for some reason */ |
407 |
|
✗ |
str = _("The profile could not be generated."); |
408 |
|
✗ |
break; |
409 |
|
✗ |
case CD_SESSION_ERROR_FAILED_TO_GET_WHITEPOINT: |
410 |
|
|
/* TRANSLATORS: The user specified a whitepoint that was |
411 |
|
|
* unobtainable with the hardware they've got -- see |
412 |
|
|
* https://en.wikipedia.org/wiki/White_point for details */ |
413 |
|
✗ |
str = _("The target whitepoint was not obtainable."); |
414 |
|
✗ |
break; |
415 |
|
✗ |
default: |
416 |
|
✗ |
break; |
417 |
|
|
} |
418 |
|
✗ |
return str; |
419 |
|
|
} |
420 |
|
|
|
421 |
|
|
static void |
422 |
|
✗ |
cc_color_calibrate_finished (CcColorCalibrate *calibrate, |
423 |
|
|
CdSessionError code, |
424 |
|
|
const gchar *error_fallback) |
425 |
|
|
{ |
426 |
|
|
GtkWidget *widget; |
427 |
|
✗ |
g_autoptr(GString) str = NULL; |
428 |
|
|
const gchar *tmp; |
429 |
|
|
|
430 |
|
|
/* save failure so we can get this after we've quit the loop */ |
431 |
|
✗ |
calibrate->session_error_code = code; |
432 |
|
|
|
433 |
|
|
/* show correct buttons */ |
434 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
435 |
|
|
"button_cancel")); |
436 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
437 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
438 |
|
|
"button_start")); |
439 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
440 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
441 |
|
|
"button_resume")); |
442 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
443 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
444 |
|
|
"button_done")); |
445 |
|
|
|
446 |
|
✗ |
str = g_string_new (""); |
447 |
|
✗ |
if (code == CD_SESSION_ERROR_NONE) |
448 |
|
|
{ |
449 |
|
✗ |
g_debug ("calibration succeeded"); |
450 |
|
|
/* TRANSLATORS: the display calibration process is finished */ |
451 |
|
✗ |
g_string_append (str, _("Complete!")); |
452 |
|
|
} |
453 |
|
|
else |
454 |
|
|
{ |
455 |
|
✗ |
g_warning ("calibration failed with code %i: %s", |
456 |
|
|
code, error_fallback); |
457 |
|
|
/* TRANSLATORS: the display calibration failed, and we also show |
458 |
|
|
* the translated (or untranslated) error string after this */ |
459 |
|
✗ |
g_string_append (str, _("Calibration failed!")); |
460 |
|
✗ |
g_string_append (str, "\n\n"); |
461 |
|
✗ |
tmp = cc_color_calibrate_get_error_translation (code); |
462 |
|
✗ |
g_string_append (str, tmp != NULL ? tmp : error_fallback); |
463 |
|
|
} |
464 |
|
✗ |
g_string_append (str, "\n"); |
465 |
|
|
/* TRANSLATORS: The user can now remove the sensor from the screen */ |
466 |
|
✗ |
g_string_append (str, _("You can remove the calibration device.")); |
467 |
|
|
|
468 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
469 |
|
|
"label_status")); |
470 |
|
✗ |
gtk_label_set_label (GTK_LABEL (widget), str->str); |
471 |
|
✗ |
} |
472 |
|
|
|
473 |
|
|
static void |
474 |
|
✗ |
cc_color_calibrate_signal_cb (CcColorCalibrate *calibrate, |
475 |
|
|
const gchar *sender_name, |
476 |
|
|
const gchar *signal_name, |
477 |
|
|
GVariant *parameters) |
478 |
|
|
{ |
479 |
|
|
CdColorRGB color; |
480 |
|
|
CdColorRGB *color_tmp; |
481 |
|
✗ |
const gchar *image = NULL; |
482 |
|
|
const gchar *message; |
483 |
|
✗ |
const gchar *profile_path = NULL; |
484 |
|
✗ |
const gchar *str = NULL; |
485 |
|
|
gboolean ret; |
486 |
|
✗ |
g_autoptr(GError) error = NULL; |
487 |
|
✗ |
GPtrArray *array = NULL; |
488 |
|
|
GtkImage *img; |
489 |
|
|
GtkLabel *label; |
490 |
|
✗ |
g_autoptr(GVariant) dict = NULL; |
491 |
|
|
|
492 |
|
✗ |
if (g_strcmp0 (signal_name, "Finished") == 0) |
493 |
|
|
{ |
494 |
|
|
CdSessionError error_code; |
495 |
|
|
|
496 |
|
✗ |
g_variant_get (parameters, "(u@a{sv})", |
497 |
|
|
&error_code, |
498 |
|
|
&dict); |
499 |
|
✗ |
g_variant_lookup (dict, "ErrorDetails", "&s", &str); |
500 |
|
✗ |
ret = g_variant_lookup (dict, "ProfilePath", "&s", &profile_path); |
501 |
|
✗ |
if (ret) |
502 |
|
✗ |
calibrate->profile = cd_profile_new_with_object_path (profile_path); |
503 |
|
✗ |
cc_color_calibrate_finished (calibrate, error_code, str); |
504 |
|
✗ |
return; |
505 |
|
|
} |
506 |
|
✗ |
if (g_strcmp0 (signal_name, "UpdateSample") == 0) |
507 |
|
|
{ |
508 |
|
✗ |
g_variant_get (parameters, "(ddd)", |
509 |
|
|
&color.R, |
510 |
|
|
&color.G, |
511 |
|
|
&color.B); |
512 |
|
✗ |
img = GTK_IMAGE (gtk_builder_get_object (calibrate->builder, |
513 |
|
|
"image_status")); |
514 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (img), FALSE); |
515 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (calibrate->sample_widget), TRUE); |
516 |
|
✗ |
cd_sample_widget_set_color (CD_SAMPLE_WIDGET (calibrate->sample_widget), |
517 |
|
|
&color); |
518 |
|
|
|
519 |
|
|
/* for Lenovo W700 and W520 laptops we almost fullscreen the |
520 |
|
|
* sample widget as the device is actually embedded in the |
521 |
|
|
* palmrest! */ |
522 |
|
✗ |
if (cd_sensor_get_embedded (calibrate->sensor)) |
523 |
|
|
{ |
524 |
|
✗ |
g_debug ("Making sample window larger for embedded sensor"); |
525 |
|
✗ |
gtk_widget_set_size_request (calibrate->sample_widget, 1000, 600); |
526 |
|
|
} |
527 |
|
|
|
528 |
|
|
/* set the generic label too */ |
529 |
|
✗ |
label = GTK_LABEL (gtk_builder_get_object (calibrate->builder, |
530 |
|
|
"label_status")); |
531 |
|
|
/* TRANSLATORS: The user has to be careful not to knock the |
532 |
|
|
* display off the screen (although we do cope if this is |
533 |
|
|
* detected early enough) */ |
534 |
|
✗ |
gtk_label_set_label (label, _("Do not disturb the calibration device while in progress")); |
535 |
|
✗ |
return; |
536 |
|
|
} |
537 |
|
✗ |
if (g_strcmp0 (signal_name, "InteractionRequired") == 0) |
538 |
|
|
{ |
539 |
|
|
CdSessionInteraction code; |
540 |
|
|
|
541 |
|
✗ |
g_variant_get (parameters, "(u&s&s)", |
542 |
|
|
&code, |
543 |
|
|
&message, |
544 |
|
|
&image); |
545 |
|
✗ |
g_debug ("Interaction required type %i: %s", |
546 |
|
|
code, message); |
547 |
|
✗ |
cc_color_calibrate_interaction_required (calibrate, |
548 |
|
|
code, |
549 |
|
|
message, |
550 |
|
|
image); |
551 |
|
✗ |
return; |
552 |
|
|
} |
553 |
|
✗ |
if (g_strcmp0 (signal_name, "UpdateGamma") == 0) |
554 |
|
|
{ |
555 |
|
✗ |
g_autoptr(GVariantIter) iter = NULL; |
556 |
|
|
|
557 |
|
✗ |
g_variant_get (parameters, |
558 |
|
|
"(a(ddd))", |
559 |
|
|
&iter); |
560 |
|
✗ |
array = g_ptr_array_new_with_free_func (g_free); |
561 |
|
✗ |
while (g_variant_iter_loop (iter, "(ddd)", |
562 |
|
|
&color.R, |
563 |
|
|
&color.G, |
564 |
|
|
&color.B)) |
565 |
|
|
{ |
566 |
|
✗ |
color_tmp = cd_color_rgb_new (); |
567 |
|
✗ |
cd_color_rgb_copy (&color, color_tmp); |
568 |
|
✗ |
g_ptr_array_add (array, color_tmp); |
569 |
|
|
} |
570 |
|
✗ |
ret = cc_color_calibrate_calib_set_output_gamma (calibrate, |
571 |
|
|
array, |
572 |
|
|
&error); |
573 |
|
✗ |
if (!ret) |
574 |
|
|
{ |
575 |
|
✗ |
g_warning ("failed to update gamma: %s", |
576 |
|
|
error->message); |
577 |
|
✗ |
return; |
578 |
|
|
} |
579 |
|
✗ |
return; |
580 |
|
|
} |
581 |
|
✗ |
g_warning ("got unknown signal %s", signal_name); |
582 |
|
|
} |
583 |
|
|
|
584 |
|
|
static void |
585 |
|
✗ |
cc_color_calibrate_cancel (CcColorCalibrate *calibrate) |
586 |
|
|
{ |
587 |
|
✗ |
g_autoptr(GVariant) retval = NULL; |
588 |
|
✗ |
g_autoptr(GError) error = NULL; |
589 |
|
|
|
590 |
|
|
/* cancel the calibration to ensure the helper quits */ |
591 |
|
✗ |
retval = g_dbus_proxy_call_sync (calibrate->proxy_helper, |
592 |
|
|
"Cancel", |
593 |
|
|
NULL, |
594 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
595 |
|
|
-1, |
596 |
|
|
NULL, |
597 |
|
|
&error); |
598 |
|
✗ |
if (retval == NULL) |
599 |
|
✗ |
g_warning ("Failed to send Cancel: %s", error->message); |
600 |
|
|
|
601 |
|
|
/* return */ |
602 |
|
✗ |
g_main_loop_quit (calibrate->loop); |
603 |
|
✗ |
} |
604 |
|
|
|
605 |
|
|
static void |
606 |
|
✗ |
cc_color_calibrate_button_done_cb (CcColorCalibrate *calibrate) |
607 |
|
|
{ |
608 |
|
✗ |
g_main_loop_quit (calibrate->loop); |
609 |
|
✗ |
} |
610 |
|
|
|
611 |
|
|
static void |
612 |
|
✗ |
cc_color_calibrate_button_start_cb (CcColorCalibrate *calibrate) |
613 |
|
|
{ |
614 |
|
|
GtkWidget *widget; |
615 |
|
✗ |
g_autoptr(GError) error = NULL; |
616 |
|
✗ |
g_autoptr(GVariant) retval = NULL; |
617 |
|
|
|
618 |
|
|
/* set correct buttons */ |
619 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
620 |
|
|
"button_start")); |
621 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
622 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
623 |
|
|
"button_resume")); |
624 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
625 |
|
|
|
626 |
|
|
/* continue */ |
627 |
|
✗ |
retval = g_dbus_proxy_call_sync (calibrate->proxy_helper, |
628 |
|
|
"Resume", |
629 |
|
|
NULL, |
630 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
631 |
|
|
-1, |
632 |
|
|
NULL, |
633 |
|
|
&error); |
634 |
|
✗ |
if (retval == NULL) |
635 |
|
✗ |
g_warning ("Failed to send Resume: %s", error->message); |
636 |
|
✗ |
} |
637 |
|
|
|
638 |
|
|
static void |
639 |
|
✗ |
cc_color_calibrate_button_cancel_cb (CcColorCalibrate *calibrate) |
640 |
|
|
{ |
641 |
|
✗ |
cc_color_calibrate_cancel (calibrate); |
642 |
|
✗ |
} |
643 |
|
|
|
644 |
|
|
#if 0 |
645 |
|
|
static gboolean |
646 |
|
|
cc_color_calibrate_alpha_window_draw (CcColorCalibrate *calibrate, cairo_t *cr) |
647 |
|
|
{ |
648 |
|
|
GtkWidget *widget; |
649 |
|
|
|
650 |
|
|
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
651 |
|
|
"dialog_calibrate")); |
652 |
|
|
|
653 |
|
|
if (gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)) && |
654 |
|
|
gdk_screen_is_composited (gtk_widget_get_screen (widget))) |
655 |
|
|
{ |
656 |
|
|
/* transparent */ |
657 |
|
|
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, CALIBRATE_WINDOW_OPACITY); |
658 |
|
|
} |
659 |
|
|
else |
660 |
|
|
{ |
661 |
|
|
/* opaque black */ |
662 |
|
|
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); |
663 |
|
|
} |
664 |
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); |
665 |
|
|
cairo_paint (cr); |
666 |
|
|
return FALSE; |
667 |
|
|
} |
668 |
|
|
|
669 |
|
|
static void |
670 |
|
|
cc_color_calibrate_alpha_screen_changed_cb (CcColorCalibrate *calibrate) |
671 |
|
|
{ |
672 |
|
|
GtkWidget *window; |
673 |
|
|
GdkScreen *screen; |
674 |
|
|
GdkVisual *visual; |
675 |
|
|
|
676 |
|
|
window = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
677 |
|
|
"dialog_calibrate")); |
678 |
|
|
screen = gtk_widget_get_screen (GTK_WIDGET (window)); |
679 |
|
|
visual = gdk_screen_get_rgba_visual (screen); |
680 |
|
|
if (visual == NULL) |
681 |
|
|
visual = gdk_screen_get_system_visual (screen); |
682 |
|
|
gtk_widget_set_visual (GTK_WIDGET (window), visual); |
683 |
|
|
} |
684 |
|
|
#endif |
685 |
|
|
|
686 |
|
|
static void |
687 |
|
✗ |
cc_color_calibrate_uninhibit (CcColorCalibrate *calibrate) |
688 |
|
|
{ |
689 |
|
|
GtkApplication *application; |
690 |
|
|
|
691 |
|
✗ |
if (calibrate->inhibit_fd != -1) |
692 |
|
|
{ |
693 |
|
✗ |
close (calibrate->inhibit_fd); |
694 |
|
✗ |
calibrate->inhibit_fd = -1; |
695 |
|
|
} |
696 |
|
|
|
697 |
|
✗ |
if (calibrate->inhibit_cookie != 0) |
698 |
|
|
{ |
699 |
|
✗ |
application = GTK_APPLICATION (g_application_get_default ()); |
700 |
|
✗ |
gtk_application_uninhibit (application, calibrate->inhibit_cookie); |
701 |
|
✗ |
calibrate->inhibit_cookie = 0; |
702 |
|
|
} |
703 |
|
✗ |
} |
704 |
|
|
|
705 |
|
|
static void |
706 |
|
✗ |
cc_color_calibrate_inhibit (CcColorCalibrate *calibrate, GtkWindow *window) |
707 |
|
|
{ |
708 |
|
✗ |
g_autoptr(GError) error = NULL; |
709 |
|
|
gint idx; |
710 |
|
✗ |
g_autoptr(GUnixFDList) fd_list = NULL; |
711 |
|
✗ |
g_autoptr(GVariant) retval = NULL; |
712 |
|
|
GtkApplication *application; |
713 |
|
|
|
714 |
|
|
/* inhibit basically everything we can */ |
715 |
|
✗ |
application = GTK_APPLICATION (g_application_get_default ()); |
716 |
|
✗ |
calibrate->inhibit_cookie = gtk_application_inhibit (application, |
717 |
|
|
window, |
718 |
|
|
GTK_APPLICATION_INHIBIT_LOGOUT | |
719 |
|
|
GTK_APPLICATION_INHIBIT_SWITCH | |
720 |
|
|
GTK_APPLICATION_INHIBIT_SUSPEND | |
721 |
|
|
GTK_APPLICATION_INHIBIT_IDLE, |
722 |
|
|
"Display calibration in progress"); |
723 |
|
|
|
724 |
|
|
/* tell logind to disallow the lid switch */ |
725 |
|
✗ |
retval = g_dbus_proxy_call_with_unix_fd_list_sync (calibrate->proxy_inhibit, |
726 |
|
|
"Inhibit", |
727 |
|
|
g_variant_new ("(ssss)", |
728 |
|
|
"shutdown:" |
729 |
|
|
"sleep:" |
730 |
|
|
"idle:" |
731 |
|
|
"handle-lid-switch", |
732 |
|
|
"Display Calibrator", |
733 |
|
|
"Display calibration in progress", |
734 |
|
|
"block"), |
735 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
736 |
|
|
-1, |
737 |
|
|
NULL, |
738 |
|
|
&fd_list, |
739 |
|
|
NULL, |
740 |
|
|
&error); |
741 |
|
✗ |
if (retval == NULL) |
742 |
|
|
{ |
743 |
|
✗ |
g_warning ("Failed to send Inhibit: %s", error->message); |
744 |
|
✗ |
return; |
745 |
|
|
} |
746 |
|
✗ |
g_variant_get (retval, "(h)", &idx); |
747 |
|
✗ |
calibrate->inhibit_fd = g_unix_fd_list_get (fd_list, idx, &error); |
748 |
|
✗ |
if (calibrate->inhibit_fd == -1) |
749 |
|
|
{ |
750 |
|
✗ |
g_warning ("Failed to receive system inhibitor fd: %s", error->message); |
751 |
|
✗ |
return; |
752 |
|
|
} |
753 |
|
✗ |
g_debug ("System inhibitor fd is %d", calibrate->inhibit_fd); |
754 |
|
|
} |
755 |
|
|
|
756 |
|
|
gboolean |
757 |
|
✗ |
cc_color_calibrate_setup (CcColorCalibrate *calibrate, |
758 |
|
|
GError **error) |
759 |
|
|
{ |
760 |
|
✗ |
gboolean ret = TRUE; |
761 |
|
|
|
762 |
|
✗ |
g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), FALSE); |
763 |
|
✗ |
g_return_val_if_fail (calibrate->device_kind != CD_SENSOR_CAP_UNKNOWN, FALSE); |
764 |
|
|
|
765 |
|
|
/* use logind to disable system state idle */ |
766 |
|
✗ |
calibrate->proxy_inhibit = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
767 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
768 |
|
|
NULL, |
769 |
|
|
"org.freedesktop.login1", |
770 |
|
|
"/org/freedesktop/login1", |
771 |
|
|
"org.freedesktop.login1.Manager", |
772 |
|
|
NULL, |
773 |
|
|
error); |
774 |
|
✗ |
if (calibrate->proxy_inhibit == NULL) |
775 |
|
|
{ |
776 |
|
✗ |
ret = FALSE; |
777 |
|
✗ |
goto out; |
778 |
|
|
} |
779 |
|
|
|
780 |
|
|
/* start the calibration session daemon */ |
781 |
|
✗ |
calibrate->proxy_helper = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, |
782 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
783 |
|
|
NULL, |
784 |
|
|
CD_SESSION_DBUS_SERVICE, |
785 |
|
|
CD_SESSION_DBUS_PATH, |
786 |
|
|
CD_SESSION_DBUS_INTERFACE_DISPLAY, |
787 |
|
|
NULL, |
788 |
|
|
error); |
789 |
|
✗ |
if (calibrate->proxy_helper == NULL) |
790 |
|
|
{ |
791 |
|
✗ |
ret = FALSE; |
792 |
|
✗ |
goto out; |
793 |
|
|
} |
794 |
|
✗ |
g_signal_connect_object (calibrate->proxy_helper, |
795 |
|
|
"g-properties-changed", |
796 |
|
|
G_CALLBACK (cc_color_calibrate_property_changed_cb), |
797 |
|
|
calibrate, G_CONNECT_SWAPPED); |
798 |
|
✗ |
g_signal_connect_object (calibrate->proxy_helper, |
799 |
|
|
"g-signal", |
800 |
|
|
G_CALLBACK (cc_color_calibrate_signal_cb), |
801 |
|
|
calibrate, G_CONNECT_SWAPPED); |
802 |
|
✗ |
out: |
803 |
|
✗ |
return ret; |
804 |
|
|
} |
805 |
|
|
|
806 |
|
|
gboolean |
807 |
|
✗ |
cc_color_calibrate_start (CcColorCalibrate *calibrate, |
808 |
|
|
GtkWindow *parent, |
809 |
|
|
GError **error) |
810 |
|
|
{ |
811 |
|
|
const gchar *name; |
812 |
|
|
GtkWidget *widget; |
813 |
|
|
GtkWindow *window; |
814 |
|
|
GVariantBuilder builder; |
815 |
|
✗ |
g_autoptr(GVariant) retval = NULL; |
816 |
|
|
|
817 |
|
✗ |
g_return_val_if_fail (CC_IS_COLOR_CALIBRATE (calibrate), FALSE); |
818 |
|
|
|
819 |
|
|
/* get screen */ |
820 |
|
✗ |
name = cd_device_get_metadata_item (calibrate->device, |
821 |
|
|
CD_DEVICE_METADATA_XRANDR_NAME); |
822 |
|
✗ |
if (!cc_color_calibrate_calib_setup_screen (calibrate, name, error)) |
823 |
|
✗ |
return FALSE; |
824 |
|
|
|
825 |
|
✗ |
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); |
826 |
|
✗ |
g_variant_builder_add (&builder, |
827 |
|
|
"{sv}", |
828 |
|
|
"Quality", |
829 |
|
✗ |
g_variant_new_uint32 (calibrate->quality)); |
830 |
|
✗ |
g_variant_builder_add (&builder, |
831 |
|
|
"{sv}", |
832 |
|
|
"Whitepoint", |
833 |
|
|
g_variant_new_uint32 (calibrate->target_whitepoint)); |
834 |
|
✗ |
g_variant_builder_add (&builder, |
835 |
|
|
"{sv}", |
836 |
|
|
"Gamma", |
837 |
|
|
g_variant_new_double (calibrate->target_gamma)); |
838 |
|
✗ |
g_variant_builder_add (&builder, |
839 |
|
|
"{sv}", |
840 |
|
|
"Title", |
841 |
|
✗ |
g_variant_new_string (calibrate->title)); |
842 |
|
✗ |
g_variant_builder_add (&builder, |
843 |
|
|
"{sv}", |
844 |
|
|
"DeviceKind", |
845 |
|
✗ |
g_variant_new_uint32 (calibrate->device_kind)); |
846 |
|
✗ |
retval = g_dbus_proxy_call_sync (calibrate->proxy_helper, |
847 |
|
|
"Start", |
848 |
|
|
g_variant_new ("(ssa{sv})", |
849 |
|
|
cd_device_get_id (calibrate->device), |
850 |
|
|
cd_sensor_get_id (calibrate->sensor), |
851 |
|
|
&builder), |
852 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
853 |
|
|
-1, |
854 |
|
|
NULL, |
855 |
|
|
error); |
856 |
|
✗ |
if (retval == NULL) |
857 |
|
✗ |
return FALSE; |
858 |
|
|
|
859 |
|
|
/* set this above our parent */ |
860 |
|
✗ |
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder, |
861 |
|
|
"dialog_calibrate")); |
862 |
|
✗ |
gtk_window_set_modal (window, TRUE); |
863 |
|
✗ |
gtk_window_present (window); |
864 |
|
|
|
865 |
|
|
/* show correct buttons */ |
866 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
867 |
|
|
"button_cancel")); |
868 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
869 |
|
|
"button_start")); |
870 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
871 |
|
|
"button_resume")); |
872 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
873 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
874 |
|
|
"button_done")); |
875 |
|
✗ |
gtk_widget_set_visible (widget, FALSE); |
876 |
|
|
|
877 |
|
|
/* stop the computer from auto-suspending or turning off the screen */ |
878 |
|
✗ |
cc_color_calibrate_inhibit (calibrate, parent); |
879 |
|
|
|
880 |
|
✗ |
g_main_loop_run (calibrate->loop); |
881 |
|
✗ |
gtk_window_close (window); |
882 |
|
|
|
883 |
|
|
/* we can go idle now */ |
884 |
|
✗ |
cc_color_calibrate_uninhibit (calibrate); |
885 |
|
|
|
886 |
|
|
/* see if we failed */ |
887 |
|
✗ |
if (calibrate->session_error_code != CD_SESSION_ERROR_NONE) |
888 |
|
|
{ |
889 |
|
✗ |
g_set_error_literal (error, |
890 |
|
|
CD_SESSION_ERROR, |
891 |
|
|
CD_SESSION_ERROR_INTERNAL, |
892 |
|
|
"failed to calibrate"); |
893 |
|
✗ |
return FALSE; |
894 |
|
|
} |
895 |
|
|
|
896 |
|
✗ |
return TRUE; |
897 |
|
|
} |
898 |
|
|
|
899 |
|
|
static void |
900 |
|
✗ |
cc_color_calibrate_finalize (GObject *object) |
901 |
|
|
{ |
902 |
|
✗ |
CcColorCalibrate *calibrate = CC_COLOR_CALIBRATE (object); |
903 |
|
|
|
904 |
|
✗ |
g_clear_pointer (&calibrate->window, gtk_window_destroy); |
905 |
|
✗ |
g_clear_object (&calibrate->builder); |
906 |
|
✗ |
g_clear_object (&calibrate->device); |
907 |
|
✗ |
g_clear_object (&calibrate->proxy_helper); |
908 |
|
✗ |
g_clear_object (&calibrate->proxy_inhibit); |
909 |
|
✗ |
g_clear_object (&calibrate->sensor); |
910 |
|
✗ |
g_clear_object (&calibrate->x11_screen); |
911 |
|
✗ |
g_free (calibrate->title); |
912 |
|
✗ |
g_main_loop_unref (calibrate->loop); |
913 |
|
|
|
914 |
|
✗ |
G_OBJECT_CLASS (cc_color_calibrate_parent_class)->finalize (object); |
915 |
|
✗ |
} |
916 |
|
|
|
917 |
|
|
static void |
918 |
|
✗ |
cc_color_calibrate_class_init (CcColorCalibrateClass *klass) |
919 |
|
|
{ |
920 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
921 |
|
✗ |
object_class->finalize = cc_color_calibrate_finalize; |
922 |
|
✗ |
} |
923 |
|
|
|
924 |
|
|
static void |
925 |
|
✗ |
cc_color_calibrate_init (CcColorCalibrate *calibrate) |
926 |
|
|
{ |
927 |
|
✗ |
g_autoptr(GError) error = NULL; |
928 |
|
|
gint retval; |
929 |
|
✗ |
g_autoptr(GSettings) settings = NULL; |
930 |
|
|
GtkBox *box; |
931 |
|
|
GtkWidget *widget; |
932 |
|
|
GtkWindow *window; |
933 |
|
|
|
934 |
|
✗ |
calibrate->loop = g_main_loop_new (NULL, FALSE); |
935 |
|
✗ |
calibrate->inhibit_fd = -1; |
936 |
|
|
|
937 |
|
|
/* load UI */ |
938 |
|
✗ |
calibrate->builder = gtk_builder_new (); |
939 |
|
✗ |
retval = gtk_builder_add_from_resource (calibrate->builder, |
940 |
|
|
"/org/gnome/control-center/color/cc-color-calibrate.ui", |
941 |
|
|
&error); |
942 |
|
✗ |
if (retval == 0) |
943 |
|
✗ |
g_warning ("Could not load interface: %s", error->message); |
944 |
|
|
|
945 |
|
|
/* add sample widget */ |
946 |
|
✗ |
box = GTK_BOX (gtk_builder_get_object (calibrate->builder, |
947 |
|
|
"vbox_status")); |
948 |
|
✗ |
calibrate->sample_widget = cd_sample_widget_new (); |
949 |
|
✗ |
gtk_widget_set_size_request (calibrate->sample_widget, 400, 400); |
950 |
|
✗ |
gtk_box_prepend (box, calibrate->sample_widget); |
951 |
|
✗ |
gtk_widget_set_vexpand (calibrate->sample_widget, FALSE); |
952 |
|
✗ |
gtk_widget_set_hexpand (calibrate->sample_widget, FALSE); |
953 |
|
|
|
954 |
|
|
/* get defaults */ |
955 |
|
✗ |
settings = g_settings_new (COLORD_SETTINGS_SCHEMA); |
956 |
|
✗ |
calibrate->target_whitepoint = g_settings_get_int (settings, "display-whitepoint"); |
957 |
|
✗ |
calibrate->target_gamma = g_settings_get_double (settings, "display-gamma"); |
958 |
|
|
|
959 |
|
|
/* connect to buttons */ |
960 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
961 |
|
|
"button_start")); |
962 |
|
✗ |
g_signal_connect_object (widget, "clicked", |
963 |
|
|
G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate, G_CONNECT_SWAPPED); |
964 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
965 |
|
|
"button_resume")); |
966 |
|
✗ |
g_signal_connect_object (widget, "clicked", |
967 |
|
|
G_CALLBACK (cc_color_calibrate_button_start_cb), calibrate, G_CONNECT_SWAPPED); |
968 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
969 |
|
|
"button_done")); |
970 |
|
✗ |
g_signal_connect_object (widget, "clicked", |
971 |
|
|
G_CALLBACK (cc_color_calibrate_button_done_cb), calibrate, G_CONNECT_SWAPPED); |
972 |
|
✗ |
widget = GTK_WIDGET (gtk_builder_get_object (calibrate->builder, |
973 |
|
|
"button_cancel")); |
974 |
|
✗ |
g_signal_connect_object (widget, "clicked", |
975 |
|
|
G_CALLBACK (cc_color_calibrate_button_cancel_cb), calibrate, G_CONNECT_SWAPPED); |
976 |
|
✗ |
gtk_widget_set_visible (widget, TRUE); |
977 |
|
|
|
978 |
|
|
/* setup the specialist calibration window */ |
979 |
|
✗ |
window = GTK_WINDOW (gtk_builder_get_object (calibrate->builder, |
980 |
|
|
"dialog_calibrate")); |
981 |
|
✗ |
calibrate->window = window; |
982 |
|
✗ |
} |
983 |
|
|
|
984 |
|
|
CcColorCalibrate * |
985 |
|
✗ |
cc_color_calibrate_new (void) |
986 |
|
|
{ |
987 |
|
|
CcColorCalibrate *calibrate; |
988 |
|
✗ |
calibrate = g_object_new (CC_TYPE_COLOR_CALIBRATE, NULL); |
989 |
|
✗ |
return CC_COLOR_CALIBRATE (calibrate); |
990 |
|
|
} |
991 |
|
|
|