Tizen 2.1 base
[platform/core/uifw/libslp-utilx.git] / x11.c
1 /*
2  * libslp-utilx
3  *
4    Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <sys/shm.h>
25 #include <unistd.h>
26
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include <X11/extensions/Xrandr.h>
31
32 #include "utilX.h"
33 #include "util_x11.h"
34
35 #include <fcntl.h>
36 #include <X11/extensions/Xvlib.h>
37 #include <X11/extensions/Xvproto.h>
38 #include <X11/extensions/Xdamage.h>
39 #include <X11/extensions/XShm.h>
40 #include <dri2.h>
41 #include <drm_slp_bufmgr.h>
42
43
44 #define UTILX_DEBUG 0
45 #if UTILX_DEBUG
46 #define UTILX_TRACE  printf
47 #else
48 #define UTILX_TRACE(...)
49 #endif
50
51 static Atom _atom_grab_key = None;
52 static Atom _atom_grab_excl_win = None;
53 static Atom _atom_grab_or_excl_win = None;
54
55 static Atom _atom_notification_level = None;
56 static Atom _atom_indicator_visible_state = None;
57 static Atom _atom_indicator_visible_state_on = None;
58 static Atom _atom_indicator_visible_state_off = None;
59
60 static Atom _atom_comp_effect_state = None;
61 static Atom _atom_comp_fake_launch = None;
62 static Atom _atom_comp_fake_launch_image = None;
63
64 static Atom _atom_comp_window_effect_type = None;
65 static Atom _atom_comp_effect_default = None;
66 static Atom _atom_comp_effect_none = None;
67 static Atom _atom_comp_effect_custom0 = None;
68 static Atom _atom_comp_effect_custom1 = None;
69 static Atom _atom_comp_effect_custom2 = None;
70 static Atom _atom_comp_effect_custom3 = None;
71 static Atom _atom_comp_effect_custom4 = None;
72 static Atom _atom_comp_effect_custom5 = None;
73 static Atom _atom_comp_effect_custom6 = None;
74 static Atom _atom_comp_effect_custom7 = None;
75 static Atom _atom_comp_effect_custom8 = None;
76 static Atom _atom_comp_effect_custom9 = None;
77
78 static Atom _atom_window_opaque = None;
79
80 static Atom _atom_screen_capture_disable = None;
81
82 static Atom _atom_comp_capture_effect = None;
83
84 const unsigned long maxlen = 1024l;
85
86 static void _utilx_set_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int num);
87 static int _utilx_get_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int len);
88
89 static void _utilx_effect_atom_check( Display* dpy );
90 static Atom _utilx_convert_style_to_atom( Display* dpy, Utilx_Effect_Style style );
91 static Utilx_Effect_Style _utilx_convert_atom_to_style( Display* dpy, Atom style );
92
93 static int _utilx_get_indicator_atoms(Display *dpy);
94
95 API void utilx_set_system_notification_level (Display* dpy, Window win, Utilx_Notification_Level level)
96 {
97         UTILX_TRACE ("[UTILX] utilx_set_system_notification_level... win = %x, level = %d\n", win, level);
98
99         int noti_level;
100
101         if (dpy == NULL)
102         {
103                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
104                 return;
105         }
106
107         switch (level)
108         {
109                 case UTILX_NOTIFICATION_LEVEL_LOW:
110                         noti_level = 50;
111                         break;
112
113                 case UTILX_NOTIFICATION_LEVEL_NORMAL:
114                         noti_level = 100;
115                         break;
116
117                 case UTILX_NOTIFICATION_LEVEL_HIGH:
118                         noti_level = 150;
119                         break;
120
121                 default:
122                         noti_level = 50;
123                         break;
124         }
125
126         if (!_atom_notification_level)
127         {
128                 _atom_notification_level = XInternAtom (dpy, "_E_ILLUME_NOTIFICATION_LEVEL", False);
129                 if (!_atom_notification_level)
130                 {
131                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_NOTIFICATION_LEVEL atom.. %s (%d)\n", __func__, __LINE__);
132                         return;
133                 }
134         }
135
136         _utilx_set_window_property (dpy, win, _atom_notification_level, XA_CARDINAL,
137                         (unsigned int *)&noti_level, 1);
138 }
139
140
141 API Utilx_Notification_Level utilx_get_system_notification_level (Display* dpy, Window win)
142 {
143         UTILX_TRACE ("[UTILX] utilx_get_system_notification_level... win = %x\n", win);
144
145         Utilx_Notification_Level noti_level;
146         unsigned int level;
147         int ret;
148
149         noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
150
151         if (dpy == NULL)
152         {
153                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
154                 goto error;
155         }
156
157         if (!_atom_notification_level)
158         {
159                 _atom_notification_level = XInternAtom (dpy, "_E_ILLUME_NOTIFICATION_LEVEL", False);
160                 if (!_atom_notification_level)
161                 {
162                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_NOTIFICATION_LEVEL atom.. %s (%d)\n", __func__, __LINE__);
163                         goto error;
164                 }
165         }
166
167         ret = _utilx_get_window_property (dpy, win, _atom_notification_level, XA_CARDINAL,
168                         (unsigned int *)&level, 1);
169
170         if (ret > 0)
171         {
172                 switch (level)
173                 {
174                         case 50:
175                                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
176                                 break;
177
178                         case 100:
179                                 noti_level = UTILX_NOTIFICATION_LEVEL_NORMAL;
180                                 break;
181
182                         case 150:
183                                 noti_level = UTILX_NOTIFICATION_LEVEL_HIGH;
184                                 break;
185
186                         default:
187                                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
188                                 break;
189                 }
190         }
191         else
192         {
193                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
194         }
195
196 error:
197         return noti_level;
198 }
199
200 static int _utilx_get_indicator_atoms(Display *dpy)
201 {
202         if (!_atom_indicator_visible_state)
203         {
204                 _atom_indicator_visible_state = XInternAtom (dpy, "_E_ILLUME_INDICATOR_STATE", False);
205                 if (!_atom_indicator_visible_state)
206                 {
207                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_STATE atom.. %s (%d)\n", __func__, __LINE__);
208                         return 0;
209                 }
210         }
211
212         if (!_atom_indicator_visible_state_on)
213         {
214                 _atom_indicator_visible_state_on = XInternAtom (dpy, "_E_ILLUME_INDICATOR_ON", False);
215                 if (!_atom_indicator_visible_state_on)
216                 {
217                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_ON atom.. %s (%d)\n", __func__, __LINE__);
218                         return 0;
219                 }
220         }
221
222         if (!_atom_indicator_visible_state_off)
223         {
224                 _atom_indicator_visible_state_off = XInternAtom (dpy, "_E_ILLUME_INDICATOR_OFF", False);
225                 if (!_atom_indicator_visible_state_off)
226                 {
227                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_OFF atom.. %s (%d)\n", __func__, __LINE__);
228                         return 0;
229                 }
230         }
231
232         return 1;
233 }
234
235 API void utilx_enable_indicator (Display* dpy, Window win, int enable)
236 {
237         UTILX_TRACE ("[UTILX] utilx_indicator_set_visible_state... win = %x, show_state = %d\n", win, enable);
238
239         if (dpy == NULL)
240         {
241                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
242                 return;
243         }
244
245         if (!_utilx_get_indicator_atoms(dpy))
246         {
247                 fprintf (stderr, "[UTILX] Error.. Cannot create atoms.. %s (%d)\n", __func__, __LINE__);
248                 return;
249         }
250
251         if (enable == 1)
252         {
253                 _utilx_set_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
254                         (unsigned int *)&_atom_indicator_visible_state_on, 1);
255         }
256         else
257         {
258                 _utilx_set_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
259                         (unsigned int *)&_atom_indicator_visible_state_off, 1);
260         }
261 }
262
263
264 API int utilx_get_indicator_state (Display* dpy, Window win)
265 {
266         UTILX_TRACE ("[UTILX] utilx_indicator_set_visible_state... win = %x, show_state = %d\n", win, enable);
267
268         int ret;
269         Atom state;
270
271         if (dpy == NULL)
272         {
273                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
274                 return -1;
275         }
276
277         if (!_utilx_get_indicator_atoms(dpy))
278         {
279                 fprintf (stderr, "[UTILX] Error.. Cannot create atoms.. %s (%d)\n", __func__, __LINE__);
280                 return -1;
281         }
282
283         ret = _utilx_get_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
284                         (unsigned int *)&state, 1);
285
286         if (ret > 0)
287         {
288                 if (state == _atom_indicator_visible_state_on)
289                         return 1;
290                 else if (state == _atom_indicator_visible_state_off)
291                         return 0;
292                 else
293                         return -1;
294         }
295         else
296                 return -1;
297 }
298
299 static void
300 _utilx_set_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int num)
301 {
302         XChangeProperty (dpy, win, atom, type, 32, PropModeReplace, (unsigned char *)val, num);
303         XSync(dpy, 0 );
304 }
305
306
307 static int
308 _utilx_get_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int len)
309 {
310         unsigned char* prop_ret;
311         Atom type_ret;
312         unsigned long bytes_after, num_ret;
313         int format_ret;
314         unsigned int i;
315         int num;
316
317         prop_ret = NULL;
318         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
319                                 type, &type_ret, &format_ret, &num_ret,
320                                 &bytes_after, &prop_ret) != Success)
321         {
322                 return -1;
323         }
324
325         if (type_ret != type || format_ret != 32)
326         {
327                 num = -1;
328         }
329         else if (num_ret == 0 || !prop_ret)
330         {
331                 num = 0;
332         }
333         else
334         {
335                 if (num_ret < len)
336                 len = num_ret;
337                 for (i = 0; i < len; i++)
338                 {
339                         val[i] = ((unsigned long *)prop_ret)[i];
340                 }
341                 num = len;
342         }
343
344         if (prop_ret)
345                 XFree(prop_ret);
346
347         return num;
348
349 }
350
351
352 static unsigned long _get_list_of_grabbed_key (Display *disp, Window win, int **key_list)
353 {
354         Atom ret_type;
355         int ret_format;
356         unsigned long nr_item;
357         unsigned long sz_remains_data;
358
359         if (XGetWindowProperty(disp, win,
360                 _atom_grab_key, 0, 0x7fffffff, False, XA_CARDINAL,
361                 &ret_type, &ret_format, &nr_item,
362                 &sz_remains_data, (unsigned char**)key_list) != Success)
363         {
364                 nr_item = 0;
365         }
366
367 //      fprintf(stderr, "\e[31m%d - %lu\e[0m\n", ret_format, nr_item);
368
369         return nr_item;
370 }
371
372
373 static void _free_list_of_grabbed_key (int *key_list)
374 {
375         if (key_list) {
376                 XFree(key_list);
377         }
378 }
379
380
381 static void _free_new_list_of_grabbed_key (int *new_key_list)
382 {
383         if (new_key_list) {
384                 free(new_key_list);
385         }
386 }
387
388
389 static int _search_grabbed_key (int *key_list, int key, unsigned long cnt)
390 {
391         register int i;
392
393         for (i = cnt - 1; i >= 0; i --) {
394                 if (key_list[i] == key) break;
395         }
396
397         return i;
398 }
399
400
401 static int *_del_grabbed_key (int *key_list, int i, unsigned long *cnt)
402 {
403         int *new_key_list = NULL;
404
405         // Only one element is exists in the list of grabbed key
406         (*cnt) --;
407
408         if (*cnt == 0) return NULL;
409
410         // Shrink the buffer
411         new_key_list = malloc((*cnt) * sizeof(int));
412         if (new_key_list == NULL) {
413                 perror(__func__);
414                 return NULL;
415         }
416
417         // copy head
418         if (i > 0) {
419                 memcpy(new_key_list, key_list, sizeof(int) * i);
420         }
421
422         // copy tail
423         if ((*cnt) - i > 0) {
424                 memcpy(new_key_list + i,
425                         key_list + i + 1,
426                         sizeof(int) * ((*cnt) - i)
427                 );
428         }
429         return new_key_list;
430 }
431
432
433 static void _set_exclusive_grab_info_to_root (Display *disp, int keycode, Window win, int grab_mode)
434 {
435         int i;
436         int *key_list = NULL;
437
438         Atom ret_type;
439         int ret_format;
440         unsigned long nr_item;
441         unsigned long sz_remains_data;
442         Window ex_grabwin;
443
444         if( grab_mode == EXCLUSIVE_GRAB )
445         {
446                 if( _atom_grab_excl_win == None )
447                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
448                 ex_grabwin = _atom_grab_excl_win;
449         }
450         else if( grab_mode == OR_EXCLUSIVE_GRAB )
451         {
452                 if( _atom_grab_or_excl_win == None )
453                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
454                 ex_grabwin = _atom_grab_or_excl_win;
455         }
456         else
457                 return;
458
459         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
460                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
461                 &ret_type, &ret_format, &nr_item,
462                 &sz_remains_data, (unsigned char**)&key_list) != Success)
463         {
464                 fprintf(stderr, "[utilX][%s] Fail to get root window property !\n", __FUNCTION__);
465                 goto out;
466         }
467
468 #ifdef __DEBUG__
469         printf("[%s] keycode = %d\n", __FUNCTION__, keycode);
470 #endif
471
472         for( i=0 ; i < nr_item ; i++ )
473         {
474                 if( key_list && (key_list[i] == keycode) )
475                         return;
476         }
477
478         XChangeProperty(disp, DefaultRootWindow(disp), ex_grabwin, XA_CARDINAL, 32,
479         nr_item ? PropModeAppend : PropModeReplace, (unsigned char *)&keycode, 1);
480         XSync(disp, False);
481
482 out:
483         return;
484 }
485
486
487 static void _unset_exclusive_grab_info_to_root (Display *disp, int keycode, int grab_mode)
488 {
489         int i;
490         unsigned long cnt = 0;
491         int *key_list = NULL;
492         int *new_key_list = NULL;
493
494         Atom ret_type;
495         int ret_format;
496         unsigned long nr_item;
497         unsigned long sz_remains_data;
498         Window ex_grabwin;
499
500         if( grab_mode == EXCLUSIVE_GRAB )
501         {
502                 if( _atom_grab_excl_win == None )
503                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
504                 ex_grabwin = _atom_grab_excl_win;
505         }
506         else if( grab_mode == OR_EXCLUSIVE_GRAB )
507         {
508                 if( _atom_grab_or_excl_win == None )
509                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
510                 ex_grabwin = _atom_grab_or_excl_win;
511         }
512         else
513                 return;
514
515         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
516                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
517                 &ret_type, &ret_format, &nr_item,
518                 &sz_remains_data, (unsigned char**)&key_list) != Success)
519         {
520                 nr_item = 0;
521         }
522
523         if (nr_item == 0)
524         {
525                 fprintf(stderr, "\e[32m[utilX][%s] keycode = %d\e[0m\n", __FUNCTION__, keycode);
526                 goto out;
527         }
528
529         for( i=0 ; i < nr_item ; i++ )
530         {
531                 if( key_list[i] == keycode )//&& grab_mode == EXCLUSIVE_GRAB )
532                 {
533                         continue;
534                 }
535                 cnt++;
536         }
537
538 #ifdef __DEBUG__
539         fprintf(stderr, "[utilX][%s] cnt = %d, nr_item = %d\n", __FUNCTION__, cnt, nr_item);
540 #endif
541
542         if( 0 < cnt )
543         {
544                 new_key_list = malloc(sizeof(int)*cnt);
545                 cnt = 0;
546         }
547         else
548                 new_key_list = NULL;
549
550         if( !new_key_list )
551         {
552                 //fprintf(stderr, "\e[32m[utilX][%s] Fail to allocation memory for new_key_list ! \e[0m\n", __FUNCTION__);
553                 XDeleteProperty(disp, DefaultRootWindow(disp), ex_grabwin);
554                 XSync(disp, False);
555                 goto out;
556         }
557
558         for( i=0 ; i < nr_item ; i++ )
559         {
560                 if( key_list[i] == keycode )//&& grab_mode == EXCLUSIVE_GRAB )
561                 {
562                         continue;
563                 }
564                 else
565                         new_key_list[cnt++] = key_list[i];
566         }
567
568         if (new_key_list) {
569                 XChangeProperty(disp, DefaultRootWindow(disp), ex_grabwin, XA_CARDINAL, 32,
570                         PropModeReplace, (unsigned char *)new_key_list, cnt);
571         }
572         else {
573                 XDeleteProperty(disp, DefaultRootWindow(disp), ex_grabwin);
574         }
575         XSync(disp, False);
576
577         if(new_key_list)
578                 free(new_key_list);
579
580 out:
581         return;
582 }
583
584
585 static int _is_grabbed_key_exclusively (Display* disp, int keycode, int grab_mode)
586 {
587         int i, result = 0;
588         int *key_list = NULL;
589
590         Atom ret_type;
591         int ret_format;
592         unsigned long nr_item;
593         unsigned long sz_remains_data;
594         Window ex_grabwin;
595
596         if( grab_mode == EXCLUSIVE_GRAB )
597         {
598                 if( _atom_grab_excl_win == None )
599                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
600                 ex_grabwin = _atom_grab_excl_win;
601         }
602         else if( grab_mode == OR_EXCLUSIVE_GRAB )
603         {
604                 if( _atom_grab_or_excl_win == None )
605                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
606                 ex_grabwin = _atom_grab_or_excl_win;
607         }
608         else
609                 return result;
610
611         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
612                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
613                 &ret_type, &ret_format, &nr_item,
614                 &sz_remains_data, (unsigned char**)&key_list) != Success)
615         {
616                 fprintf(stderr, "[%s] Fail to get root window property !\n", __FUNCTION__);
617                 goto out;
618         }
619
620         for( i=0 ; i < nr_item ; i++ )
621         {
622                 if( key_list[i] == keycode )
623                         return EXCLUSIVE_GRABBED_ALREADY;
624         }
625
626 out:
627         return result;
628 }
629
630 API int utilx_grab_key (Display* disp, Window win, const char* key, int grab_mode)
631 {
632         unsigned long cnt;
633         int *key_list = NULL;
634         int i, result = 0;
635         int keycode = 0;
636         KeySym keysym;
637         errno = EINVAL;
638
639         if( NULL == disp )
640         {
641                 fprintf(stderr, "[%s] Display is NULL\n", __FUNCTION__);
642                 return -1;
643         }
644
645         if (_atom_grab_key == None) {
646                 _atom_grab_key = XInternAtom(disp, STR_ATOM_GRAB_KEY, False);
647         }
648
649         if (!strncmp(key, "Keycode-", 8)) {
650                 keycode = atoi(key + 8);
651         } else {
652                 keysym = XStringToKeysym(key);
653                 if (keysym == NoSymbol) goto out;
654                 keycode = XKeysymToKeycode(disp, XStringToKeysym(key));
655         }
656         if (keycode == 0) goto out;
657
658         if( grab_mode == EXCLUSIVE_GRAB )
659         {
660                 //Window grabWin;
661                 result = _is_grabbed_key_exclusively(disp, keycode, grab_mode);
662
663 #ifdef __DEBUG__
664                 printf("[%s] _is_grabbed_key_exclusively returns result = %d\n", __FUNCTION__, result);
665 #endif
666
667                 if( result )
668                 {
669                         fprintf(stderr, "[%s] keycode(%d) was already grabbed exclusively (grab_mode=0x%X) !\n", __FUNCTION__, keycode, grab_mode);
670                         goto out;
671                 }
672         }
673         else if( grab_mode == OR_EXCLUSIVE_GRAB )
674         {
675                 result = _is_grabbed_key_exclusively(disp, keycode, grab_mode);
676
677                 if( result )
678                 {
679                         fprintf(stderr, "[%s] Keycode(%d) was already grabbed with overridable exclusive mode (grab_mode=0x%x)\n", __FUNCTION__, keycode, grab_mode);
680                         fprintf(stderr, "[%s] Now it will be overridden by a new window(0x%x) !\n", __FUNCTION__, win);
681                         utilx_ungrab_key(disp, win, key);
682                 }
683         }
684
685         keycode |= grab_mode;
686
687         cnt = _get_list_of_grabbed_key(disp, win, &key_list);
688         if (cnt > 0) {
689                 i = _search_grabbed_key(key_list, keycode, cnt);
690                 _free_list_of_grabbed_key(key_list);
691                 if ( i != -1 ) {
692                         if( grab_mode == OR_EXCLUSIVE_GRAB )
693                         {
694                                 utilx_ungrab_key(disp, win, key);
695                         }
696                         else
697                         {
698                         fprintf(stderr, "Key is already grabbed\n");
699                         goto out;
700                         }
701                 }
702         }
703
704         XChangeProperty(disp, win, _atom_grab_key, XA_CARDINAL, 32,
705                         cnt ? PropModeAppend : PropModeReplace, (unsigned char *)&keycode, 1);
706         XSync(disp, False);
707         keycode = keycode & (~GRAB_MODE_MASK);
708 #ifdef __DEBUG__
709         printf("[%s] keycode = %d\n", __FUNCTION__, keycode);
710 #endif
711
712         if( EXCLUSIVE_GRAB == grab_mode || OR_EXCLUSIVE_GRAB == grab_mode )
713                 _set_exclusive_grab_info_to_root(disp, keycode, win, grab_mode);
714
715         errno = 0;
716
717 out:
718
719         return result;
720 }
721
722
723 API int utilx_ungrab_key (Display* disp, Window win, const char* key)
724 {
725         int i;
726         unsigned long cnt;
727         int *key_list = NULL;
728         int *new_key_list = NULL;
729         long keycode = 0;
730         KeySym keysym;
731         int ret = -1;
732         errno = EINVAL;
733
734         if( NULL == disp )
735         {
736                 fprintf(stderr, "[%s] Display is NULL\n", __FUNCTION__);
737                 return -1;
738         }
739
740         if (_atom_grab_key == None) {
741                 _atom_grab_key = XInternAtom(disp, STR_ATOM_GRAB_KEY, False);
742         }
743
744         if (!strncmp(key, "Keycode-", 8)) {
745                 keycode = atoi(key + 8);
746         } else {
747                 keysym = XStringToKeysym(key);
748                 if (keysym == NoSymbol) goto out;
749                 keycode = XKeysymToKeycode(disp, XStringToKeysym(key));
750         }
751         if (keycode == 0) goto out;
752
753         cnt = _get_list_of_grabbed_key(disp, win, &key_list);
754         if (cnt == 0) goto out;
755
756         //EXCLUSIVE mode
757         i = _search_grabbed_key(key_list, keycode | EXCLUSIVE_GRAB, cnt);
758
759         if ( i == -1)
760         {
761                 //OR_EXCLUSIVE mode
762                 i = _search_grabbed_key(key_list, keycode | OR_EXCLUSIVE_GRAB, cnt);
763
764                 if ( i == -1)
765                 {
766                         //TOP_POSITION mode
767                         i = _search_grabbed_key(key_list, keycode | TOP_POSITION_GRAB, cnt);
768
769                         if (i == -1)
770                         {
771                                 //SHARED mode
772                                 i = _search_grabbed_key(key_list, keycode | SHARED_GRAB, cnt);
773
774                                 if (i == -1)
775                                 {
776                                         _free_list_of_grabbed_key(key_list);
777                                         goto out;
778                                 }
779                         }
780                 }
781                 else
782                 {
783                         _unset_exclusive_grab_info_to_root(disp, keycode, OR_EXCLUSIVE_GRAB);
784                 }
785         }
786         else
787         {
788                 _unset_exclusive_grab_info_to_root(disp, keycode, EXCLUSIVE_GRAB);
789         }
790
791         new_key_list = _del_grabbed_key(key_list, i, &cnt);
792         _free_list_of_grabbed_key(key_list);
793
794         if (new_key_list) {
795                 XChangeProperty(disp, win, _atom_grab_key, XA_CARDINAL, 32,
796                         PropModeReplace, (unsigned char *)new_key_list, cnt);
797         }
798         else {
799                 XDeleteProperty(disp, win, _atom_grab_key);
800         }
801         XSync(disp, False);
802
803         _free_new_list_of_grabbed_key(new_key_list);
804         ret = 0;
805         errno = 0;
806
807 out:
808
809         return ret;
810 }
811
812 API Utilx_Key_Status utilx_get_key_status(Display* dpy, char *key_name)
813 {
814         unsigned char keymap[32];
815         static unsigned int masktable[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
816         Utilx_Key_Status status = UTILX_KEY_STATUS_UNKNOWN;
817
818         if( !strncmp(key_name, KEY_VOLUMEDOWN, LEN_KEY_VOLUMEDOWN) ||
819                 !strncmp(key_name, KEY_VOLUMEUP, LEN_KEY_VOLUMEUP) ||
820                 !strncmp(key_name, KEY_PAUSE, LEN_KEY_PAUSE) ||
821                 !strncmp(key_name, KEY_SEND, LEN_KEY_SEND) ||
822                 !strncmp(key_name, KEY_SELECT, LEN_KEY_VOLUMEDOWN) ||
823                 !strncmp(key_name, KEY_END, LEN_KEY_END) ||
824                 !strncmp(key_name, KEY_POWER, LEN_KEY_POWER) ||
825                 !strncmp(key_name, KEY_CAMERA, LEN_KEY_CAMERA) ||
826                 !strncmp(key_name, KEY_CONFIG, LEN_KEY_CONFIG) ||
827                 !strncmp(key_name, KEY_PLAYCD, LEN_KEY_PLAYCD) ||
828                 !strncmp(key_name, KEY_STOPCD, LEN_KEY_STOPCD) ||
829                 !strncmp(key_name, KEY_PAUSECD, LEN_KEY_PAUSECD) ||
830                 !strncmp(key_name, KEY_NEXTSONG, LEN_KEY_NEXTSONG) ||
831                 !strncmp(key_name, KEY_PREVIOUSSONG, LEN_KEY_PREVIOUSSONG) ||
832                 !strncmp(key_name, KEY_REWIND, LEN_KEY_REWIND) ||
833                 !strncmp(key_name, KEY_FASTFORWARD, LEN_KEY_FASTFORWARD) ||
834                 !strncmp(key_name, KEY_MEDIA, LEN_KEY_MEDIA) )
835         {
836                 KeySym ks = XStringToKeysym(key_name);
837                 KeyCode kc = XKeysymToKeycode(dpy, ks);
838
839                 if( kc )
840                 {
841                         XQueryKeymap(dpy, (char *)keymap);
842                         if( keymap[kc >> 3] & masktable[kc & 7] )
843                                 status = UTILX_KEY_STATUS_PRESSED;
844                         else
845                                 status = UTILX_KEY_STATUS_RELEASED;
846                 }
847         }
848
849         return status;
850 }
851
852 API void utilx_set_window_effect_state(Display* dpy, Window win, int state)
853 {
854         if ( dpy == NULL )
855         {
856                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
857                 return;
858         }
859         if( !_atom_comp_effect_state)
860                 _atom_comp_effect_state = XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_ENABLE",False);
861
862         _utilx_set_window_property(dpy, win, _atom_comp_effect_state, XA_CARDINAL, (unsigned int *)&state, 1);
863
864         XSync(dpy, 0 );
865 }
866
867 API int utilx_get_window_effect_state(Display* dpy, Window win)
868 {
869         int state = 0;
870         if( !_atom_comp_effect_state)
871                 _atom_comp_effect_state = XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_ENABLE",False);
872         _utilx_get_window_property(dpy, win, _atom_comp_effect_state, XA_CARDINAL, (unsigned int *)&state, 1);
873         return state;
874 }
875
876 static void
877 _utilx_string_set_window_property( Display *dpy, Window win, Atom atom, char *val, unsigned int num)
878 {
879         XChangeProperty( dpy, win, atom, XA_STRING, 8, PropModeReplace, (unsigned char*)val, val ? strlen(val):0 );
880 }
881
882 API void utilx_set_fake_launch_img(Display* dpy, Window win, char *file_name)
883 {
884         //UTILX_TRACE ("[UTILX] utilx_set_effect_state... win = %x, show_state = %d\n", win, enable);
885
886         if ( dpy == NULL )
887         {
888                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
889                 return;
890         }
891         if( !_atom_comp_fake_launch_image)
892                 _atom_comp_fake_launch_image = XInternAtom(dpy, "_E_COMP_FAKE_LAUNCH_IMAGE",False);
893
894         _utilx_string_set_window_property(dpy, win, _atom_comp_fake_launch_image, file_name, 1);
895 }
896
897 API void utilx_show_fake_effect( Display *dpy, Window win, char *fake_image_file )
898 {
899         XEvent xev;
900
901         _atom_comp_fake_launch = XInternAtom( dpy, "_E_COMP_FAKE_LAUNCH", False );
902
903         if(  !_atom_comp_fake_launch )
904         {
905                 fprintf( stderr, "XInternAtom(_E_COMP_FAKE_LAUNCH) failed.\n" );
906                 return;
907         }
908
909         utilx_set_fake_launch_img(dpy, win, fake_image_file);
910
911         XSync(dpy, 0 );
912
913         // send fake client message
914         xev.xclient.type = ClientMessage;
915         xev.xclient.display = dpy;
916         xev.xclient.window = win;
917         xev.xclient.message_type =  _atom_comp_fake_launch;
918         xev.xclient.format = 32;
919         xev.xclient.data.l[0] = 1;  // 1 : start effect , 0 : end effect
920         xev.xclient.data.l[1] = 0;
921         xev.xclient.data.l[2] = 0;
922         xev.xclient.data.l[3] = 0;
923         xev.xclient.data.l[4] = 0;
924
925         XSendEvent( dpy, win, False,
926                                 SubstructureRedirectMask | SubstructureNotifyMask,
927                                 &xev );
928         XSync(dpy, 0 );
929
930 }
931
932
933 API void utilx_hide_fake_effect( Display *dpy, Window win)
934 {
935         XEvent xev;
936
937         _atom_comp_fake_launch = XInternAtom( dpy, "_E_COMP_FAKE_LAUNCH", False );
938         if(  !_atom_comp_fake_launch )
939         {
940                 fprintf( stderr, "XInternAtom(_E_COMP_FAKE_LAUNCH) failed.\n" );
941                 return;
942         }
943
944         // send fake client message
945         xev.xclient.type = ClientMessage;
946         xev.xclient.display = dpy;
947         xev.xclient.window = win;
948         xev.xclient.message_type =  _atom_comp_fake_launch;
949         xev.xclient.format = 32;
950         xev.xclient.data.l[0] = 0;  // 1 : start effect , 0 : end effect
951         xev.xclient.data.l[1] = 0;
952         xev.xclient.data.l[2] = 0;
953         xev.xclient.data.l[3] = 0;
954         xev.xclient.data.l[4] = 0;
955
956         XSendEvent( dpy, win, False,
957                                 SubstructureRedirectMask | SubstructureNotifyMask,
958                                 &xev );
959         XSync(dpy, 0 );
960 }
961
962 static void _utilx_effect_atom_check( Display* dpy )
963 {
964         if ( dpy == NULL )
965         {
966                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
967                 return;
968         }
969
970         if( !_atom_comp_window_effect_type)
971                 _atom_comp_window_effect_type =  XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_TYPE",False);
972         if( !_atom_comp_effect_default )
973                 _atom_comp_effect_default = XInternAtom(dpy, "_NET_CM_EFFECT_DEFAULT",False);
974         if( !_atom_comp_effect_none )
975                 _atom_comp_effect_none = XInternAtom(dpy, "_NET_CM_EFFECT_NONE",False);
976         if( !_atom_comp_effect_custom0 )
977                 _atom_comp_effect_custom0 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM0",False);
978         if( !_atom_comp_effect_custom1 )
979                 _atom_comp_effect_custom1 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM1",False);
980         if( !_atom_comp_effect_custom2 )
981                 _atom_comp_effect_custom2 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM2",False);
982         if( !_atom_comp_effect_custom3 )
983                 _atom_comp_effect_custom3 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM3",False);
984         if( !_atom_comp_effect_custom4 )
985                 _atom_comp_effect_custom4 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM4",False);
986         if( !_atom_comp_effect_custom5 )
987                 _atom_comp_effect_custom5 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM5",False);
988         if( !_atom_comp_effect_custom6 )
989                 _atom_comp_effect_custom6 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM6",False);
990         if( !_atom_comp_effect_custom7 )
991                 _atom_comp_effect_custom7 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM7",False);
992         if( !_atom_comp_effect_custom8 )
993                 _atom_comp_effect_custom8 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM8",False);
994         if( !_atom_comp_effect_custom9 )
995                 _atom_comp_effect_custom9 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM9",False);
996 }
997
998 static Atom _utilx_convert_style_to_atom( Display* dpy, Utilx_Effect_Style style )
999 {
1000         if ( dpy == NULL )
1001         {
1002                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1003                 return _atom_comp_effect_none;
1004         }
1005         _utilx_effect_atom_check(dpy);
1006
1007         if ( style == UTILX_EFFECT_STYLE_DEFAULT )       return _atom_comp_effect_default;
1008         else if ( style == UTILX_EFFECT_STYLE_NONE )     return _atom_comp_effect_none;
1009         else if ( style == UTILX_EFFECT_STYLE_CUSTOM0 )  return _atom_comp_effect_custom0;
1010         else if ( style == UTILX_EFFECT_STYLE_CUSTOM1 )  return _atom_comp_effect_custom1;
1011         else if ( style == UTILX_EFFECT_STYLE_CUSTOM2 )  return _atom_comp_effect_custom2;
1012         else if ( style == UTILX_EFFECT_STYLE_CUSTOM3 )  return _atom_comp_effect_custom3;
1013         else if ( style == UTILX_EFFECT_STYLE_CUSTOM4 )  return _atom_comp_effect_custom4;
1014         else if ( style == UTILX_EFFECT_STYLE_CUSTOM5 )  return _atom_comp_effect_custom5;
1015         else if ( style == UTILX_EFFECT_STYLE_CUSTOM6 )  return _atom_comp_effect_custom6;
1016         else if ( style == UTILX_EFFECT_STYLE_CUSTOM7 )  return _atom_comp_effect_custom7;
1017         else if ( style == UTILX_EFFECT_STYLE_CUSTOM8 )  return _atom_comp_effect_custom8;
1018         else if ( style == UTILX_EFFECT_STYLE_CUSTOM9 )  return _atom_comp_effect_custom9;
1019         else                                             return _atom_comp_effect_none;
1020
1021 }
1022
1023 static Utilx_Effect_Style _utilx_convert_atom_to_style( Display* dpy, Atom style )
1024 {
1025         if ( dpy == NULL )
1026         {
1027                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1028                 return UTILX_EFFECT_STYLE_NONE;
1029         }
1030         _utilx_effect_atom_check(dpy);
1031
1032         if ( style == _atom_comp_effect_default )       return UTILX_EFFECT_STYLE_DEFAULT;
1033         else if ( style == _atom_comp_effect_none )     return UTILX_EFFECT_STYLE_NONE;
1034         else if ( style == _atom_comp_effect_custom0 )  return UTILX_EFFECT_STYLE_CUSTOM0;
1035         else if ( style == _atom_comp_effect_custom1 )  return UTILX_EFFECT_STYLE_CUSTOM1;
1036         else if ( style == _atom_comp_effect_custom2 )  return UTILX_EFFECT_STYLE_CUSTOM2;
1037         else if ( style == _atom_comp_effect_custom3 )  return UTILX_EFFECT_STYLE_CUSTOM3;
1038         else if ( style == _atom_comp_effect_custom4 )  return UTILX_EFFECT_STYLE_CUSTOM4;
1039         else if ( style == _atom_comp_effect_custom5 )  return UTILX_EFFECT_STYLE_CUSTOM5;
1040         else if ( style == _atom_comp_effect_custom6 )  return UTILX_EFFECT_STYLE_CUSTOM6;
1041         else if ( style == _atom_comp_effect_custom7 )  return UTILX_EFFECT_STYLE_CUSTOM7;
1042         else if ( style == _atom_comp_effect_custom8 )  return UTILX_EFFECT_STYLE_CUSTOM8;
1043         else if ( style == _atom_comp_effect_custom9 )  return UTILX_EFFECT_STYLE_CUSTOM9;
1044         else                                            return UTILX_EFFECT_STYLE_DEFAULT;
1045 }
1046
1047 API void utilx_set_window_effect_style(Display* dpy, Window win, Utilx_Effect_Type type, Utilx_Effect_Style style)
1048 {
1049         Atom *window_effect_type_list = NULL;
1050         if ( dpy == NULL )
1051         {
1052                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1053                 return;
1054         }
1055         _utilx_effect_atom_check(dpy);
1056
1057         window_effect_type_list = (Atom *)malloc(sizeof(Atom) * 6);
1058
1059         if ( !window_effect_type_list )
1060         {
1061                 fprintf (stderr, "[UTILX] Error.. malloc().. %s (%d)\n", __func__, __LINE__);
1062                 return;
1063         }
1064
1065         window_effect_type_list[0] = _atom_comp_effect_default;
1066         window_effect_type_list[1] = _atom_comp_effect_default;
1067         window_effect_type_list[2] = _atom_comp_effect_default;
1068         window_effect_type_list[3] = _atom_comp_effect_default;
1069         window_effect_type_list[4] = _atom_comp_effect_default;
1070         window_effect_type_list[5] = _atom_comp_effect_default;
1071
1072         _utilx_get_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6);
1073
1074         if ( type == UTILX_EFFECT_TYPE_MAP )             window_effect_type_list[0] = _utilx_convert_style_to_atom(dpy, style);
1075         else if ( type == UTILX_EFFECT_TYPE_UNMAP )      window_effect_type_list[1] = _utilx_convert_style_to_atom(dpy, style);
1076         else if ( type == UTILX_EFFECT_TYPE_RAISEABOVE ) window_effect_type_list[2] = _utilx_convert_style_to_atom(dpy, style);
1077         else if ( type == UTILX_EFFECT_TYPE_ROTATION )   window_effect_type_list[3] = _utilx_convert_style_to_atom(dpy, style);
1078         else if ( type == UTILX_EFFECT_TYPE_FOCUSIN )    window_effect_type_list[4] = _utilx_convert_style_to_atom(dpy, style);
1079         else if ( type == UTILX_EFFECT_TYPE_FOCUSOUT )   window_effect_type_list[5] = _utilx_convert_style_to_atom(dpy, style);
1080
1081         _utilx_set_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6);
1082
1083         XSync(dpy, 0 );
1084         free(window_effect_type_list);
1085 }
1086
1087 API Utilx_Effect_Style utilx_get_window_effect_style(Display* dpy, Window win, Utilx_Effect_Type type)
1088 {
1089         Atom *window_effect_type_list = NULL;
1090         Utilx_Effect_Style style = UTILX_EFFECT_STYLE_DEFAULT;
1091
1092         if ( dpy == NULL )
1093         {
1094                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1095                 return UTILX_EFFECT_STYLE_NONE;
1096         }
1097         _utilx_effect_atom_check(dpy);
1098
1099         window_effect_type_list = (Atom *)malloc(sizeof(Atom) * 6);
1100
1101         if ( !window_effect_type_list )
1102         {
1103                 fprintf (stderr, "[UTILX] Error.. malloc().. %s (%d)\n", __func__, __LINE__);
1104                 return UTILX_EFFECT_STYLE_NONE;
1105         }
1106
1107         if ( _utilx_get_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6) != 6 )
1108         {
1109                 fprintf (stderr, "[UTILX] Error.. get property failed!.. %s (%d)\n", __func__, __LINE__);
1110                 free(window_effect_type_list);
1111                 return UTILX_EFFECT_STYLE_NONE;
1112         }
1113
1114         if ( type == UTILX_EFFECT_TYPE_MAP )             style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[0]);
1115         else if ( type == UTILX_EFFECT_TYPE_UNMAP )      style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[1]);
1116         else if ( type == UTILX_EFFECT_TYPE_RAISEABOVE ) style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[2]);
1117         else if ( type == UTILX_EFFECT_TYPE_ROTATION )   style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[3]);
1118         else if ( type == UTILX_EFFECT_TYPE_FOCUSIN )    style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[4]);
1119         else if ( type == UTILX_EFFECT_TYPE_FOCUSOUT )   style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[5]);
1120
1121         XSync(dpy, 0 );
1122         free(window_effect_type_list);
1123         return style;
1124 }
1125
1126 API int utilx_set_window_opaque_state (Display* dpy, Window win, Utilx_Opaque_State state)
1127 {
1128         UTILX_TRACE ("[UTILX] utilx_set_window_opaque_state... win = %x, show_state = %d\n", win, state);
1129
1130         unsigned int is_opaque;
1131
1132         if (dpy == NULL)
1133         {
1134                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1135                 return 0;
1136         }
1137
1138         switch (state)
1139         {
1140                 case UTILX_OPAQUE_STATE_OFF:
1141                         is_opaque = 0;
1142                         break;
1143
1144                 case UTILX_OPAQUE_STATE_ON:
1145                         is_opaque = 1;
1146                         break;
1147
1148                 default:
1149                         fprintf (stderr, "[UTILX] Error.. Invald State.. %s (%d)\n", __func__, __LINE__);
1150                         return 0;
1151         }
1152
1153         if (!_atom_window_opaque)
1154         {
1155                 _atom_window_opaque = XInternAtom (dpy, "_E_ILLUME_WINDOW_REGION_OPAQUE", False);
1156                 if (!_atom_window_opaque)
1157                 {
1158                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_WINDOW_REGION_OPAQUE atom.. %s (%d)\n", __func__, __LINE__);
1159                         return 0;
1160                 }
1161         }
1162
1163         _utilx_set_window_property (dpy, win, _atom_window_opaque, XA_CARDINAL,
1164                         (unsigned int *)&is_opaque, 1);
1165
1166         return 1;
1167 }
1168
1169 static void
1170 _utilx_screen_capture_atom_ensure (Display* dpy)
1171 {
1172         if (_atom_screen_capture_disable)
1173                 return;
1174
1175         _atom_screen_capture_disable = XInternAtom (dpy, "_CB_SCREEN_CAPTURE_DISABLE", False);
1176         if (_atom_screen_capture_disable)
1177                 return;
1178
1179         fprintf (stderr, "[UTILX] Error.. Cannot create _CB_SCREEN_CAPTURE_DISABLE atom.. %s (%d)\n", __func__, __LINE__);
1180 }
1181
1182 API int
1183 utilx_set_screen_capture(Display* dpy, int enable)
1184 {
1185         Window root;
1186         int disable;
1187
1188         if (!dpy)
1189         {
1190                 fprintf (stderr, "[UTILX] Error.. dpy is NULL %s (%d)\n", __func__, __LINE__);
1191                 return 0;
1192         }
1193
1194         root = RootWindow (dpy, DefaultScreen(dpy));
1195         disable = (enable) ? 0 : 1;
1196
1197         _utilx_screen_capture_atom_ensure (dpy);
1198
1199         _utilx_set_window_property (dpy, root, _atom_screen_capture_disable, XA_CARDINAL, (unsigned int *)&disable, 1);
1200
1201         return 1;
1202 }
1203
1204 API int
1205 utilx_get_screen_capture(Display* dpy)
1206 {
1207         Window root;
1208         int disable = 0;
1209
1210         if (!dpy)
1211         {
1212                 fprintf (stderr, "[UTILX] Error.. dpy is NULL %s (%d)\n", __func__, __LINE__);
1213                 return 0;
1214         }
1215
1216         root = RootWindow (dpy, DefaultScreen(dpy));
1217
1218         _utilx_screen_capture_atom_ensure (dpy);
1219
1220         _utilx_get_window_property(dpy, root, _atom_screen_capture_disable, XA_CARDINAL,
1221                                     (unsigned int *)&disable, 1);
1222
1223         return (disable) ? 0 : 1;
1224 }
1225
1226 API void utilx_set_window_cardinal_property(Display* dpy, Window win, Atom atom, unsigned int *value)
1227 {
1228         _utilx_set_window_property(dpy, win, atom, XA_CARDINAL, value, 1);
1229 }
1230
1231 API int utilx_get_window_cardinal_property (Display* dpy, Window win, Atom atom, unsigned int *value)
1232 {
1233         return _utilx_get_window_property(dpy, win, atom, XA_CARDINAL, value, 1);
1234 }
1235
1236 API void utilx_show_capture_effect( Display *dpy, Window win)
1237 {
1238     XEvent xev;
1239
1240     _atom_comp_capture_effect = XInternAtom( dpy, "_E_COMP_CAPTURE_EFFECT", False );
1241     if(  !_atom_comp_capture_effect )
1242     {
1243         fprintf( stderr, "XInternAtom(_E_COMP_CAPTURE_EFFECT) failed.\n" );
1244         return;
1245     }
1246
1247     // send capture effect client message
1248     xev.xclient.type = ClientMessage;
1249     xev.xclient.display = dpy;
1250     xev.xclient.window = win;
1251     xev.xclient.message_type =  _atom_comp_capture_effect;
1252     xev.xclient.format = 32;
1253     xev.xclient.data.l[0] = 0;
1254     xev.xclient.data.l[1] = 0;
1255     xev.xclient.data.l[2] = 0;
1256     xev.xclient.data.l[3] = 0;
1257     xev.xclient.data.l[4] = 0;
1258
1259     XSendEvent( dpy, win, False,
1260                 SubstructureRedirectMask | SubstructureNotifyMask,
1261                 &xev );
1262     XSync(dpy, 0 );
1263 }
1264
1265 API UtilxScrnConf *utilx_scrnconf_allocate (void)
1266 {
1267     UtilxScrnConf *scrnconf = calloc (1, sizeof(UtilxScrnConf));
1268     if (!scrnconf)
1269     {
1270         fprintf (stderr, "fail to allocate UtilxScrnConf\n");
1271         return NULL;
1272     }
1273
1274     return scrnconf;
1275 }
1276
1277 API void utilx_scrnconf_free (UtilxScrnConf *scrnconf)
1278 {
1279     if (!scrnconf)
1280         return;
1281
1282     if (scrnconf->str_output)
1283         free (scrnconf->str_output);
1284
1285     if (scrnconf->str_resolution)
1286         free (scrnconf->str_resolution);
1287
1288     free(scrnconf);
1289     scrnconf = NULL;
1290 }
1291
1292 API int utilx_scrnconf_get_info (Display *dpy, UtilxScrnConf *scrnconf)
1293 {
1294     Window win = DefaultRootWindow(dpy);
1295         Atom scrnconf_atom = None;
1296     XTextProperty xtp;
1297     char *str = NULL;
1298     char *ptr = NULL;
1299     int items;
1300     char **list = NULL;
1301     int i = 0;
1302     int s;
1303
1304     scrnconf_atom = XInternAtom (dpy, "_SCRNCONF_INFO", False);
1305
1306     /* get property */
1307     if (XGetTextProperty (dpy, win, &xtp, scrnconf_atom))
1308     {
1309         s = XmbTextPropertyToTextList (dpy, &xtp, &list, &items);
1310         if ((s == XLocaleNotSupported) ||
1311             (s == XNoMemory) || (s == XConverterNotFound))
1312           str = strdup((char *)xtp.value);
1313         else if ((s >= Success) && (items > 0))
1314           str = strdup(list[0]);
1315
1316         if (list)
1317             XFreeStringList (list);
1318
1319         XFree(xtp.value);
1320     }
1321
1322     ptr = strtok (str, ",");
1323     while (ptr != NULL)
1324     {
1325         if (i == 0)
1326         {
1327             scrnconf->str_output = calloc (1, strlen(ptr));
1328             if (!scrnconf->str_output)
1329                 goto fail;
1330
1331             strcpy (scrnconf->str_output, ptr);
1332         }
1333         else if (i == 1)
1334         {
1335             if (!strcmp(ptr, "CONNECT"))
1336                 scrnconf->status = UTILX_SCRNCONF_STATUS_CONNECT;
1337             else if (!strcmp(ptr, "ACTIVE"))
1338                 scrnconf->status = UTILX_SCRNCONF_STATUS_ACTIVE;
1339             else
1340                 scrnconf->status = UTILX_SCRNCONF_STATUS_NULL;
1341         }
1342         else if (i == 2)
1343         {
1344             scrnconf->str_resolution = calloc (1, strlen(ptr));
1345             if (!scrnconf->str_resolution)
1346                 goto fail;
1347
1348             strcpy (scrnconf->str_resolution, ptr);
1349         }
1350         else if (i == 3)
1351         {
1352             if (!strcmp(ptr, "CLONE"))
1353                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_CLONE;
1354             else if (!strcmp(ptr, "EXTENDED"))
1355                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_EXTENDED;
1356             else
1357                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_NULL;
1358         }
1359         else
1360            break;
1361
1362         ptr = strtok (NULL, ",");
1363         i++;
1364     }
1365
1366     free (str);
1367
1368     return 1;
1369 fail:
1370     if (str)
1371         free (str);
1372
1373     return 0;
1374 }
1375
1376 API int utilx_scrnconf_set_dispmode (Display *dpy, Utilx_Scrnconf_Dispmode dispmode)
1377 {
1378     Window win = DefaultRootWindow(dpy);
1379         XEvent xev;
1380         Atom scrnconf_atom = None;
1381     UtilxScrnConf *scrnconf = NULL;
1382
1383     scrnconf = utilx_scrnconf_allocate ();
1384     if (!scrnconf)
1385         return 0;
1386
1387     if (!utilx_scrnconf_get_info (dpy, scrnconf))
1388     {
1389         utilx_scrnconf_free (scrnconf);
1390         return 0;
1391     }
1392
1393     if (scrnconf->status  == UTILX_SCRNCONF_STATUS_NULL)
1394     {
1395         fprintf (stderr, "[utilx_scrnconf]: the status of screen configuration is null\n");
1396         utilx_scrnconf_free (scrnconf);
1397         return 0;
1398     }
1399
1400     if (scrnconf->dispmode == dispmode)
1401     {
1402         fprintf (stderr, "[utilx_scrnconf]: dispmode (%d) already set\n", dispmode);
1403         utilx_scrnconf_free (scrnconf);
1404         return 1;
1405     }
1406
1407     utilx_scrnconf_free (scrnconf);
1408
1409     scrnconf_atom = XInternAtom (dpy, "_SCRNCONF_DISPMODE_SET", False);
1410
1411         xev.xclient.window = win;
1412         xev.xclient.type = ClientMessage;
1413         xev.xclient.message_type = scrnconf_atom;
1414         xev.xclient.format = 32;
1415         xev.xclient.data.s[0] = dispmode;
1416
1417         XSendEvent(dpy, win, False, StructureNotifyMask, &xev);
1418         XSync(dpy, False);
1419
1420     return 1;
1421 }
1422
1423 typedef struct _ShotInfo
1424 {
1425     Display *dpy;
1426
1427     /* GetStill */
1428     int      port;
1429     unsigned int width;
1430     unsigned int height;
1431     Pixmap   pixmap;
1432     GC       gc;
1433
1434     /* Damage */
1435     Damage   damage;
1436     int      damage_base;
1437
1438     /* Dri2 */
1439     int      drm_fd;
1440     drm_slp_bufmgr bufmgr;
1441     void    *virtual;
1442     DRI2Buffer* dri2_buffers;
1443     drm_slp_bo bo;
1444
1445     /* XShm */
1446     Bool       enable_xshm;
1447     XImage    *image;
1448     XShmSegmentInfo shminfo;
1449 } ShotInfo;
1450
1451 #define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
1452
1453 #define FOURCC_RGB32    FOURCC('R','G','B','4')
1454
1455     /* x error handling */
1456 static Bool x_error_caught;
1457
1458 static ShotInfo *shot_info;
1459
1460 static int
1461 _get_port (Display *dpy, unsigned int id)
1462 {
1463     unsigned int ver, rev, req_base, evt_base, err_base;
1464     unsigned int adaptors;
1465     XvAdaptorInfo *ai = NULL;
1466     XvImageFormatValues *fo = NULL;
1467     int formats;
1468     int i, j, p;
1469
1470     if (XvQueryExtension (dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
1471     {
1472         fprintf (stderr, "[UTILX] no XV extension. \n");
1473         return -1;
1474     }
1475
1476     if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &adaptors, &ai) != Success)
1477     {
1478         fprintf (stderr, "[UTILX] fail : query adaptors. \n");
1479         return -1;
1480     }
1481
1482     if (!ai)
1483     {
1484         fprintf (stderr, "[UTILX] fail : get adaptor info. \n");
1485         return -1;
1486     }
1487
1488     for (i = 0; i < adaptors; i++)
1489     {
1490         int support_format = False;
1491
1492         if (!(ai[i].type & XvStillMask))
1493             continue;
1494
1495         p = ai[i].base_id;
1496
1497         fo = XvListImageFormats (dpy, p, &formats);
1498         for (j = 0; j < formats; j++)
1499             if (fo[j].id == (int)id)
1500                 support_format = True;
1501
1502         if (fo)
1503             XFree (fo);
1504
1505         if (!support_format)
1506             continue;
1507
1508         if (XvGrabPort (dpy, p, 0) == Success)
1509         {
1510             XvFreeAdaptorInfo (ai);
1511             return p;
1512         }
1513
1514         fprintf (stderr, "[UTILX] fail : grab port. \n");
1515     }
1516
1517     XvFreeAdaptorInfo (ai);
1518
1519     return -1;
1520 }
1521
1522 static void
1523 _deinit_screen_shot (ShotInfo *info)
1524 {
1525     static Atom atom_stream_off = None;
1526
1527     if (!info)
1528         return;
1529
1530     if (atom_stream_off == None)
1531         atom_stream_off = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);
1532
1533     XvSetPortAttribute (info->dpy, info->port, atom_stream_off, 1);
1534
1535     if (info->image)
1536         XDestroyImage (info->image);
1537     if (info->shminfo.shmid != -1)
1538     {
1539         XShmDetach (info->dpy, &info->shminfo);
1540         shmdt (info->shminfo.shmaddr);
1541         shmctl (info->shminfo.shmid, IPC_RMID, 0);
1542     }
1543
1544     if (info->bo)
1545         drm_slp_bo_unref(info->bo);
1546     if (info->dri2_buffers)
1547         free(info->dri2_buffers);
1548     if (info->bufmgr)
1549         drm_slp_bufmgr_destroy (info->bufmgr);
1550     if (info->drm_fd >= 0)
1551         close (info->drm_fd);
1552
1553     if (info->damage)
1554         XDamageDestroy (info->dpy, info->damage);
1555
1556     if (info->gc)
1557         XFreeGC (info->dpy, info->gc);
1558     if (info->pixmap > 0)
1559         XFreePixmap (info->dpy, info->pixmap);
1560     if (info->port > 0)
1561         XvUngrabPort (info->dpy, info->port, 0);
1562
1563     free (info);
1564     shot_info = NULL;
1565 }
1566
1567 static int
1568 _screen_shot_x_error_handle (Display *dpy, XErrorEvent *ev)
1569 {
1570     char error_msg[1024];
1571
1572     if (!shot_info || (dpy != shot_info->dpy))
1573         return 0;
1574
1575     XGetErrorText (dpy, ev->error_code, error_msg, 1024);
1576     fprintf (stderr, "[UTILX] get XError: %s\n", error_msg);
1577
1578     x_error_caught = True;
1579
1580     return 0;
1581 }
1582
1583 static Bool
1584 _init_screen_shot_damage (ShotInfo *info)
1585 {
1586     int damage_err_base = 0;
1587
1588     if (!XDamageQueryExtension(info->dpy, &info->damage_base, &damage_err_base))
1589     {
1590         fprintf (stderr, "[UTILX] no X Damage extension. \n");
1591         return False;
1592     }
1593
1594     info->damage = XDamageCreate (info->dpy, info->pixmap, XDamageReportNonEmpty);
1595     if (info->damage <= 0)
1596     {
1597         fprintf (stderr, "[UTILX] fail : create damage \n");
1598         return False;
1599     }
1600
1601     return True;
1602 }
1603
1604 static Bool
1605 _init_screen_shot_dri2 (ShotInfo *info)
1606 {
1607     int screen;
1608     int dri2_base = 0;
1609     int dri2_err_base = 0;
1610     int dri2Major, dri2Minor;
1611     char *driverName = NULL, *deviceName = NULL;
1612     unsigned int attachments[1];
1613     int dri2_count, dri2_out_count;
1614     int dri2_width, dri2_height, dri2_stride;
1615     drm_magic_t magic;
1616
1617     screen = DefaultScreen(info->dpy);
1618     if (!DRI2QueryExtension (info->dpy, &dri2_base, &dri2_err_base))
1619     {
1620         fprintf (stderr, "[UTILX] no DRI2 extension. !!\n");
1621         goto fail_init_dri2;
1622     }
1623
1624     if (!DRI2QueryVersion (info->dpy, &dri2Major, &dri2Minor))
1625     {
1626         fprintf (stderr, "[UTILX] fail : DRI2QueryVersion !!\n");
1627         goto fail_init_dri2;
1628     }
1629
1630     if (!DRI2Connect (info->dpy, RootWindow(info->dpy, screen), &driverName, &deviceName))
1631     {
1632         fprintf (stderr, "[UTILX] fail : DRI2Connect !!\n");
1633         goto fail_init_dri2;
1634     }
1635
1636     /* drm_fd */
1637     info->drm_fd = open (deviceName, O_RDWR);
1638     if (info->drm_fd < 0)
1639     {
1640         fprintf (stderr, "[UTILX] fail : open drm device (%s)\n", deviceName);
1641         goto fail_init_dri2;
1642     }
1643
1644     /* get the drm magic */
1645     drmGetMagic(info->drm_fd, &magic);
1646     if (!DRI2Authenticate(info->dpy, RootWindow(info->dpy, screen), magic))
1647     {
1648         fprintf (stderr, "[UTILX] fail : DRI2Authenticate (%d)\n", magic);
1649         goto fail_init_dri2;
1650     }
1651
1652     /* bufmgr */
1653     info->bufmgr = drm_slp_bufmgr_init (info->drm_fd, NULL);
1654     if (!info->bufmgr)
1655     {
1656         fprintf (stderr, "[UTILX] fail : init buffer manager \n");
1657         goto fail_init_dri2;
1658     }
1659
1660     DRI2CreateDrawable (info->dpy, info->pixmap);
1661
1662     attachments[0] = DRI2BufferFrontLeft;
1663     dri2_count = 1;
1664     info->dri2_buffers = DRI2GetBuffers (info->dpy, info->pixmap, &dri2_width, &dri2_height,
1665                                          attachments, dri2_count, &dri2_out_count);
1666
1667     if (!info->dri2_buffers)
1668     {
1669         fprintf (stderr, "[UTILX] fail : get buffers\n");
1670         goto fail_init_dri2;
1671     }
1672
1673     if (!info->dri2_buffers[0].name)
1674     {
1675         fprintf (stderr, "[UTILX] fail : a handle of the dri2 buffer is null \n ");
1676         goto fail_init_dri2;
1677     }
1678
1679     info->bo = drm_slp_bo_import (info->bufmgr, info->dri2_buffers[0].name);
1680     if (!info->bo)
1681     {
1682         fprintf (stderr, "[UTILX] fail : import bo (key:%d)\n", info->dri2_buffers[0].name);
1683         goto fail_init_dri2;
1684     }
1685
1686     dri2_stride = info->dri2_buffers[0].pitch;
1687
1688     /* virtual */
1689     info->virtual = (void*)drm_slp_bo_get_handle (info->bo, DRM_SLP_DEVICE_CPU);
1690     if (!info->virtual)
1691     {
1692         fprintf (stderr, "[UTILX] fail : map \n");
1693         goto fail_init_dri2;
1694     }
1695
1696     info->enable_xshm = False;
1697
1698     return True;
1699
1700 fail_init_dri2:
1701
1702     if (info->bo)
1703         drm_slp_bo_unref(info->bo);
1704     if (info->dri2_buffers)
1705         free(info->dri2_buffers);
1706     if (info->bufmgr)
1707         drm_slp_bufmgr_destroy (info->bufmgr);
1708     if (info->drm_fd >= 0)
1709         close (info->drm_fd);
1710
1711     return False;
1712 }
1713
1714 static Bool
1715 _init_screen_shot_shm (ShotInfo *info)
1716 {
1717     if (!XShmQueryExtension (info->dpy))
1718     {
1719         fprintf (stderr, "[UTILX] no XShm extension. !!\n");
1720         return False;
1721     }
1722
1723     info->image = XShmCreateImage (info->dpy,
1724                                    DefaultVisual (info->dpy, DefaultScreen (info->dpy)),
1725                                    DefaultDepth (info->dpy, DefaultScreen (info->dpy)),
1726                                    ZPixmap,
1727                                    NULL,
1728                                    &info->shminfo,
1729                                    info->width,
1730                                    info->height);
1731     if (!info->image)
1732     {
1733         fprintf (stderr, "[UTILX] fail : XShmCreateImage \n");
1734         return False;
1735     }
1736
1737     info->shminfo.shmid = shmget (IPC_PRIVATE, info->image->bytes_per_line * info->height, IPC_CREAT | 0777);
1738     if (info->shminfo.shmid == -1)
1739     {
1740         XDestroyImage (info->image);
1741         fprintf (stderr, "[UTILX] fail : shmget\n");
1742         return False;
1743     }
1744
1745     info->shminfo.shmaddr = shmat (info->shminfo.shmid, 0, 0);
1746     if (info->shminfo.shmaddr == (void *) -1)
1747     {
1748         XDestroyImage (info->image);
1749         shmctl (info->shminfo.shmid, IPC_RMID, 0);
1750         info->shminfo.shmid = -1;
1751         fprintf (stderr, "[UTILX] fail : shmat\n");
1752         return False;
1753     }
1754
1755     info->shminfo.readOnly = False;
1756
1757     if (!XShmAttach (info->dpy, &info->shminfo))
1758     {
1759         XDestroyImage (info->image);
1760         shmdt (info->shminfo.shmaddr);
1761         shmctl (info->shminfo.shmid, IPC_RMID, 0);
1762         info->shminfo.shmid = -1;
1763         fprintf (stderr, "[UTILX] fail : XShmAttach\n");
1764         return False;
1765     }
1766
1767     info->image->data = info->shminfo.shmaddr;
1768     info->virtual = info->shminfo.shmaddr;
1769
1770     info->enable_xshm = True;
1771
1772     return True;
1773 }
1774
1775 static ShotInfo*
1776 _init_screen_shot (Display* dpy, unsigned int width, unsigned int height)
1777 {
1778     ShotInfo *info = NULL;
1779     static Atom atom_capture = None;
1780
1781     if (shot_info)
1782     {
1783         if (shot_info->width == width && shot_info->height == height)
1784             return shot_info;
1785
1786         _deinit_screen_shot (shot_info);
1787     }
1788
1789     info = calloc (1, sizeof (ShotInfo));
1790     if (!info)
1791         goto fail_init;
1792
1793     shot_info = info;
1794
1795     /* dpy */
1796     info->dpy = dpy;
1797     info->shminfo.shmid = -1;
1798     info->shminfo.shmaddr = (void*)-1;
1799     info->drm_fd = -1;
1800
1801     /* port */
1802     info->port = _get_port (info->dpy, FOURCC_RGB32);
1803     if (info->port <= 0)
1804         goto fail_init;
1805
1806     /* width, height */
1807     if (atom_capture == None)
1808         atom_capture = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1809
1810     XvSetPortAttribute (info->dpy, info->port, atom_capture, 1);
1811     XvQueryBestSize (info->dpy, info->port, 0, 0, 0, width, height, &width, &height);
1812     if (width <= 0 || height <= 0)
1813         goto fail_init;
1814     info->width = width;
1815     info->height = height;
1816
1817     /* pixmap */
1818     info->pixmap = XCreatePixmap (info->dpy,
1819                                   DefaultRootWindow (info->dpy),
1820                                   width, height,
1821                                   DefaultDepth (info->dpy, DefaultScreen (info->dpy)));
1822     if (info->pixmap <= 0)
1823     {
1824         fprintf (stderr, "[UTILX] fail : create pixmap. \n");
1825         goto fail_init;
1826     }
1827
1828     /* gc */
1829     info->gc = XCreateGC (info->dpy, info->pixmap, 0, 0);
1830     if (info->gc <= 0)
1831     {
1832         fprintf (stderr, "[UTILX] fail : create gc. \n");
1833         goto fail_init;
1834     }
1835
1836     XSetForeground (info->dpy, info->gc, 0xFF000000);
1837     XFillRectangle (info->dpy, info->pixmap, info->gc, 0, 0, width, height);
1838
1839     if (!_init_screen_shot_damage (info))
1840         goto fail_init;
1841
1842     if (!_init_screen_shot_dri2 (info))
1843     {
1844         if (!_init_screen_shot_shm (info))
1845             goto fail_init;
1846         else
1847             fprintf (stderr, "[UTILX] XShm success. !!\n");
1848     }
1849
1850     if (!info->virtual)
1851     {
1852         fprintf (stderr, "[UTILX] fail : get virtual \n");
1853         goto fail_init;
1854     }
1855
1856     XFlush (info->dpy);
1857
1858     return info;
1859
1860 fail_init:
1861     _deinit_screen_shot (info);
1862     return NULL;
1863 }
1864
1865 API void*
1866 utilx_create_screen_shot (Display* dpy, int width, int height)
1867 {
1868     ShotInfo *info;
1869     XEvent ev;
1870     XErrorHandler old_handler = NULL;
1871
1872     if (dpy <= 0)
1873     {
1874         fprintf (stderr, "[UTILX] invalid display(%p) \n", dpy);
1875         return NULL;
1876     }
1877
1878     if (width <= 0 || height <= 0)
1879     {
1880         fprintf (stderr, "[UTILX] invalid size(%dx%d) \n", width, height);
1881         return NULL;
1882     }
1883
1884     XSync (dpy, 0);
1885
1886     x_error_caught = False;
1887     old_handler = XSetErrorHandler (_screen_shot_x_error_handle);
1888
1889     info = _init_screen_shot (dpy, width, height);
1890
1891     if (!info)
1892     {
1893         fprintf (stderr, "[UTILX] fail : initialize screenshot. \n");
1894         return NULL;
1895     }
1896
1897     XvGetStill (info->dpy, info->port, info->pixmap, info->gc,
1898                 0, 0, info->width, info->height,
1899                 0, 0, info->width, info->height);
1900
1901     XSync (dpy, 0);
1902
1903     if (x_error_caught)
1904     {
1905         x_error_caught = False;
1906         XSetErrorHandler (old_handler);
1907         fprintf (stderr, "[UTILX] fail : GetStill. \n");
1908         return NULL;
1909     }
1910
1911     x_error_caught = False;
1912     XSetErrorHandler (old_handler);
1913
1914     XNextEvent (info->dpy, &ev); /* wating for x event */
1915
1916     if (ev.type == (info->damage_base + XDamageNotify))
1917     {
1918         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1919         if (damage_ev->drawable == info->pixmap)
1920         {
1921             if (info->enable_xshm)
1922                 XShmGetImage (info->dpy, info->pixmap, info->image, 0, 0, AllPlanes);
1923
1924             XDamageSubtract (info->dpy, info->damage, None, None );
1925             return info->virtual;
1926         }
1927
1928         XDamageSubtract (info->dpy, info->damage, None, None );
1929     }
1930
1931     utilx_release_screen_shot ();
1932
1933     return NULL;
1934 }
1935
1936 API void
1937 utilx_release_screen_shot (void)
1938 {
1939     _deinit_screen_shot (shot_info);
1940 }
1941
1942 #define XRR_PROPERTY_FB_VISIBLE     "XRR_PROPERTY_FB_VISIBLE"
1943 #define XRR_PROPERTY_VIDEO_OFFSET   "XRR_PROPERTY_VIDEO_OFFSET"
1944
1945 static Bool
1946 _utilx_xrr_set_property (Display* dpy, Atom atom, unsigned char *buf, int buf_len, unsigned char **get)
1947 {
1948     Window root = None;
1949     XRRScreenResources *res = NULL;
1950     RROutput rr_output = None;
1951     int i;
1952
1953     root = XRootWindow (dpy, 0);
1954     if (root == None)
1955     {
1956         fprintf (stderr, "[UTILX] Warning : Root window is None.. %s (%d)\n", __func__, __LINE__);
1957         return False;
1958     }
1959
1960     res = XRRGetScreenResources (dpy, root);
1961     if (res == NULL || res->noutput == 0)
1962     {
1963         fprintf (stderr, "[UTILX] Warning : ScreenResources is None.. %s (%d)\n", __func__, __LINE__);
1964         return False;
1965     }
1966
1967     for (i = 0; i < res->noutput; i++)
1968     {
1969         XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[i]);
1970         if (output_info)
1971         {
1972             if (!strcmp (output_info->name, "LVDS1"))
1973             {
1974                 rr_output = res->outputs[i];
1975                 XRRFreeOutputInfo(output_info);
1976                 break;
1977             }
1978             XRRFreeOutputInfo(output_info);
1979         }
1980     }
1981
1982     if (rr_output == None)
1983     {
1984         fprintf (stderr, "[UTILX] Warning : output is None.. %s (%d)\n", __func__, __LINE__);
1985         XRRFreeScreenResources (res);
1986         return False;
1987     }
1988
1989     XRRChangeOutputProperty (dpy, rr_output, atom,
1990                              XA_CARDINAL, 8, PropModeReplace, buf, buf_len);
1991
1992     if (get)
1993     {
1994         Atom actual_type;
1995         int actual_format;
1996         unsigned long nitems, bytes_after;
1997
1998         XRRGetOutputProperty (dpy, rr_output, atom,
1999                               0, 1024L,
2000                               True, False, XA_CARDINAL,
2001                               &actual_type, &actual_format,
2002                               &nitems, &bytes_after,
2003                               get);
2004     }
2005
2006     XSync (dpy, 0);
2007
2008     XRRFreeScreenResources (res);
2009
2010     return True;
2011 }
2012
2013 API void
2014 utilx_set_fb_visible (Display* dpy, Utilx_Fb_Type fb, Bool visible)
2015 {
2016     static Atom property = None;
2017     char buf[8192] = {0,};
2018     char *p = buf;
2019     int buf_len = 0;
2020
2021     if (!dpy)
2022     {
2023         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2024         return;
2025     }
2026
2027     if (fb <= UTILX_FB_TYPE_NONE || fb > UTILX_FB_TYPE_OVERLAY)
2028     {
2029         fprintf (stderr, "[UTILX] Error.. Invald fb(%d).. %s (%d)\n", fb, __func__, __LINE__);
2030         return;
2031     }
2032
2033     p += sprintf (p, "%d:", 0);
2034     p += sprintf (p, "%d", fb + 2);
2035     p += sprintf (p, ":%d", (visible > 0)? 1 : 0);
2036
2037     *p = '\0';
2038     p++;
2039
2040     buf_len = p - buf;
2041
2042     if (property == None)
2043         property = XInternAtom (dpy, XRR_PROPERTY_FB_VISIBLE, False);
2044
2045     if (property == None)
2046     {
2047         fprintf (stderr, "[UTILX] Warning : FB_VISIBLE property is None.. %s (%d)\n", __func__, __LINE__);
2048         return;
2049     }
2050
2051     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, NULL))
2052     {
2053         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2054         return;
2055     }
2056 }
2057
2058 API Bool
2059 utilx_get_fb_visible (Display* dpy, Utilx_Fb_Type fb)
2060 {
2061     static Atom property = None;
2062     char buf[32] = {0,};
2063     char *p = buf;
2064     int buf_len = 0;
2065     unsigned char *prop = NULL;
2066     Bool visible = False;
2067
2068     if (!dpy)
2069     {
2070         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2071         return False;
2072     }
2073
2074     if (fb <= UTILX_FB_TYPE_NONE || fb > UTILX_FB_TYPE_OVERLAY)
2075     {
2076         fprintf (stderr, "[UTILX] Error.. Invald fb(%d).. %s (%d)\n", fb, __func__, __LINE__);
2077         return False;
2078     }
2079
2080     p += sprintf (p, "%d:", 0);
2081     p += sprintf (p, "%d", fb + 2);
2082
2083     *p = '\0';
2084     p++;
2085
2086     buf_len = p - buf;
2087
2088     if (property == None)
2089         property = XInternAtom (dpy, XRR_PROPERTY_FB_VISIBLE, False);
2090
2091     if (property == None)
2092     {
2093         fprintf (stderr, "[UTILX] Warning : FB_VISIBLE property is None.. %s (%d)\n", __func__, __LINE__);
2094         return False;
2095     }
2096
2097     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, &prop))
2098     {
2099         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2100         return False;
2101     }
2102
2103     if (prop)
2104         visible = atoi((char*)prop);
2105
2106     return visible;
2107 }
2108
2109 API void
2110 utilx_set_video_offset (Display* dpy, int x, int y)
2111 {
2112     static Atom property = None;
2113     char buf[32] = {0,};
2114     char *p = buf;
2115     int buf_len = 0;
2116
2117     if (!dpy)
2118     {
2119         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2120         return;
2121     }
2122
2123     p += sprintf (p, "%d,%d", x, y);
2124
2125     *p = '\0';
2126     p++;
2127
2128     buf_len = p - buf;
2129
2130     if (property == None)
2131         property = XInternAtom (dpy, XRR_PROPERTY_VIDEO_OFFSET, False);
2132
2133     if (property == None)
2134     {
2135         fprintf (stderr, "[UTILX] Warning : VIDEO_OFFSET property is None.. %s (%d)\n", __func__, __LINE__);
2136         return;
2137     }
2138
2139     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, NULL))
2140     {
2141         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2142         return;
2143     }
2144 }