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