File: | rc/gs-fade.c |
Warning: | line 504, column 10 Access of the heap area at index 0, while it holds only 0 'struct GSGammaInfo' element |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- | |||
2 | * | |||
3 | * Copyright (C) 2004-2009 William Jon McCann <mccann@jhu.edu> | |||
4 | * Copyright (C) 2009 Red Hat, Inc. | |||
5 | * | |||
6 | * This program is free software; you can redistribute it and/or modify | |||
7 | * it under the terms of the GNU General Public License as published by | |||
8 | * the Free Software Foundation; either version 2 of the License, or | |||
9 | * (at your option) any later version. | |||
10 | * | |||
11 | * This program is distributed in the hope that it will be useful, | |||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
14 | * GNU General Public License for more details. | |||
15 | * | |||
16 | * You should have received a copy of the GNU General Public License | |||
17 | * along with this program; if not, write to the Free Software | |||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |||
19 | * | |||
20 | * Authors: William Jon McCann <mccann@jhu.edu> | |||
21 | * | |||
22 | */ | |||
23 | ||||
24 | #include "config.h" | |||
25 | ||||
26 | #include <stdlib.h> | |||
27 | #include <stdio.h> | |||
28 | #include <time.h> | |||
29 | #include <errno(*__errno_location ()).h> | |||
30 | ||||
31 | #include <string.h> | |||
32 | #include <sys/time.h> | |||
33 | #include <sys/types.h> | |||
34 | #ifdef HAVE_UNISTD_H1 | |||
35 | #include <unistd.h> | |||
36 | #endif /* HAVE_UNISTD_H */ | |||
37 | ||||
38 | #include <cdk/cdkx.h> | |||
39 | #include <ctk/ctk.h> | |||
40 | ||||
41 | #include "gs-fade.h" | |||
42 | #include "gs-debug.h" | |||
43 | ||||
44 | #define CAFE_DESKTOP_USE_UNSTABLE_API | |||
45 | ||||
46 | #include "libcafe-desktop/cafe-rr.h" | |||
47 | ||||
48 | /* XFree86 4.x+ Gamma fading */ | |||
49 | ||||
50 | ||||
51 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
52 | ||||
53 | #include <X11/extensions/xf86vmode.h> | |||
54 | ||||
55 | #define XF86_MIN_GAMMA0.1 0.1 | |||
56 | ||||
57 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
58 | ||||
59 | static void gs_fade_finalize (GObject *object); | |||
60 | ||||
61 | struct GSGammaInfo | |||
62 | { | |||
63 | int size; | |||
64 | unsigned short *r; | |||
65 | unsigned short *g; | |||
66 | unsigned short *b; | |||
67 | }; | |||
68 | ||||
69 | struct GSFadeScreenPrivate | |||
70 | { | |||
71 | int fade_type; | |||
72 | int num_ramps; | |||
73 | /* one per crtc in randr mode */ | |||
74 | struct GSGammaInfo *info; | |||
75 | /* one per screen in theory */ | |||
76 | CafeRRScreen *rrscreen; | |||
77 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
78 | /* one per screen also */ | |||
79 | XF86VidModeGamma vmg; | |||
80 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
81 | gboolean (*fade_setup) (GSFade *fade); | |||
82 | gboolean (*fade_set_alpha_gamma) (GSFade *fade, | |||
83 | gdouble alpha); | |||
84 | void (*fade_finish) (GSFade *fade); | |||
85 | }; | |||
86 | ||||
87 | struct GSFadePrivate | |||
88 | { | |||
89 | guint enabled : 1; | |||
90 | guint active : 1; | |||
91 | ||||
92 | guint timeout; | |||
93 | ||||
94 | guint step; | |||
95 | guint num_steps; | |||
96 | guint timer_id; | |||
97 | ||||
98 | gdouble alpha_per_iter; | |||
99 | gdouble current_alpha; | |||
100 | ||||
101 | struct GSFadeScreenPrivate screen_priv; | |||
102 | }; | |||
103 | ||||
104 | enum | |||
105 | { | |||
106 | FADED, | |||
107 | LAST_SIGNAL | |||
108 | }; | |||
109 | ||||
110 | enum | |||
111 | { | |||
112 | FADE_TYPE_NONE, | |||
113 | FADE_TYPE_GAMMA_NUMBER, | |||
114 | FADE_TYPE_GAMMA_RAMP, | |||
115 | FADE_TYPE_XRANDR, | |||
116 | }; | |||
117 | ||||
118 | static guint signals [LAST_SIGNAL] = { 0, }; | |||
119 | ||||
120 | G_DEFINE_TYPE_WITH_PRIVATE (GSFade, gs_fade, G_TYPE_OBJECT)static void gs_fade_init (GSFade *self); static void gs_fade_class_init (GSFadeClass *klass); static GType gs_fade_get_type_once (void ); static gpointer gs_fade_parent_class = ((void*)0); static gint GSFade_private_offset; static void gs_fade_class_intern_init (gpointer klass) { gs_fade_parent_class = g_type_class_peek_parent (klass); if (GSFade_private_offset != 0) g_type_class_adjust_private_offset (klass, &GSFade_private_offset); gs_fade_class_init ((GSFadeClass *) klass); } __attribute__ ((__unused__)) static inline gpointer gs_fade_get_instance_private (GSFade *self) { return (((gpointer ) ((guint8*) (self) + (glong) (GSFade_private_offset)))); } GType gs_fade_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); (void ) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*) 0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = gs_fade_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType gs_fade_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple (((GType) ( (20) << (2))), g_intern_static_string ("GSFade"), sizeof (GSFadeClass), (GClassInitFunc)(void (*)(void)) gs_fade_class_intern_init , sizeof (GSFade), (GInstanceInitFunc)(void (*)(void)) gs_fade_init , (GTypeFlags) 0); { {{ GSFade_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (GSFadePrivate)); };} } return g_define_type_id ; } | |||
121 | ||||
122 | static gpointer fade_object = NULL((void*)0); | |||
123 | ||||
124 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
125 | ||||
126 | /* This is needed because the VidMode extension doesn't work | |||
127 | on remote displays -- but if the remote display has the extension | |||
128 | at all, XF86VidModeQueryExtension returns true, and then | |||
129 | XF86VidModeQueryVersion dies with an X error. | |||
130 | */ | |||
131 | ||||
132 | static gboolean error_handler_hit = FALSE(0); | |||
133 | ||||
134 | static int | |||
135 | ignore_all_errors_ehandler (Display *dpy, | |||
136 | XErrorEvent *error) | |||
137 | { | |||
138 | error_handler_hit = TRUE(!(0)); | |||
139 | ||||
140 | return 0; | |||
141 | } | |||
142 | ||||
143 | static Boolint | |||
144 | safe_XF86VidModeQueryVersion (Display *dpy, | |||
145 | int *majP, | |||
146 | int *minP) | |||
147 | { | |||
148 | Boolint result; | |||
149 | XErrorHandler old_handler; | |||
150 | ||||
151 | XSync (dpy, False0); | |||
152 | error_handler_hit = FALSE(0); | |||
153 | old_handler = XSetErrorHandler (ignore_all_errors_ehandler); | |||
154 | ||||
155 | result = XF86VidModeQueryVersion (dpy, majP, minP); | |||
156 | ||||
157 | XSync (dpy, False0); | |||
158 | XSetErrorHandler (old_handler); | |||
159 | XSync (dpy, False0); | |||
160 | ||||
161 | return (error_handler_hit | |||
162 | ? False0 | |||
163 | : result); | |||
164 | } | |||
165 | ||||
166 | static gboolean | |||
167 | xf86_whack_gamma (int screen, | |||
168 | struct GSFadeScreenPrivate *screen_priv, | |||
169 | float ratio) | |||
170 | { | |||
171 | Boolint status; | |||
172 | struct GSGammaInfo *gamma_info; | |||
173 | CdkDisplay *display; | |||
174 | ||||
175 | gamma_info = screen_priv->info; | |||
176 | ||||
177 | if (!gamma_info) | |||
178 | return FALSE(0); | |||
179 | ||||
180 | if (ratio < 0) | |||
181 | { | |||
182 | ratio = 0; | |||
183 | } | |||
184 | if (ratio > 1) | |||
185 | { | |||
186 | ratio = 1; | |||
187 | } | |||
188 | ||||
189 | if (gamma_info->size == 0) | |||
190 | { | |||
191 | /* we only have a gamma number, not a ramp. */ | |||
192 | ||||
193 | XF86VidModeGamma g2; | |||
194 | ||||
195 | g2.red = screen_priv->vmg.red * ratio; | |||
196 | g2.green = screen_priv->vmg.green * ratio; | |||
197 | g2.blue = screen_priv->vmg.blue * ratio; | |||
198 | ||||
199 | if (g2.red < XF86_MIN_GAMMA0.1) | |||
200 | { | |||
201 | g2.red = XF86_MIN_GAMMA0.1; | |||
202 | } | |||
203 | if (g2.green < XF86_MIN_GAMMA0.1) | |||
204 | { | |||
205 | g2.green = XF86_MIN_GAMMA0.1; | |||
206 | } | |||
207 | if (g2.blue < XF86_MIN_GAMMA0.1) | |||
208 | { | |||
209 | g2.blue = XF86_MIN_GAMMA0.1; | |||
210 | } | |||
211 | ||||
212 | status = XF86VidModeSetGamma (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), screen, &g2); | |||
213 | } | |||
214 | else | |||
215 | { | |||
216 | ||||
217 | # ifdef HAVE_XF86VMODE_GAMMA_RAMP1 | |||
218 | unsigned short *r, *g, *b; | |||
219 | int i; | |||
220 | ||||
221 | r = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
222 | g = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
223 | b = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
224 | ||||
225 | for (i = 0; i < gamma_info->size; i++) | |||
226 | { | |||
227 | r[i] = gamma_info->r[i] * ratio; | |||
228 | g[i] = gamma_info->g[i] * ratio; | |||
229 | b[i] = gamma_info->b[i] * ratio; | |||
230 | } | |||
231 | ||||
232 | status = XF86VidModeSetGammaRamp (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), screen, gamma_info->size, r, g, b); | |||
233 | ||||
234 | g_free (r); | |||
235 | g_free (g); | |||
236 | g_free (b); | |||
237 | ||||
238 | # else /* !HAVE_XF86VMODE_GAMMA_RAMP */ | |||
239 | abort (); | |||
240 | # endif /* !HAVE_XF86VMODE_GAMMA_RAMP */ | |||
241 | } | |||
242 | ||||
243 | display = cdk_display_get_default (); | |||
244 | cdk_display_flush (display); | |||
245 | ||||
246 | return status; | |||
247 | } | |||
248 | ||||
249 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
250 | ||||
251 | /* VidModeExtension version 2.0 or better is needed to do gamma. | |||
252 | 2.0 added gamma values; 2.1 added gamma ramps. | |||
253 | */ | |||
254 | # define XF86_VIDMODE_GAMMA_MIN_MAJOR2 2 | |||
255 | # define XF86_VIDMODE_GAMMA_MIN_MINOR0 0 | |||
256 | # define XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR2 2 | |||
257 | # define XF86_VIDMODE_GAMMA_RAMP_MIN_MINOR1 1 | |||
258 | ||||
259 | ||||
260 | gboolean | |||
261 | gs_fade_get_enabled (GSFade *fade) | |||
262 | { | |||
263 | g_return_val_if_fail (GS_IS_FADE (fade), FALSE)do{ (void)0; }while (0); | |||
264 | ||||
265 | return fade->priv->enabled; | |||
266 | } | |||
267 | ||||
268 | void | |||
269 | gs_fade_set_enabled (GSFade *fade, | |||
270 | gboolean enabled) | |||
271 | { | |||
272 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
273 | ||||
274 | if (fade->priv->enabled != enabled) | |||
275 | { | |||
276 | fade->priv->enabled = enabled; | |||
277 | } | |||
278 | } | |||
279 | ||||
280 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
281 | static gboolean | |||
282 | gamma_fade_setup (GSFade *fade) | |||
283 | { | |||
284 | gboolean res; | |||
285 | struct GSFadeScreenPrivate *screen_priv; | |||
286 | ||||
287 | screen_priv = &fade->priv->screen_priv; | |||
288 | ||||
289 | if (screen_priv->info) | |||
290 | return TRUE(!(0)); | |||
291 | ||||
292 | # ifndef HAVE_XF86VMODE_GAMMA_RAMP1 | |||
293 | if (FADE_TYPE_GAMMA_RAMP == screen_priv->fade_type) | |||
294 | { | |||
295 | /* server is newer than client! */ | |||
296 | screen_priv->fade_type = FADE_TYPE_GAMMA_NUMBER; | |||
297 | } | |||
298 | # endif | |||
299 | ||||
300 | # ifdef HAVE_XF86VMODE_GAMMA_RAMP1 | |||
301 | ||||
302 | screen_priv->info = g_new0(struct GSGammaInfo, 1)((struct GSGammaInfo *) g_malloc0_n ((1), sizeof (struct GSGammaInfo ))); | |||
303 | screen_priv->num_ramps = 1; | |||
304 | ||||
305 | if (FADE_TYPE_GAMMA_RAMP == screen_priv->fade_type) | |||
306 | { | |||
307 | /* have ramps */ | |||
308 | ||||
309 | ||||
310 | res = XF86VidModeGetGammaRampSize (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), | |||
311 | CDK_SCREEN_XNUMBER (cdk_screen_get_default ())(cdk_x11_screen_get_screen_number (cdk_screen_get_default ()) ), | |||
312 | &screen_priv->info->size); | |||
313 | if (!res || screen_priv->info->size <= 0) | |||
314 | { | |||
315 | screen_priv->fade_type = FADE_TYPE_GAMMA_NUMBER; | |||
316 | goto test_number; | |||
317 | } | |||
318 | ||||
319 | screen_priv->info->r = g_new0 (unsigned short, screen_priv->info->size)((unsigned short *) g_malloc0_n ((screen_priv->info->size ), sizeof (unsigned short))); | |||
320 | screen_priv->info->g = g_new0 (unsigned short, screen_priv->info->size)((unsigned short *) g_malloc0_n ((screen_priv->info->size ), sizeof (unsigned short))); | |||
321 | screen_priv->info->b = g_new0 (unsigned short, screen_priv->info->size)((unsigned short *) g_malloc0_n ((screen_priv->info->size ), sizeof (unsigned short))); | |||
322 | ||||
323 | if (! (screen_priv->info->r && screen_priv->info->g && screen_priv->info->b)) | |||
324 | { | |||
325 | screen_priv->fade_type = FADE_TYPE_GAMMA_NUMBER; | |||
326 | goto test_number; | |||
327 | } | |||
328 | ||||
329 | res = XF86VidModeGetGammaRamp (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), | |||
330 | CDK_SCREEN_XNUMBER (cdk_screen_get_default ())(cdk_x11_screen_get_screen_number (cdk_screen_get_default ()) ), | |||
331 | screen_priv->info->size, | |||
332 | screen_priv->info->r, | |||
333 | screen_priv->info->g, | |||
334 | screen_priv->info->b); | |||
335 | if (! res) | |||
336 | { | |||
337 | screen_priv->fade_type = FADE_TYPE_GAMMA_NUMBER; | |||
338 | goto test_number; | |||
339 | } | |||
340 | gs_debug ("Initialized gamma ramp fade")gs_debug_real (__func__, "gs-fade.c", 340, "Initialized gamma ramp fade" ); | |||
341 | } | |||
342 | # endif /* HAVE_XF86VMODE_GAMMA_RAMP */ | |||
343 | ||||
344 | test_number: | |||
345 | if (FADE_TYPE_GAMMA_NUMBER == screen_priv->fade_type) | |||
346 | { | |||
347 | /* only have gamma parameter, not ramps. */ | |||
348 | ||||
349 | res = XF86VidModeGetGamma (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), | |||
350 | CDK_SCREEN_XNUMBER (cdk_screen_get_default ())(cdk_x11_screen_get_screen_number (cdk_screen_get_default ()) ), | |||
351 | &screen_priv->vmg); | |||
352 | if (! res) | |||
353 | { | |||
354 | screen_priv->fade_type = FADE_TYPE_NONE; | |||
355 | goto test_none; | |||
356 | } | |||
357 | gs_debug ("Initialized gamma fade: %f %f %f",gs_debug_real (__func__, "gs-fade.c", 360, "Initialized gamma fade: %f %f %f" , screen_priv->vmg.red, screen_priv->vmg.green, screen_priv ->vmg.blue) | |||
358 | screen_priv->vmg.red,gs_debug_real (__func__, "gs-fade.c", 360, "Initialized gamma fade: %f %f %f" , screen_priv->vmg.red, screen_priv->vmg.green, screen_priv ->vmg.blue) | |||
359 | screen_priv->vmg.green,gs_debug_real (__func__, "gs-fade.c", 360, "Initialized gamma fade: %f %f %f" , screen_priv->vmg.red, screen_priv->vmg.green, screen_priv ->vmg.blue) | |||
360 | screen_priv->vmg.blue)gs_debug_real (__func__, "gs-fade.c", 360, "Initialized gamma fade: %f %f %f" , screen_priv->vmg.red, screen_priv->vmg.green, screen_priv ->vmg.blue); | |||
361 | } | |||
362 | ||||
363 | test_none: | |||
364 | if (FADE_TYPE_NONE == screen_priv->fade_type) | |||
365 | { | |||
366 | goto FAIL; | |||
367 | } | |||
368 | ||||
369 | return TRUE(!(0)); | |||
370 | FAIL: | |||
371 | ||||
372 | return FALSE(0); | |||
373 | } | |||
374 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
375 | ||||
376 | static void | |||
377 | screen_fade_finish (GSFade *fade) | |||
378 | { | |||
379 | struct GSFadeScreenPrivate *screen_priv; | |||
380 | int i; | |||
381 | screen_priv = &fade->priv->screen_priv; | |||
382 | ||||
383 | if (!screen_priv->info) | |||
384 | return; | |||
385 | ||||
386 | for (i = 0; i < screen_priv->num_ramps; i++) | |||
387 | { | |||
388 | if (screen_priv->info[i].r) | |||
389 | g_free (screen_priv->info[i].r); | |||
390 | if (screen_priv->info[i].g) | |||
391 | g_free (screen_priv->info[i].g); | |||
392 | if (screen_priv->info[i].b) | |||
393 | g_free (screen_priv->info[i].b); | |||
394 | } | |||
395 | ||||
396 | g_free (screen_priv->info); | |||
397 | screen_priv->info = NULL((void*)0); | |||
398 | screen_priv->num_ramps = 0; | |||
399 | } | |||
400 | ||||
401 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
402 | static gboolean | |||
403 | gamma_fade_set_alpha_gamma (GSFade *fade, | |||
404 | gdouble alpha) | |||
405 | { | |||
406 | struct GSFadeScreenPrivate *screen_priv; | |||
407 | int screen_idx = CDK_SCREEN_XNUMBER (cdk_screen_get_default ())(cdk_x11_screen_get_screen_number (cdk_screen_get_default ()) ); | |||
408 | ||||
409 | screen_priv = &fade->priv->screen_priv; | |||
410 | xf86_whack_gamma (screen_idx, screen_priv, alpha); | |||
411 | ||||
412 | return TRUE(!(0)); | |||
413 | } | |||
414 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
415 | ||||
416 | static void | |||
417 | check_gamma_extension (GSFade *fade) | |||
418 | { | |||
419 | struct GSFadeScreenPrivate *screen_priv; | |||
420 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
421 | int event; | |||
422 | int error; | |||
423 | int major; | |||
424 | int minor; | |||
425 | gboolean res; | |||
426 | #endif /* HAVE_XF86VMODE_GAMMA */ | |||
427 | ||||
428 | screen_priv = &fade->priv->screen_priv; | |||
429 | ||||
430 | #ifdef HAVE_XF86VMODE_GAMMA1 | |||
431 | res = XF86VidModeQueryExtension (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &event, &error); | |||
432 | if (! res) | |||
433 | goto fade_none; | |||
434 | ||||
435 | res = safe_XF86VidModeQueryVersion (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &major, &minor); | |||
436 | if (! res) | |||
437 | goto fade_none; | |||
438 | ||||
439 | if (major < XF86_VIDMODE_GAMMA_MIN_MAJOR2 || | |||
440 | (major == XF86_VIDMODE_GAMMA_MIN_MAJOR2 && | |||
441 | minor < XF86_VIDMODE_GAMMA_MIN_MINOR0)) | |||
442 | goto fade_none; | |||
443 | ||||
444 | screen_priv->fade_setup = gamma_fade_setup; | |||
445 | screen_priv->fade_finish = screen_fade_finish; | |||
446 | screen_priv->fade_set_alpha_gamma = gamma_fade_set_alpha_gamma; | |||
447 | ||||
448 | if (major < XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR2 || | |||
449 | (major == XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR2 && | |||
450 | minor < XF86_VIDMODE_GAMMA_RAMP_MIN_MINOR1)) | |||
451 | { | |||
452 | screen_priv->fade_type = FADE_TYPE_GAMMA_NUMBER; | |||
453 | return; | |||
454 | } | |||
455 | ||||
456 | /* Copacetic */ | |||
457 | screen_priv->fade_type = FADE_TYPE_GAMMA_RAMP; | |||
458 | return; | |||
459 | fade_none: | |||
460 | #endif | |||
461 | screen_priv->fade_type = FADE_TYPE_NONE; | |||
462 | } | |||
463 | ||||
464 | /* Xrandr support */ | |||
465 | ||||
466 | static gboolean xrandr_fade_setup (GSFade *fade) | |||
467 | { | |||
468 | struct GSFadeScreenPrivate *screen_priv; | |||
469 | CafeRRCrtc *crtc; | |||
470 | CafeRRCrtc **crtcs; | |||
471 | int crtc_count = 0; | |||
472 | struct GSGammaInfo *info; | |||
473 | gboolean res; | |||
474 | ||||
475 | screen_priv = &fade->priv->screen_priv; | |||
476 | ||||
477 | if (screen_priv->info) | |||
| ||||
478 | return TRUE(!(0)); | |||
479 | ||||
480 | /* refresh the screen info */ | |||
481 | cafe_rr_screen_refresh (screen_priv->rrscreen, NULL((void*)0)); | |||
482 | ||||
483 | crtcs = cafe_rr_screen_list_crtcs (screen_priv->rrscreen); | |||
484 | while (*crtcs) | |||
485 | { | |||
486 | crtc_count++; | |||
487 | crtcs++; | |||
488 | }; | |||
489 | ||||
490 | screen_priv->info = g_new0 (struct GSGammaInfo, crtc_count)((struct GSGammaInfo *) g_malloc0_n ((crtc_count), sizeof (struct GSGammaInfo))); | |||
491 | screen_priv->num_ramps = crtc_count; | |||
492 | ||||
493 | crtc_count = 0; | |||
494 | crtcs = cafe_rr_screen_list_crtcs (screen_priv->rrscreen); | |||
495 | while (*crtcs) | |||
496 | { | |||
497 | crtc = *crtcs; | |||
498 | ||||
499 | info = &screen_priv->info[crtc_count]; | |||
500 | ||||
501 | /* if no mode ignore crtc */ | |||
502 | if (!cafe_rr_crtc_get_current_mode (crtc)) | |||
503 | { | |||
504 | info->size = 0; | |||
| ||||
505 | info->r = NULL((void*)0); | |||
506 | info->g = NULL((void*)0); | |||
507 | info->b = NULL((void*)0); | |||
508 | } | |||
509 | else | |||
510 | { | |||
511 | res = cafe_rr_crtc_get_gamma (crtc, &info->size, | |||
512 | &info->r, &info->g, | |||
513 | &info->b); | |||
514 | if (res == FALSE(0)) | |||
515 | goto fail; | |||
516 | } | |||
517 | ||||
518 | crtcs++; | |||
519 | crtc_count++; | |||
520 | } | |||
521 | return TRUE(!(0)); | |||
522 | fail: | |||
523 | return FALSE(0); | |||
524 | } | |||
525 | ||||
526 | static void xrandr_crtc_whack_gamma (CafeRRCrtc *crtc, | |||
527 | struct GSGammaInfo *gamma_info, | |||
528 | float ratio) | |||
529 | { | |||
530 | unsigned short *r, *g, *b; | |||
531 | int i; | |||
532 | ||||
533 | if (gamma_info->size == 0) | |||
534 | return; | |||
535 | ||||
536 | if (ratio < 0) | |||
537 | { | |||
538 | ratio = 0; | |||
539 | } | |||
540 | if (ratio > 1) | |||
541 | { | |||
542 | ratio = 1; | |||
543 | } | |||
544 | ||||
545 | r = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
546 | g = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
547 | b = g_new0 (unsigned short, gamma_info->size)((unsigned short *) g_malloc0_n ((gamma_info->size), sizeof (unsigned short))); | |||
548 | ||||
549 | for (i = 0; i < gamma_info->size; i++) | |||
550 | { | |||
551 | r[i] = gamma_info->r[i] * ratio; | |||
552 | g[i] = gamma_info->g[i] * ratio; | |||
553 | b[i] = gamma_info->b[i] * ratio; | |||
554 | } | |||
555 | ||||
556 | cafe_rr_crtc_set_gamma (crtc, gamma_info->size, | |||
557 | r, g, b); | |||
558 | g_free (r); | |||
559 | g_free (g); | |||
560 | g_free (b); | |||
561 | } | |||
562 | ||||
563 | static gboolean xrandr_fade_set_alpha_gamma (GSFade *fade, | |||
564 | gdouble alpha) | |||
565 | { | |||
566 | struct GSFadeScreenPrivate *screen_priv; | |||
567 | struct GSGammaInfo *info; | |||
568 | CafeRRCrtc **crtcs; | |||
569 | int i; | |||
570 | ||||
571 | screen_priv = &fade->priv->screen_priv; | |||
572 | ||||
573 | if (!screen_priv->info) | |||
574 | return FALSE(0); | |||
575 | ||||
576 | crtcs = cafe_rr_screen_list_crtcs (screen_priv->rrscreen); | |||
577 | i = 0; | |||
578 | ||||
579 | while (*crtcs) | |||
580 | { | |||
581 | info = &screen_priv->info[i]; | |||
582 | xrandr_crtc_whack_gamma (*crtcs, info, alpha); | |||
583 | i++; | |||
584 | crtcs++; | |||
585 | } | |||
586 | return TRUE(!(0)); | |||
587 | } | |||
588 | ||||
589 | static void | |||
590 | check_randr_extension (GSFade *fade) | |||
591 | { | |||
592 | CdkDisplay *display = cdk_display_get_default (); | |||
593 | CdkScreen *screen = cdk_display_get_default_screen (display); | |||
594 | struct GSFadeScreenPrivate *screen_priv; | |||
595 | ||||
596 | screen_priv = &fade->priv->screen_priv; | |||
597 | ||||
598 | screen_priv->rrscreen = cafe_rr_screen_new (screen, | |||
599 | NULL((void*)0)); | |||
600 | if (!screen_priv->rrscreen) | |||
601 | { | |||
602 | screen_priv->fade_type = FADE_TYPE_NONE; | |||
603 | return; | |||
604 | } | |||
605 | ||||
606 | screen_priv->fade_type = FADE_TYPE_XRANDR; | |||
607 | screen_priv->fade_setup = xrandr_fade_setup; | |||
608 | screen_priv->fade_finish = screen_fade_finish; | |||
609 | screen_priv->fade_set_alpha_gamma = xrandr_fade_set_alpha_gamma; | |||
610 | } | |||
611 | ||||
612 | static gboolean | |||
613 | gs_fade_set_alpha (GSFade *fade, | |||
614 | gdouble alpha) | |||
615 | { | |||
616 | gboolean ret = FALSE(0); | |||
617 | ||||
618 | switch (fade->priv->screen_priv.fade_type) | |||
619 | { | |||
620 | case FADE_TYPE_GAMMA_RAMP: | |||
621 | case FADE_TYPE_GAMMA_NUMBER: | |||
622 | case FADE_TYPE_XRANDR: | |||
623 | ret = fade->priv->screen_priv.fade_set_alpha_gamma (fade, alpha); | |||
624 | break; | |||
625 | case FADE_TYPE_NONE: | |||
626 | ret = FALSE(0); | |||
627 | break; | |||
628 | default: | |||
629 | g_warning ("Unknown fade type"); | |||
630 | ret = FALSE(0); | |||
631 | break; | |||
632 | } | |||
633 | ||||
634 | return ret; | |||
635 | } | |||
636 | ||||
637 | static gboolean | |||
638 | gs_fade_out_iter (GSFade *fade) | |||
639 | { | |||
640 | gboolean ret; | |||
641 | ||||
642 | if (fade->priv->current_alpha < 0.01) | |||
643 | { | |||
644 | return FALSE(0); | |||
645 | } | |||
646 | ||||
647 | fade->priv->current_alpha -= fade->priv->alpha_per_iter; | |||
648 | ||||
649 | ret = gs_fade_set_alpha (fade, fade->priv->current_alpha); | |||
650 | ||||
651 | return ret; | |||
652 | } | |||
653 | ||||
654 | static gboolean | |||
655 | gs_fade_stop (GSFade *fade) | |||
656 | { | |||
657 | if (fade->priv->timer_id > 0) | |||
658 | { | |||
659 | g_source_remove (fade->priv->timer_id); | |||
660 | fade->priv->timer_id = 0; | |||
661 | } | |||
662 | ||||
663 | fade->priv->step = 0; | |||
664 | fade->priv->active = FALSE(0); | |||
665 | ||||
666 | return TRUE(!(0)); | |||
667 | } | |||
668 | ||||
669 | void | |||
670 | gs_fade_finish (GSFade *fade) | |||
671 | { | |||
672 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
673 | ||||
674 | if (! fade->priv->active) | |||
675 | { | |||
676 | return; | |||
677 | } | |||
678 | ||||
679 | gs_fade_stop (fade); | |||
680 | ||||
681 | g_signal_emit (fade, signals [FADED], 0); | |||
682 | ||||
683 | fade->priv->active = FALSE(0); | |||
684 | } | |||
685 | ||||
686 | static gboolean | |||
687 | fade_out_timer (GSFade *fade) | |||
688 | { | |||
689 | gboolean res; | |||
690 | ||||
691 | res = gs_fade_out_iter (fade); | |||
692 | ||||
693 | /* if failed then fade is complete */ | |||
694 | if (! res) | |||
695 | { | |||
696 | gs_fade_finish (fade); | |||
697 | return FALSE(0); | |||
698 | } | |||
699 | ||||
700 | return TRUE(!(0)); | |||
701 | } | |||
702 | ||||
703 | gboolean | |||
704 | gs_fade_get_active (GSFade *fade) | |||
705 | { | |||
706 | g_return_val_if_fail (GS_IS_FADE (fade), FALSE)do{ (void)0; }while (0); | |||
707 | ||||
708 | return fade->priv->active; | |||
709 | } | |||
710 | ||||
711 | static void | |||
712 | gs_fade_set_timeout (GSFade *fade, | |||
713 | guint timeout) | |||
714 | { | |||
715 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
716 | ||||
717 | fade->priv->timeout = timeout; | |||
718 | } | |||
719 | ||||
720 | static void | |||
721 | gs_fade_start (GSFade *fade, | |||
722 | guint timeout) | |||
723 | { | |||
724 | guint steps_per_sec = 60; | |||
725 | guint msecs_per_step; | |||
726 | gboolean active_fade, res; | |||
727 | ||||
728 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
729 | ||||
730 | if (fade->priv->screen_priv.fade_type != FADE_TYPE_NONE) | |||
731 | { | |||
732 | res = fade->priv->screen_priv.fade_setup (fade); | |||
733 | if (res == FALSE(0)) | |||
734 | return; | |||
735 | } | |||
736 | ||||
737 | if (fade->priv->timer_id > 0) | |||
738 | { | |||
739 | gs_fade_stop (fade); | |||
740 | } | |||
741 | ||||
742 | fade->priv->active = TRUE(!(0)); | |||
743 | ||||
744 | gs_fade_set_timeout (fade, timeout); | |||
745 | ||||
746 | active_fade = FALSE(0); | |||
747 | if (fade->priv->screen_priv.fade_type != FADE_TYPE_NONE) | |||
748 | active_fade = TRUE(!(0)); | |||
749 | ||||
750 | if (active_fade) | |||
751 | { | |||
752 | guint num_steps; | |||
753 | ||||
754 | num_steps = (fade->priv->timeout / 1000.0) * steps_per_sec; | |||
755 | msecs_per_step = 1000 / steps_per_sec; | |||
756 | fade->priv->alpha_per_iter = 1.0 / (gdouble)num_steps; | |||
757 | ||||
758 | fade->priv->timer_id = g_timeout_add (msecs_per_step, (GSourceFunc)fade_out_timer, fade); | |||
759 | } | |||
760 | else | |||
761 | { | |||
762 | gs_fade_finish (fade); | |||
763 | } | |||
764 | } | |||
765 | ||||
766 | typedef struct | |||
767 | { | |||
768 | GSFadeDoneFunc done_cb; | |||
769 | gpointer data; | |||
770 | } FadedCallbackData; | |||
771 | ||||
772 | static void | |||
773 | gs_fade_async_callback (GSFade *fade, | |||
774 | FadedCallbackData *cdata) | |||
775 | { | |||
776 | g_signal_handlers_disconnect_by_func (fade,g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_async_callback), (cdata)) | |||
777 | gs_fade_async_callback,g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_async_callback), (cdata)) | |||
778 | cdata)g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_async_callback), (cdata)); | |||
779 | ||||
780 | if (cdata->done_cb) | |||
781 | { | |||
782 | cdata->done_cb (fade, cdata->data); | |||
783 | } | |||
784 | ||||
785 | g_free (cdata); | |||
786 | } | |||
787 | ||||
788 | void | |||
789 | gs_fade_async (GSFade *fade, | |||
790 | guint timeout, | |||
791 | GSFadeDoneFunc func, | |||
792 | gpointer data) | |||
793 | { | |||
794 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
795 | ||||
796 | /* if fade is active then pause it */ | |||
797 | if (fade->priv->active) | |||
798 | { | |||
799 | gs_fade_stop (fade); | |||
800 | } | |||
801 | ||||
802 | if (func) | |||
803 | { | |||
804 | FadedCallbackData *cb_data; | |||
805 | ||||
806 | cb_data = g_new0 (FadedCallbackData, 1)((FadedCallbackData *) g_malloc0_n ((1), sizeof (FadedCallbackData ))); | |||
807 | cb_data->done_cb = func; | |||
808 | cb_data->data = data; | |||
809 | ||||
810 | g_signal_connect (fade, "faded",g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_async_callback ))), (cb_data), ((void*)0), (GConnectFlags) 0) | |||
811 | G_CALLBACK (gs_fade_async_callback),g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_async_callback ))), (cb_data), ((void*)0), (GConnectFlags) 0) | |||
812 | cb_data)g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_async_callback ))), (cb_data), ((void*)0), (GConnectFlags) 0); | |||
813 | } | |||
814 | ||||
815 | gs_fade_start (fade, timeout); | |||
816 | } | |||
817 | ||||
818 | static void | |||
819 | gs_fade_sync_callback (GSFade *fade, | |||
820 | int *flag) | |||
821 | { | |||
822 | *flag = TRUE(!(0)); | |||
823 | g_signal_handlers_disconnect_by_func (fade,g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_sync_callback), (flag)) | |||
824 | gs_fade_sync_callback,g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_sync_callback), (flag)) | |||
825 | flag)g_signal_handlers_disconnect_matched ((fade), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (gs_fade_sync_callback), (flag)); | |||
826 | } | |||
827 | ||||
828 | void | |||
829 | gs_fade_sync (GSFade *fade, | |||
830 | guint timeout) | |||
831 | { | |||
832 | int flag = FALSE(0); | |||
833 | ||||
834 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
835 | ||||
836 | /* if fade is active then pause it */ | |||
837 | if (fade->priv->active) | |||
838 | { | |||
839 | gs_fade_stop (fade); | |||
840 | } | |||
841 | ||||
842 | g_signal_connect (fade, "faded",g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_sync_callback ))), (&flag), ((void*)0), (GConnectFlags) 0) | |||
843 | G_CALLBACK (gs_fade_sync_callback),g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_sync_callback ))), (&flag), ((void*)0), (GConnectFlags) 0) | |||
844 | &flag)g_signal_connect_data ((fade), ("faded"), (((GCallback) (gs_fade_sync_callback ))), (&flag), ((void*)0), (GConnectFlags) 0); | |||
845 | ||||
846 | gs_fade_start (fade, timeout); | |||
847 | ||||
848 | while (! flag) | |||
849 | { | |||
850 | ctk_main_iteration (); | |||
851 | } | |||
852 | } | |||
853 | ||||
854 | void | |||
855 | gs_fade_reset (GSFade *fade) | |||
856 | { | |||
857 | g_return_if_fail (GS_IS_FADE (fade))do{ (void)0; }while (0); | |||
858 | ||||
859 | gs_debug ("Resetting fade")gs_debug_real (__func__, "gs-fade.c", 859, "Resetting fade"); | |||
860 | ||||
861 | if (fade->priv->active) | |||
862 | { | |||
863 | gs_fade_stop (fade); | |||
864 | } | |||
865 | ||||
866 | fade->priv->current_alpha = 1.0; | |||
867 | ||||
868 | gs_fade_set_alpha (fade, fade->priv->current_alpha); | |||
869 | ||||
870 | if (fade->priv->screen_priv.fade_type != FADE_TYPE_NONE) | |||
871 | fade->priv->screen_priv.fade_finish (fade); | |||
872 | } | |||
873 | ||||
874 | static void | |||
875 | gs_fade_class_init (GSFadeClass *klass) | |||
876 | { | |||
877 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); | |||
878 | ||||
879 | object_class->finalize = gs_fade_finalize; | |||
880 | ||||
881 | signals [FADED] = | |||
882 | g_signal_new ("faded", | |||
883 | G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type), | |||
884 | G_SIGNAL_RUN_LAST, | |||
885 | G_STRUCT_OFFSET (GSFadeClass, faded)((glong) __builtin_offsetof(GSFadeClass, faded)), | |||
886 | NULL((void*)0), | |||
887 | NULL((void*)0), | |||
888 | g_cclosure_marshal_VOID__VOID, | |||
889 | G_TYPE_NONE((GType) ((1) << (2))), | |||
890 | 0, G_TYPE_NONE((GType) ((1) << (2)))); | |||
891 | } | |||
892 | ||||
893 | static void | |||
894 | gs_fade_init (GSFade *fade) | |||
895 | { | |||
896 | fade->priv = gs_fade_get_instance_private (fade); | |||
897 | ||||
898 | fade->priv->timeout = 1000; | |||
899 | fade->priv->current_alpha = 1.0; | |||
900 | ||||
901 | check_randr_extension (fade); | |||
902 | if (!fade->priv->screen_priv.fade_type) | |||
903 | check_gamma_extension (fade); | |||
904 | gs_debug ("Fade type: %d", fade->priv->screen_priv.fade_type)gs_debug_real (__func__, "gs-fade.c", 904, "Fade type: %d", fade ->priv->screen_priv.fade_type); | |||
905 | } | |||
906 | ||||
907 | static void | |||
908 | gs_fade_finalize (GObject *object) | |||
909 | { | |||
910 | GSFade *fade; | |||
911 | ||||
912 | g_return_if_fail (object != NULL)do{ (void)0; }while (0); | |||
913 | g_return_if_fail (GS_IS_FADE (object))do{ (void)0; }while (0); | |||
914 | ||||
915 | fade = GS_FADE (object)((((GSFade*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((gs_fade_get_type ())))))); | |||
916 | ||||
917 | g_return_if_fail (fade->priv != NULL)do{ (void)0; }while (0); | |||
918 | ||||
919 | fade->priv->screen_priv.fade_finish(fade); | |||
920 | ||||
921 | if (fade->priv->screen_priv.rrscreen) | |||
922 | g_object_unref (fade->priv->screen_priv.rrscreen); | |||
923 | fade->priv->screen_priv.rrscreen = NULL((void*)0); | |||
924 | ||||
925 | G_OBJECT_CLASS (gs_fade_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((gs_fade_parent_class)), (((GType) ((20) << (2))))) )))->finalize (object); | |||
926 | } | |||
927 | ||||
928 | GSFade * | |||
929 | gs_fade_new (void) | |||
930 | { | |||
931 | if (fade_object) | |||
932 | { | |||
933 | g_object_ref (fade_object)((__typeof__ (fade_object)) (g_object_ref) (fade_object)); | |||
934 | } | |||
935 | else | |||
936 | { | |||
937 | fade_object = g_object_new (GS_TYPE_FADE(gs_fade_get_type ()), NULL((void*)0)); | |||
938 | g_object_add_weak_pointer (fade_object, | |||
939 | (gpointer *) &fade_object); | |||
940 | } | |||
941 | ||||
942 | return GS_FADE (fade_object)((((GSFade*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((fade_object)), ((gs_fade_get_type ())))))); | |||
943 | } |