fix prevent bug
[framework/uifw/xorg/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     if (!driverName || !deviceName)
1619     {
1620         fprintf (stderr, "[UTILX] fail : Get DRI info !!\n");
1621         goto fail_init_dri2;
1622     }
1623
1624     /* drm_fd */
1625     info->drm_fd = open (deviceName, O_RDWR);
1626     if (info->drm_fd < 0)
1627     {
1628         fprintf (stderr, "[UTILX] fail : open drm device (%s)\n", deviceName);
1629         goto fail_init_dri2;
1630     }
1631
1632     /* get the drm magic */
1633     drmGetMagic(info->drm_fd, &magic);
1634     if (!DRI2Authenticate(info->dpy, RootWindow(info->dpy, screen), magic))
1635     {
1636         fprintf (stderr, "[UTILX] fail : DRI2Authenticate (%d)\n", magic);
1637         goto fail_init_dri2;
1638     }
1639
1640     /* bufmgr */
1641     info->bufmgr = tbm_bufmgr_init (info->drm_fd);
1642     if (!info->bufmgr)
1643     {
1644         fprintf (stderr, "[UTILX] fail : init buffer manager \n");
1645         goto fail_init_dri2;
1646     }
1647
1648     DRI2CreateDrawable (info->dpy, info->pixmap);
1649
1650     attachments[0] = DRI2BufferFrontLeft;
1651     dri2_count = 1;
1652     info->dri2_buffers = DRI2GetBuffers (info->dpy, info->pixmap, &dri2_width, &dri2_height,
1653                                          attachments, dri2_count, &dri2_out_count);
1654
1655     if (!info->dri2_buffers)
1656     {
1657         fprintf (stderr, "[UTILX] fail : get buffers\n");
1658         goto fail_init_dri2;
1659     }
1660
1661     if (!info->dri2_buffers[0].name)
1662     {
1663         fprintf (stderr, "[UTILX] fail : a handle of the dri2 buffer is null \n ");
1664         goto fail_init_dri2;
1665     }
1666
1667     info->bo = tbm_bo_import (info->bufmgr, info->dri2_buffers[0].name);
1668     if (!info->bo)
1669     {
1670         fprintf (stderr, "[UTILX] fail : import bo (key:%d)\n", info->dri2_buffers[0].name);
1671         goto fail_init_dri2;
1672     }
1673
1674     dri2_stride = info->dri2_buffers[0].pitch;
1675
1676     /* virtual */
1677     bo_handle = tbm_bo_get_handle (info->bo, TBM_DEVICE_CPU);
1678     info->virtual = (void *)bo_handle.ptr;
1679     if (!info->virtual)
1680     {
1681         fprintf (stderr, "[UTILX] fail : map \n");
1682         goto fail_init_dri2;
1683     }
1684
1685     info->enable_xshm = False;
1686
1687     free (driverName);
1688     free (deviceName);
1689
1690     return True;
1691
1692 fail_init_dri2:
1693
1694     if (info->bo)
1695         tbm_bo_unref(info->bo);
1696     if (info->dri2_buffers)
1697         free(info->dri2_buffers);
1698     if (info->bufmgr)
1699         tbm_bufmgr_deinit (info->bufmgr);
1700     if (info->drm_fd >= 0)
1701         close (info->drm_fd);
1702
1703     if (driverName)
1704         free (driverName);
1705     if (deviceName)
1706         free (deviceName);
1707
1708     return False;
1709 }
1710
1711 static Bool
1712 _init_screen_shot_shm (ShotInfo *info)
1713 {
1714     if (!XShmQueryExtension (info->dpy))
1715     {
1716         fprintf (stderr, "[UTILX] no XShm extension. !!\n");
1717         return False;
1718     }
1719
1720     info->image = XShmCreateImage (info->dpy,
1721                                    DefaultVisual (info->dpy, DefaultScreen (info->dpy)),
1722                                    DefaultDepth (info->dpy, DefaultScreen (info->dpy)),
1723                                    ZPixmap,
1724                                    NULL,
1725                                    &info->shminfo,
1726                                    info->width,
1727                                    info->height);
1728     if (!info->image)
1729     {
1730         fprintf (stderr, "[UTILX] fail : XShmCreateImage \n");
1731         return False;
1732     }
1733
1734     info->shminfo.shmid = shmget (IPC_PRIVATE, info->image->bytes_per_line * info->height, IPC_CREAT | 0777);
1735     if (info->shminfo.shmid == -1)
1736     {
1737         XDestroyImage (info->image);
1738         fprintf (stderr, "[UTILX] fail : shmget\n");
1739         return False;
1740     }
1741
1742     info->shminfo.shmaddr = shmat (info->shminfo.shmid, 0, 0);
1743     if (info->shminfo.shmaddr == (void *) -1)
1744     {
1745         XDestroyImage (info->image);
1746         shmctl (info->shminfo.shmid, IPC_RMID, 0);
1747         info->shminfo.shmid = -1;
1748         fprintf (stderr, "[UTILX] fail : shmat\n");
1749         return False;
1750     }
1751
1752     info->shminfo.readOnly = False;
1753
1754     if (!XShmAttach (info->dpy, &info->shminfo))
1755     {
1756         XDestroyImage (info->image);
1757         shmdt (info->shminfo.shmaddr);
1758         shmctl (info->shminfo.shmid, IPC_RMID, 0);
1759         info->shminfo.shmid = -1;
1760         fprintf (stderr, "[UTILX] fail : XShmAttach\n");
1761         return False;
1762     }
1763
1764     info->image->data = info->shminfo.shmaddr;
1765     info->virtual = info->shminfo.shmaddr;
1766
1767     info->enable_xshm = True;
1768
1769     return True;
1770 }
1771
1772 static ShotInfo*
1773 _init_screen_shot (Display* dpy, unsigned int width, unsigned int height)
1774 {
1775     ShotInfo *info = NULL;
1776     static Atom atom_capture = None;
1777     static Atom atom_fps = None;
1778     XErrorHandler old_handler = NULL;
1779
1780     if (shot_info)
1781     {
1782         if (shot_info->width == width && shot_info->height == height)
1783             return shot_info;
1784
1785         _deinit_screen_shot (shot_info);
1786     }
1787
1788     info = calloc (1, sizeof (ShotInfo));
1789     if (!info)
1790         goto fail_init;
1791
1792     shot_info = info;
1793
1794     /* dpy */
1795     info->dpy = dpy;
1796     info->shminfo.shmid = -1;
1797     info->shminfo.shmaddr = (void*)-1;
1798     info->drm_fd = -1;
1799
1800     /* port */
1801     info->port = _get_port (info->dpy, FOURCC_RGB32);
1802     if (info->port <= 0)
1803         goto fail_init;
1804
1805     /* width, height */
1806     if (atom_capture == None)
1807         atom_capture = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1808     if (atom_fps == None)
1809         atom_fps = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_FPS", False);
1810
1811     XSync (info->dpy, 0);
1812     x_error_caught = False;
1813     old_handler = XSetErrorHandler (_screen_shot_x_error_handle);
1814
1815     XvSetPortAttribute (info->dpy, info->port, atom_capture, 1);
1816     XvSetPortAttribute (info->dpy, info->port, atom_fps, 60);
1817
1818     XSync (info->dpy, 0);
1819
1820     x_error_caught = False;
1821     XSetErrorHandler (old_handler);
1822
1823     XvQueryBestSize (info->dpy, info->port, 0, 0, 0, width, height, &width, &height);
1824     if (width <= 0 || height <= 0)
1825         goto fail_init;
1826     info->width = width;
1827     info->height = height;
1828
1829     /* pixmap */
1830     info->pixmap = XCreatePixmap (info->dpy,
1831                                   DefaultRootWindow (info->dpy),
1832                                   width, height,
1833                                   DefaultDepth (info->dpy, DefaultScreen (info->dpy)));
1834     if (info->pixmap <= 0)
1835     {
1836         fprintf (stderr, "[UTILX] fail : create pixmap. \n");
1837         goto fail_init;
1838     }
1839
1840     /* gc */
1841     info->gc = XCreateGC (info->dpy, info->pixmap, 0, 0);
1842     if (info->gc == NULL)
1843     {
1844         fprintf (stderr, "[UTILX] fail : create gc. \n");
1845         goto fail_init;
1846     }
1847
1848     XSetForeground (info->dpy, info->gc, 0xFF000000);
1849     XFillRectangle (info->dpy, info->pixmap, info->gc, 0, 0, width, height);
1850
1851     if (!_init_screen_shot_damage (info))
1852         goto fail_init;
1853
1854     if (!_init_screen_shot_dri2 (info))
1855     {
1856         if (!_init_screen_shot_shm (info))
1857             goto fail_init;
1858         else
1859             fprintf (stderr, "[UTILX] XShm success. !!\n");
1860     }
1861
1862     if (!info->virtual)
1863     {
1864         fprintf (stderr, "[UTILX] fail : get virtual \n");
1865         goto fail_init;
1866     }
1867
1868     XFlush (info->dpy);
1869
1870     return info;
1871
1872 fail_init:
1873     _deinit_screen_shot (info);
1874     return NULL;
1875 }
1876
1877 API void*
1878 utilx_create_screen_shot (Display* dpy, int width, int height)
1879 {
1880     ShotInfo *info;
1881     XEvent ev = {0,};
1882     XErrorHandler old_handler = NULL;
1883
1884     if (dpy == NULL)
1885     {
1886         fprintf (stderr, "[UTILX] invalid display(%p) \n", dpy);
1887         return NULL;
1888     }
1889
1890     if (width <= 0 || height <= 0)
1891     {
1892         fprintf (stderr, "[UTILX] invalid size(%dx%d) \n", width, height);
1893         return NULL;
1894     }
1895
1896     XSync (dpy, 0);
1897
1898     info = _init_screen_shot (dpy, width, height);
1899
1900     if (!info)
1901     {
1902         fprintf (stderr, "[UTILX] fail : initialize screenshot. \n");
1903         return NULL;
1904     }
1905
1906     XSync (dpy, 0);
1907
1908     x_error_caught = False;
1909     old_handler = XSetErrorHandler (_screen_shot_x_error_handle);
1910
1911     XvPutStill (info->dpy, info->port, info->pixmap, info->gc,
1912                 0, 0, info->width, info->height,
1913                 0, 0, info->width, info->height);
1914
1915     XSync (dpy, 0);
1916
1917     if (x_error_caught)
1918     {
1919         x_error_caught = False;
1920         XSetErrorHandler (old_handler);
1921         return NULL;
1922     }
1923
1924     x_error_caught = False;
1925     XSetErrorHandler (old_handler);
1926
1927     if (XPending (info->dpy))
1928         XNextEvent (info->dpy, &ev);
1929     else
1930     {
1931         int fd = ConnectionNumber (info->dpy);
1932         fd_set mask;
1933         struct timeval tv;
1934         int ret;
1935
1936         FD_ZERO (&mask);
1937         FD_SET (fd, &mask);
1938
1939         tv.tv_usec = 0;
1940         tv.tv_sec = TIMEOUT_CAPTURE;
1941
1942         ret = select (fd + 1, &mask, 0, 0, &tv);
1943         if (ret < 0)
1944             fprintf (stderr, "[UTILX] fail: select.\n");
1945         else if (ret == 0)
1946             fprintf (stderr, "[UTILX] timeout(%d sec)!\n", TIMEOUT_CAPTURE);
1947         else if (XPending (info->dpy))
1948             XNextEvent (info->dpy, &ev);
1949         else
1950             fprintf (stderr, "[UTILX] fail: not passed a event!\n");
1951     }
1952
1953     if (ev.type == (info->damage_base + XDamageNotify))
1954     {
1955         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1956         if (damage_ev->drawable == info->pixmap)
1957         {
1958             if (info->enable_xshm)
1959                 XShmGetImage (info->dpy, info->pixmap, info->image, 0, 0, AllPlanes);
1960
1961             XDamageSubtract (info->dpy, info->damage, None, None );
1962             return info->virtual;
1963         }
1964
1965         XDamageSubtract (info->dpy, info->damage, None, None );
1966     }
1967
1968     utilx_release_screen_shot ();
1969
1970     return NULL;
1971 }
1972
1973 API void
1974 utilx_release_screen_shot (void)
1975 {
1976     _deinit_screen_shot (shot_info);
1977 }
1978
1979 #define XRR_PROPERTY_FB_VISIBLE     "XRR_PROPERTY_FB_VISIBLE"
1980 #define XRR_PROPERTY_VIDEO_OFFSET   "XRR_PROPERTY_VIDEO_OFFSET"
1981
1982 static Bool
1983 _utilx_xrr_set_property (Display* dpy, Atom atom, unsigned char *buf, int buf_len, unsigned char **get)
1984 {
1985     Window root = None;
1986     XRRScreenResources *res = NULL;
1987     RROutput rr_output = None;
1988     int i;
1989
1990     root = XRootWindow (dpy, 0);
1991     if (root == None)
1992     {
1993         fprintf (stderr, "[UTILX] Warning : Root window is None.. %s (%d)\n", __func__, __LINE__);
1994         return False;
1995     }
1996
1997     res = XRRGetScreenResources (dpy, root);
1998     if (res == NULL || res->noutput == 0)
1999     {
2000         fprintf (stderr, "[UTILX] Warning : ScreenResources is None.. %s (%d)\n", __func__, __LINE__);
2001         return False;
2002     }
2003
2004     for (i = 0; i < res->noutput; i++)
2005     {
2006         XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[i]);
2007         if (output_info)
2008         {
2009             if (!strcmp (output_info->name, "LVDS1"))
2010             {
2011                 rr_output = res->outputs[i];
2012                 XRRFreeOutputInfo(output_info);
2013                 break;
2014             }
2015             XRRFreeOutputInfo(output_info);
2016         }
2017     }
2018
2019     if (rr_output == None)
2020     {
2021         fprintf (stderr, "[UTILX] Warning : output is None.. %s (%d)\n", __func__, __LINE__);
2022         XRRFreeScreenResources (res);
2023         return False;
2024     }
2025
2026     XRRChangeOutputProperty (dpy, rr_output, atom,
2027                              XA_CARDINAL, 8, PropModeReplace, buf, buf_len);
2028
2029     if (get)
2030     {
2031         Atom actual_type;
2032         int actual_format;
2033         unsigned long nitems, bytes_after;
2034
2035         XRRGetOutputProperty (dpy, rr_output, atom,
2036                               0, 1024L,
2037                               True, False, XA_CARDINAL,
2038                               &actual_type, &actual_format,
2039                               &nitems, &bytes_after,
2040                               get);
2041     }
2042
2043     XSync (dpy, 0);
2044
2045     XRRFreeScreenResources (res);
2046
2047     return True;
2048 }
2049
2050 API void
2051 utilx_set_fb_visible (Display* dpy, Utilx_Fb_Type fb, Bool visible)
2052 {
2053     static Atom property = None;
2054     char buf[8192] = {0,};
2055     char *p = buf;
2056     int buf_len = 0;
2057
2058     if (!dpy)
2059     {
2060         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2061         return;
2062     }
2063
2064     if (fb <= UTILX_FB_TYPE_NONE || fb > UTILX_FB_TYPE_OVERLAY)
2065     {
2066         fprintf (stderr, "[UTILX] Error.. Invald fb(%d).. %s (%d)\n", fb, __func__, __LINE__);
2067         return;
2068     }
2069
2070     p += sprintf (p, "%d:", 0);
2071     p += sprintf (p, "%d", fb + 2);
2072     p += sprintf (p, ":%d", (visible > 0)? 1 : 0);
2073
2074     *p = '\0';
2075     p++;
2076
2077     buf_len = p - buf;
2078
2079     if (property == None)
2080         property = XInternAtom (dpy, XRR_PROPERTY_FB_VISIBLE, False);
2081
2082     if (property == None)
2083     {
2084         fprintf (stderr, "[UTILX] Warning : FB_VISIBLE property is None.. %s (%d)\n", __func__, __LINE__);
2085         return;
2086     }
2087
2088     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, NULL))
2089     {
2090         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2091         return;
2092     }
2093 }
2094
2095 API Bool
2096 utilx_get_fb_visible (Display* dpy, Utilx_Fb_Type fb)
2097 {
2098     static Atom property = None;
2099     char buf[32] = {0,};
2100     char *p = buf;
2101     int buf_len = 0;
2102     unsigned char *prop = NULL;
2103     Bool visible = False;
2104
2105     if (!dpy)
2106     {
2107         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2108         return False;
2109     }
2110
2111     if (fb <= UTILX_FB_TYPE_NONE || fb > UTILX_FB_TYPE_OVERLAY)
2112     {
2113         fprintf (stderr, "[UTILX] Error.. Invald fb(%d).. %s (%d)\n", fb, __func__, __LINE__);
2114         return False;
2115     }
2116
2117     p += sprintf (p, "%d:", 0);
2118     p += sprintf (p, "%d", fb + 2);
2119
2120     *p = '\0';
2121     p++;
2122
2123     buf_len = p - buf;
2124
2125     if (property == None)
2126         property = XInternAtom (dpy, XRR_PROPERTY_FB_VISIBLE, False);
2127
2128     if (property == None)
2129     {
2130         fprintf (stderr, "[UTILX] Warning : FB_VISIBLE property is None.. %s (%d)\n", __func__, __LINE__);
2131         return False;
2132     }
2133
2134     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, &prop))
2135     {
2136         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2137         return False;
2138     }
2139
2140     if (prop)
2141         visible = atoi((char*)prop);
2142
2143     return visible;
2144 }
2145
2146 API void
2147 utilx_set_video_offset (Display* dpy, int x, int y)
2148 {
2149     static Atom property = None;
2150     char buf[32] = {0,};
2151     char *p = buf;
2152     int buf_len = 0;
2153
2154     if (!dpy)
2155     {
2156         fprintf (stderr, "[UTILX] invalid display(%p).. %s (%d)\n", dpy, __func__, __LINE__);
2157         return;
2158     }
2159
2160     p += sprintf (p, "%d,%d", x, y);
2161
2162     *p = '\0';
2163     p++;
2164
2165     buf_len = p - buf;
2166
2167     if (property == None)
2168         property = XInternAtom (dpy, XRR_PROPERTY_VIDEO_OFFSET, False);
2169
2170     if (property == None)
2171     {
2172         fprintf (stderr, "[UTILX] Warning : VIDEO_OFFSET property is None.. %s (%d)\n", __func__, __LINE__);
2173         return;
2174     }
2175
2176     if (!_utilx_xrr_set_property (dpy, property, (unsigned char*)buf, buf_len, NULL))
2177     {
2178         fprintf (stderr, "[UTILX] Warning : set_property failed.. %s (%d)\n", __func__, __LINE__);
2179         return;
2180     }
2181 }