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