upload tizen2.0 source
[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
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <X11/Xatom.h>
28
29 #include "utilX.h"
30 #include "util_x11.h"
31
32 #include <fcntl.h>
33 #include <X11/extensions/Xvlib.h>
34 #include <X11/extensions/Xvproto.h>
35 #include <X11/extensions/Xdamage.h>
36 #include <dri2.h>
37 #include <drm_slp_bufmgr.h>
38
39
40 #define UTILX_DEBUG 0
41 #if UTILX_DEBUG
42 #define UTILX_TRACE  printf
43 #else
44 #define UTILX_TRACE(...)
45 #endif
46
47 static Atom _atom_grab_key = None;
48 static Atom _atom_grab_excl_win = None;
49 static Atom _atom_grab_or_excl_win = None;
50
51 static Atom _atom_notification_level = None;
52 static Atom _atom_indicator_visible_state = None;
53 static Atom _atom_indicator_visible_state_on = None;
54 static Atom _atom_indicator_visible_state_off = None;
55
56 static Atom _atom_comp_effect_state = None;
57 static Atom _atom_comp_fake_launch = None;
58 static Atom _atom_comp_fake_launch_image = None;
59
60 static Atom _atom_comp_window_effect_type = None;
61 static Atom _atom_comp_effect_default = None;
62 static Atom _atom_comp_effect_none = None;
63 static Atom _atom_comp_effect_custom0 = None;
64 static Atom _atom_comp_effect_custom1 = None;
65 static Atom _atom_comp_effect_custom2 = None;
66 static Atom _atom_comp_effect_custom3 = None;
67 static Atom _atom_comp_effect_custom4 = None;
68 static Atom _atom_comp_effect_custom5 = None;
69 static Atom _atom_comp_effect_custom6 = None;
70 static Atom _atom_comp_effect_custom7 = None;
71 static Atom _atom_comp_effect_custom8 = None;
72 static Atom _atom_comp_effect_custom9 = None;
73
74 static Atom _atom_window_opaque = None;
75
76 static Atom _atom_screen_capture_disable = None;
77
78 static Atom _atom_comp_capture_effect = None;
79
80 const unsigned long maxlen = 1024l;
81
82 static void _utilx_set_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int num);
83 static int _utilx_get_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int len);
84
85 static void _utilx_effect_atom_check( Display* dpy );
86 static Atom _utilx_convert_style_to_atom( Display* dpy, Utilx_Effect_Style style );
87 static Utilx_Effect_Style _utilx_convert_atom_to_style( Display* dpy, Atom style );
88
89 static int _utilx_get_indicator_atoms(Display *dpy);
90
91 API void utilx_set_system_notification_level (Display* dpy, Window win, Utilx_Notification_Level level)
92 {
93         UTILX_TRACE ("[UTILX] utilx_set_system_notification_level... win = %x, level = %d\n", win, level);
94
95         int noti_level;
96
97         if (dpy == NULL)
98         {
99                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
100                 return;
101         }
102
103         switch (level)
104         {
105                 case UTILX_NOTIFICATION_LEVEL_LOW:
106                         noti_level = 50;
107                         break;
108
109                 case UTILX_NOTIFICATION_LEVEL_NORMAL:
110                         noti_level = 100;
111                         break;
112
113                 case UTILX_NOTIFICATION_LEVEL_HIGH:
114                         noti_level = 150;
115                         break;
116
117                 default:
118                         noti_level = 50;
119                         break;
120         }
121
122         if (!_atom_notification_level)
123         {
124                 _atom_notification_level = XInternAtom (dpy, "_E_ILLUME_NOTIFICATION_LEVEL", False);
125                 if (!_atom_notification_level)
126                 {
127                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_NOTIFICATION_LEVEL atom.. %s (%d)\n", __func__, __LINE__);
128                         return;
129                 }
130         }
131
132         _utilx_set_window_property (dpy, win, _atom_notification_level, XA_CARDINAL,
133                         (unsigned int *)&noti_level, 1);
134 }
135
136
137 API Utilx_Notification_Level utilx_get_system_notification_level (Display* dpy, Window win)
138 {
139         UTILX_TRACE ("[UTILX] utilx_get_system_notification_level... win = %x\n", win);
140
141         Utilx_Notification_Level noti_level;
142         unsigned int level;
143         int ret;
144
145         noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
146
147         if (dpy == NULL)
148         {
149                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
150                 goto error;
151         }
152
153         if (!_atom_notification_level)
154         {
155                 _atom_notification_level = XInternAtom (dpy, "_E_ILLUME_NOTIFICATION_LEVEL", False);
156                 if (!_atom_notification_level)
157                 {
158                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_NOTIFICATION_LEVEL atom.. %s (%d)\n", __func__, __LINE__);
159                         goto error;
160                 }
161         }
162
163         ret = _utilx_get_window_property (dpy, win, _atom_notification_level, XA_CARDINAL,
164                         (unsigned int *)&level, 1);
165
166         if (ret > 0)
167         {
168                 switch (level)
169                 {
170                         case 50:
171                                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
172                                 break;
173
174                         case 100:
175                                 noti_level = UTILX_NOTIFICATION_LEVEL_NORMAL;
176                                 break;
177
178                         case 150:
179                                 noti_level = UTILX_NOTIFICATION_LEVEL_HIGH;
180                                 break;
181
182                         default:
183                                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
184                                 break;
185                 }
186         }
187         else
188         {
189                 noti_level = UTILX_NOTIFICATION_LEVEL_LOW;
190         }
191
192 error:
193         return noti_level;
194 }
195
196 static int _utilx_get_indicator_atoms(Display *dpy)
197 {
198         if (!_atom_indicator_visible_state)
199         {
200                 _atom_indicator_visible_state = XInternAtom (dpy, "_E_ILLUME_INDICATOR_STATE", False);
201                 if (!_atom_indicator_visible_state)
202                 {
203                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_STATE atom.. %s (%d)\n", __func__, __LINE__);
204                         return 0;
205                 }
206         }
207
208         if (!_atom_indicator_visible_state_on)
209         {
210                 _atom_indicator_visible_state_on = XInternAtom (dpy, "_E_ILLUME_INDICATOR_ON", False);
211                 if (!_atom_indicator_visible_state_on)
212                 {
213                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_ON atom.. %s (%d)\n", __func__, __LINE__);
214                         return 0;
215                 }
216         }
217
218         if (!_atom_indicator_visible_state_off)
219         {
220                 _atom_indicator_visible_state_off = XInternAtom (dpy, "_E_ILLUME_INDICATOR_OFF", False);
221                 if (!_atom_indicator_visible_state_off)
222                 {
223                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_INDICATOR_OFF atom.. %s (%d)\n", __func__, __LINE__);
224                         return 0;
225                 }
226         }
227
228         return 1;
229 }
230
231 API void utilx_enable_indicator (Display* dpy, Window win, int enable)
232 {
233         UTILX_TRACE ("[UTILX] utilx_indicator_set_visible_state... win = %x, show_state = %d\n", win, enable);
234
235         if (dpy == NULL)
236         {
237                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
238                 return;
239         }
240
241         if (!_utilx_get_indicator_atoms(dpy))
242         {
243                 fprintf (stderr, "[UTILX] Error.. Cannot create atoms.. %s (%d)\n", __func__, __LINE__);
244                 return;
245         }
246
247         if (enable == 1)
248         {
249                 _utilx_set_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
250                         (unsigned int *)&_atom_indicator_visible_state_on, 1);
251         }
252         else
253         {
254                 _utilx_set_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
255                         (unsigned int *)&_atom_indicator_visible_state_off, 1);
256         }
257 }
258
259
260 API int utilx_get_indicator_state (Display* dpy, Window win)
261 {
262         UTILX_TRACE ("[UTILX] utilx_indicator_set_visible_state... win = %x, show_state = %d\n", win, enable);
263
264         int ret;
265         Atom state;
266
267         if (dpy == NULL)
268         {
269                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
270                 return -1;
271         }
272
273         if (!_utilx_get_indicator_atoms(dpy))
274         {
275                 fprintf (stderr, "[UTILX] Error.. Cannot create atoms.. %s (%d)\n", __func__, __LINE__);
276                 return;
277         }
278
279         ret = _utilx_get_window_property (dpy, win, _atom_indicator_visible_state, XA_ATOM,
280                         (unsigned int *)&state, 1);
281
282         if (ret > 0)
283         {
284                 if (state == _atom_indicator_visible_state_on)
285                         return 1;
286                 else if (state == _atom_indicator_visible_state_off)
287                         return 0;
288                 else
289                         return -1;
290         }
291         else
292                 return -1;
293 }
294
295 static void
296 _utilx_set_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int num)
297 {
298         XChangeProperty (dpy, win, atom, type, 32, PropModeReplace, (unsigned char *)val, num);
299         XSync(dpy, 0 );
300 }
301
302
303 static int
304 _utilx_get_window_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int len)
305 {
306         unsigned char* prop_ret;
307         Atom type_ret;
308         unsigned long bytes_after, num_ret;
309         int format_ret;
310         unsigned int i;
311         int num;
312
313         prop_ret = NULL;
314         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
315                                 type, &type_ret, &format_ret, &num_ret,
316                                 &bytes_after, &prop_ret) != Success)
317         {
318                 return -1;
319         }
320
321         if (type_ret != type || format_ret != 32)
322         {
323                 num = -1;
324         }
325         else if (num_ret == 0 || !prop_ret)
326         {
327                 num = 0;
328         }
329         else
330         {
331                 if (num_ret < len)
332                 len = num_ret;
333                 for (i = 0; i < len; i++)
334                 {
335                         val[i] = ((unsigned long *)prop_ret)[i];
336                 }
337                 num = len;
338         }
339
340         if (prop_ret)
341                 XFree(prop_ret);
342
343         return num;
344
345 }
346
347
348 static unsigned long _get_list_of_grabbed_key (Display *disp, Window win, int **key_list)
349 {
350         Atom ret_type;
351         int ret_format;
352         unsigned long nr_item;
353         unsigned long sz_remains_data;
354
355         if (XGetWindowProperty(disp, win,
356                 _atom_grab_key, 0, 0x7fffffff, False, XA_CARDINAL,
357                 &ret_type, &ret_format, &nr_item,
358                 &sz_remains_data, (unsigned char**)key_list) != Success)
359         {
360                 nr_item = 0;
361         }
362
363 //      fprintf(stderr, "\e[31m%d - %lu\e[0m\n", ret_format, nr_item);
364
365         return nr_item;
366 }
367
368
369 static void _free_list_of_grabbed_key (int *key_list)
370 {
371         if (key_list) {
372                 XFree(key_list);
373         }
374 }
375
376
377 static void _free_new_list_of_grabbed_key (int *new_key_list)
378 {
379         if (new_key_list) {
380                 free(new_key_list);
381         }
382 }
383
384
385 static int _search_grabbed_key (int *key_list, int key, unsigned long cnt)
386 {
387         register int i;
388
389         for (i = cnt - 1; i >= 0; i --) {
390                 if (key_list[i] == key) break;
391         }
392
393         return i;
394 }
395
396
397 static int *_del_grabbed_key (int *key_list, int i, unsigned long *cnt)
398 {
399         int *new_key_list = NULL;
400
401         // Only one element is exists in the list of grabbed key
402         (*cnt) --;
403
404         if (*cnt == 0) return NULL;
405
406         // Shrink the buffer
407         new_key_list = malloc((*cnt) * sizeof(int));
408         if (new_key_list == NULL) {
409                 perror(__func__);
410                 return NULL;
411         }
412
413         // copy head
414         if (i > 0) {
415                 memcpy(new_key_list, key_list, sizeof(int) * i);
416         }
417
418         // copy tail
419         if ((*cnt) - i > 0) {
420                 memcpy(new_key_list + i,
421                         key_list + i + 1,
422                         sizeof(int) * ((*cnt) - i)
423                 );
424         }
425         return new_key_list;
426 }
427
428
429 static void _set_exclusive_grab_info_to_root (Display *disp, int keycode, Window win, int grab_mode)
430 {
431         int i;
432         int *key_list = NULL;
433
434         Atom ret_type;
435         int ret_format;
436         unsigned long nr_item;
437         unsigned long sz_remains_data;
438         Window ex_grabwin;
439
440         if( grab_mode == EXCLUSIVE_GRAB )
441         {
442                 if( _atom_grab_excl_win == None )
443                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
444                 ex_grabwin = _atom_grab_excl_win;
445         }
446         else if( grab_mode == OR_EXCLUSIVE_GRAB )
447         {
448                 if( _atom_grab_or_excl_win == None )
449                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
450                 ex_grabwin = _atom_grab_or_excl_win;
451         }
452         else
453                 return;
454
455         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
456                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
457                 &ret_type, &ret_format, &nr_item,
458                 &sz_remains_data, (unsigned char**)&key_list) != Success)
459         {
460                 fprintf(stderr, "[utilX][%s] Fail to get root window property !\n", __FUNCTION__);
461                 goto out;
462         }
463
464 #ifdef __DEBUG__
465         printf("[%s] keycode = %d\n", __FUNCTION__, keycode);
466 #endif
467
468         for( i=0 ; i < nr_item ; i++ )
469         {
470                 if( key_list && (key_list[i] == keycode) )
471                         return;
472         }
473
474         XChangeProperty(disp, DefaultRootWindow(disp), ex_grabwin, XA_CARDINAL, 32,
475         nr_item ? PropModeAppend : PropModeReplace, (unsigned char *)&keycode, 1);
476         XSync(disp, False);
477
478 out:
479         return;
480 }
481
482
483 static void _unset_exclusive_grab_info_to_root (Display *disp, int keycode, int grab_mode)
484 {
485         int i;
486         unsigned long cnt = 0;
487         int *key_list = NULL;
488         int *new_key_list = NULL;
489
490         Atom ret_type;
491         int ret_format;
492         unsigned long nr_item;
493         unsigned long sz_remains_data;
494         Window ex_grabwin;
495
496         if( grab_mode == EXCLUSIVE_GRAB )
497         {
498                 if( _atom_grab_excl_win == None )
499                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
500                 ex_grabwin = _atom_grab_excl_win;
501         }
502         else if( grab_mode == OR_EXCLUSIVE_GRAB )
503         {
504                 if( _atom_grab_or_excl_win == None )
505                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
506                 ex_grabwin = _atom_grab_or_excl_win;
507         }
508         else
509                 return;
510
511         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
512                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
513                 &ret_type, &ret_format, &nr_item,
514                 &sz_remains_data, (unsigned char**)&key_list) != Success)
515         {
516                 nr_item = 0;
517         }
518
519         if (nr_item == 0)
520         {
521                 fprintf(stderr, "\e[32m[utilX][%s] keycode = %d\e[0m\n", __FUNCTION__, keycode);
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 #ifdef __DEBUG__
535         fprintf(stderr, "[utilX][%s] cnt = %d, nr_item = %d\n", __FUNCTION__, cnt, nr_item);
536 #endif
537
538         if( 0 < cnt )
539         {
540                 new_key_list = malloc(sizeof(int)*cnt);
541                 cnt = 0;
542         }
543         else
544                 new_key_list = NULL;
545
546         if( !new_key_list )
547         {
548                 //fprintf(stderr, "\e[32m[utilX][%s] Fail to allocation memory for new_key_list ! \e[0m\n", __FUNCTION__);
549                 XDeleteProperty(disp, DefaultRootWindow(disp), ex_grabwin);
550                 XSync(disp, False);
551                 goto out;
552         }
553
554         for( i=0 ; i < nr_item ; i++ )
555         {
556                 if( key_list[i] == keycode )//&& grab_mode == EXCLUSIVE_GRAB )
557                 {
558                         continue;
559                 }
560                 else
561                         new_key_list[cnt++] = key_list[i];
562         }
563
564         if (new_key_list) {
565                 XChangeProperty(disp, DefaultRootWindow(disp), ex_grabwin, XA_CARDINAL, 32,
566                         PropModeReplace, (unsigned char *)new_key_list, cnt);
567         }
568         else {
569                 XDeleteProperty(disp, DefaultRootWindow(disp), ex_grabwin);
570         }
571         XSync(disp, False);
572
573         if(new_key_list)
574                 free(new_key_list);
575
576 out:
577         return;
578 }
579
580
581 static int _is_grabbed_key_exclusively (Display* disp, int keycode, int grab_mode)
582 {
583         int i, result = 0;
584         int *key_list = NULL;
585
586         Atom ret_type;
587         int ret_format;
588         unsigned long nr_item;
589         unsigned long sz_remains_data;
590         Window ex_grabwin;
591
592         if( grab_mode == EXCLUSIVE_GRAB )
593         {
594                 if( _atom_grab_excl_win == None )
595                         _atom_grab_excl_win = XInternAtom(disp, STR_ATOM_GRAB_EXCL_WIN, False);
596                 ex_grabwin = _atom_grab_excl_win;
597         }
598         else if( grab_mode == OR_EXCLUSIVE_GRAB )
599         {
600                 if( _atom_grab_or_excl_win == None )
601                         _atom_grab_or_excl_win = XInternAtom(disp, STR_ATOM_GRAB_OR_EXCL_WIN, False);
602                 ex_grabwin = _atom_grab_or_excl_win;
603         }
604         else
605                 return result;
606
607         if (XGetWindowProperty(disp, DefaultRootWindow(disp),
608                 ex_grabwin, 0, 0x7fffffff, False, XA_CARDINAL,
609                 &ret_type, &ret_format, &nr_item,
610                 &sz_remains_data, (unsigned char**)&key_list) != Success)
611         {
612                 fprintf(stderr, "[%s] Fail to get root window property !\n", __FUNCTION__);
613                 goto out;
614         }
615
616         for( i=0 ; i < nr_item ; i++ )
617         {
618                 if( key_list[i] == keycode )
619                         return EXCLUSIVE_GRABBED_ALREADY;
620         }
621
622 out:
623         return result;
624 }
625
626 API int utilx_grab_key (Display* disp, Window win, const char* key, int grab_mode)
627 {
628         unsigned long cnt;
629         int *key_list = NULL;
630         int i, result = 0;
631         int keycode = 0;
632         KeySym keysym;
633         errno = EINVAL;
634
635         if( NULL == disp )
636         {
637                 fprintf(stderr, "[%s] Display is NULL\n", __FUNCTION__);
638                 return -1;
639         }
640
641         if (_atom_grab_key == None) {
642                 _atom_grab_key = XInternAtom(disp, STR_ATOM_GRAB_KEY, False);
643         }
644
645         if (!strncmp(key, "Keycode-", 8)) {
646                 keycode = atoi(key + 8);
647         } else {
648                 keysym = XStringToKeysym(key);
649                 if (keysym == NoSymbol) goto out;
650                 keycode = XKeysymToKeycode(disp, XStringToKeysym(key));
651         }
652         if (keycode == 0) goto out;
653
654         if( grab_mode == EXCLUSIVE_GRAB )
655         {
656                 //Window grabWin;
657                 result = _is_grabbed_key_exclusively(disp, keycode, grab_mode);
658
659 #ifdef __DEBUG__
660                 printf("[%s] _is_grabbed_key_exclusively returns result = %d\n", __FUNCTION__, result);
661 #endif
662
663                 if( result )
664                 {
665                         fprintf(stderr, "[%s] keycode(%d) was already grabbed exclusively (grab_mode=0x%X) !\n", __FUNCTION__, keycode, grab_mode);
666                         goto out;
667                 }
668         }
669         else if( grab_mode == OR_EXCLUSIVE_GRAB )
670         {
671                 result = _is_grabbed_key_exclusively(disp, keycode, grab_mode);
672
673                 if( result )
674                 {
675                         fprintf(stderr, "[%s] Keycode(%d) was already grabbed with overridable exclusive mode (grab_mode=0x%x)\n", __FUNCTION__, keycode, grab_mode);
676                         fprintf(stderr, "[%s] Now it will be overridden by a new window(0x%x) !\n", __FUNCTION__, win);
677                         utilx_ungrab_key(disp, win, key);
678                 }
679         }
680
681         keycode |= grab_mode;
682
683         cnt = _get_list_of_grabbed_key(disp, win, &key_list);
684         if (cnt > 0) {
685                 i = _search_grabbed_key(key_list, keycode, cnt);
686                 _free_list_of_grabbed_key(key_list);
687                 if ( i != -1 ) {
688                         if( grab_mode == OR_EXCLUSIVE_GRAB )
689                         {
690                                 utilx_ungrab_key(disp, win, key);
691                         }
692                         else
693                         {
694                         fprintf(stderr, "Key is already grabbed\n");
695                         goto out;
696                         }
697                 }
698         }
699
700         XChangeProperty(disp, win, _atom_grab_key, XA_CARDINAL, 32,
701                         cnt ? PropModeAppend : PropModeReplace, (unsigned char *)&keycode, 1);
702         XSync(disp, False);
703         keycode = keycode & (~GRAB_MODE_MASK);
704 #ifdef __DEBUG__
705         printf("[%s] keycode = %d\n", __FUNCTION__, keycode);
706 #endif
707
708         if( EXCLUSIVE_GRAB == grab_mode || OR_EXCLUSIVE_GRAB == grab_mode )
709                 _set_exclusive_grab_info_to_root(disp, keycode, win, grab_mode);
710
711         errno = 0;
712
713 out:
714
715         return result;
716 }
717
718
719 API int utilx_ungrab_key (Display* disp, Window win, const char* key)
720 {
721         int i;
722         unsigned long cnt;
723         int *key_list = NULL;
724         int *new_key_list = NULL;
725         long keycode = 0;
726         KeySym keysym;
727         int ret = -1;
728         errno = EINVAL;
729
730         if( NULL == disp )
731         {
732                 fprintf(stderr, "[%s] Display is NULL\n", __FUNCTION__);
733                 return -1;
734         }
735
736         if (_atom_grab_key == None) {
737                 _atom_grab_key = XInternAtom(disp, STR_ATOM_GRAB_KEY, False);
738         }
739
740         if (!strncmp(key, "Keycode-", 8)) {
741                 keycode = atoi(key + 8);
742         } else {
743                 keysym = XStringToKeysym(key);
744                 if (keysym == NoSymbol) goto out;
745                 keycode = XKeysymToKeycode(disp, XStringToKeysym(key));
746         }
747         if (keycode == 0) goto out;
748
749         cnt = _get_list_of_grabbed_key(disp, win, &key_list);
750         if (cnt == 0) goto out;
751
752         //EXCLUSIVE mode
753         i = _search_grabbed_key(key_list, keycode | EXCLUSIVE_GRAB, cnt);
754
755         if ( i == -1)
756         {
757                 //OR_EXCLUSIVE mode
758                 i = _search_grabbed_key(key_list, keycode | OR_EXCLUSIVE_GRAB, cnt);
759
760                 if ( i == -1)
761                 {
762                         //TOP_POSITION mode
763                         i = _search_grabbed_key(key_list, keycode | TOP_POSITION_GRAB, cnt);
764
765                         if (i == -1)
766                         {
767                                 //SHARED mode
768                                 i = _search_grabbed_key(key_list, keycode | SHARED_GRAB, cnt);
769
770                                 if (i == -1)
771                                 {
772                                         _free_list_of_grabbed_key(key_list);
773                                         goto out;
774                                 }
775                         }
776                 }
777                 else
778                 {
779                         _unset_exclusive_grab_info_to_root(disp, keycode, OR_EXCLUSIVE_GRAB);
780                 }
781         }
782         else
783         {
784                 _unset_exclusive_grab_info_to_root(disp, keycode, EXCLUSIVE_GRAB);
785         }
786
787         new_key_list = _del_grabbed_key(key_list, i, &cnt);
788         _free_list_of_grabbed_key(key_list);
789
790         if (new_key_list) {
791                 XChangeProperty(disp, win, _atom_grab_key, XA_CARDINAL, 32,
792                         PropModeReplace, (unsigned char *)new_key_list, cnt);
793         }
794         else {
795                 XDeleteProperty(disp, win, _atom_grab_key);
796         }
797         XSync(disp, False);
798
799         _free_new_list_of_grabbed_key(new_key_list);
800         ret = 0;
801         errno = 0;
802
803 out:
804
805         return ret;
806 }
807
808 API Utilx_Key_Status utilx_get_key_status(Display* dpy, char *key_name)
809 {
810         unsigned char keymap[32];
811         static unsigned int masktable[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
812         Utilx_Key_Status status = UTILX_KEY_STATUS_UNKNOWN;
813
814         if( !strncmp(key_name, KEY_VOLUMEDOWN, LEN_KEY_VOLUMEDOWN) ||
815                 !strncmp(key_name, KEY_VOLUMEUP, LEN_KEY_VOLUMEUP) ||
816                 !strncmp(key_name, KEY_PAUSE, LEN_KEY_PAUSE) ||
817                 !strncmp(key_name, KEY_SEND, LEN_KEY_SEND) ||
818                 !strncmp(key_name, KEY_SELECT, LEN_KEY_VOLUMEDOWN) ||
819                 !strncmp(key_name, KEY_END, LEN_KEY_END) ||
820                 !strncmp(key_name, KEY_POWER, LEN_KEY_POWER) ||
821                 !strncmp(key_name, KEY_CAMERA, LEN_KEY_CAMERA) ||
822                 !strncmp(key_name, KEY_CONFIG, LEN_KEY_CONFIG) ||
823                 !strncmp(key_name, KEY_PLAYCD, LEN_KEY_PLAYCD) ||
824                 !strncmp(key_name, KEY_STOPCD, LEN_KEY_STOPCD) ||
825                 !strncmp(key_name, KEY_PAUSECD, LEN_KEY_PAUSECD) ||
826                 !strncmp(key_name, KEY_NEXTSONG, LEN_KEY_NEXTSONG) ||
827                 !strncmp(key_name, KEY_PREVIOUSSONG, LEN_KEY_PREVIOUSSONG) ||
828                 !strncmp(key_name, KEY_REWIND, LEN_KEY_REWIND) ||
829                 !strncmp(key_name, KEY_FASTFORWARD, LEN_KEY_FASTFORWARD) ||
830                 !strncmp(key_name, KEY_MEDIA, LEN_KEY_MEDIA) )
831         {
832                 KeySym ks = XStringToKeysym(key_name);
833                 KeyCode kc = XKeysymToKeycode(dpy, ks);
834
835                 if( kc )
836                 {
837                         XQueryKeymap(dpy, (char *)keymap);
838                         if( keymap[kc >> 3] & masktable[kc & 7] )
839                                 status = UTILX_KEY_STATUS_PRESSED;
840                         else
841                                 status = UTILX_KEY_STATUS_RELEASED;
842                 }
843         }
844
845         return status;
846 }
847
848 API void utilx_set_window_effect_state(Display* dpy, Window win, int state)
849 {
850         if ( dpy == NULL )
851         {
852                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
853                 return;
854         }
855         if( !_atom_comp_effect_state)
856                 _atom_comp_effect_state = XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_ENABLE",False);
857
858         _utilx_set_window_property(dpy, win, _atom_comp_effect_state, XA_CARDINAL, (unsigned int *)&state, 1);
859
860         XSync(dpy, 0 );
861 }
862
863 API int utilx_get_window_effect_state(Display* dpy, Window win)
864 {
865         int state = 0;
866         if( !_atom_comp_effect_state)
867                 _atom_comp_effect_state = XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_ENABLE",False);
868         _utilx_get_window_property(dpy, win, _atom_comp_effect_state, XA_CARDINAL, (unsigned int *)&state, 1);
869         return state;
870 }
871
872 static void
873 _utilx_string_set_window_property( Display *dpy, Window win, Atom atom, char *val, unsigned int num)
874 {
875         XChangeProperty( dpy, win, atom, XA_STRING, 8, PropModeReplace, (unsigned char*)val, val ? strlen(val):0 );
876 }
877
878 API void utilx_set_fake_launch_img(Display* dpy, Window win, char *file_name)
879 {
880         //UTILX_TRACE ("[UTILX] utilx_set_effect_state... win = %x, show_state = %d\n", win, enable);
881
882         if ( dpy == NULL )
883         {
884                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
885                 return;
886         }
887         if( !_atom_comp_fake_launch_image)
888                 _atom_comp_fake_launch_image = XInternAtom(dpy, "_E_COMP_FAKE_LAUNCH_IMAGE",False);
889
890         _utilx_string_set_window_property(dpy, win, _atom_comp_fake_launch_image, file_name, 1);
891 }
892
893 API void utilx_show_fake_effect( Display *dpy, Window win, char *fake_image_file )
894 {
895         XEvent xev;
896
897         _atom_comp_fake_launch = XInternAtom( dpy, "_E_COMP_FAKE_LAUNCH", False );
898
899         if(  !_atom_comp_fake_launch )
900         {
901                 fprintf( stderr, "XInternAtom(_E_COMP_FAKE_LAUNCH) failed.\n" );
902                 return;
903         }
904
905         utilx_set_fake_launch_img(dpy, win, fake_image_file);
906
907         XSync(dpy, 0 );
908
909         // send fake client message
910         xev.xclient.type = ClientMessage;
911         xev.xclient.display = dpy;
912         xev.xclient.window = win;
913         xev.xclient.message_type =  _atom_comp_fake_launch;
914         xev.xclient.format = 32;
915         xev.xclient.data.l[0] = 1;  // 1 : start effect , 0 : end effect
916         xev.xclient.data.l[1] = 0;
917         xev.xclient.data.l[2] = 0;
918         xev.xclient.data.l[3] = 0;
919         xev.xclient.data.l[4] = 0;
920
921         XSendEvent( dpy, win, False,
922                                 SubstructureRedirectMask | SubstructureNotifyMask,
923                                 &xev );
924         XSync(dpy, 0 );
925
926 }
927
928
929 API void utilx_hide_fake_effect( Display *dpy, Window win)
930 {
931         XEvent xev;
932
933         _atom_comp_fake_launch = XInternAtom( dpy, "_E_COMP_FAKE_LAUNCH", False );
934         if(  !_atom_comp_fake_launch )
935         {
936                 fprintf( stderr, "XInternAtom(_E_COMP_FAKE_LAUNCH) failed.\n" );
937                 return;
938         }
939
940         // send fake client message
941         xev.xclient.type = ClientMessage;
942         xev.xclient.display = dpy;
943         xev.xclient.window = win;
944         xev.xclient.message_type =  _atom_comp_fake_launch;
945         xev.xclient.format = 32;
946         xev.xclient.data.l[0] = 0;  // 1 : start effect , 0 : end effect
947         xev.xclient.data.l[1] = 0;
948         xev.xclient.data.l[2] = 0;
949         xev.xclient.data.l[3] = 0;
950         xev.xclient.data.l[4] = 0;
951
952         XSendEvent( dpy, win, False,
953                                 SubstructureRedirectMask | SubstructureNotifyMask,
954                                 &xev );
955         XSync(dpy, 0 );
956 }
957
958 static void _utilx_effect_atom_check( Display* dpy )
959 {
960         if ( dpy == NULL )
961         {
962                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
963                 return;
964         }
965
966         if( !_atom_comp_window_effect_type)
967                 _atom_comp_window_effect_type =  XInternAtom(dpy, "_NET_CM_WINDOW_EFFECT_TYPE",False);
968         if( !_atom_comp_effect_default )
969                 _atom_comp_effect_default = XInternAtom(dpy, "_NET_CM_EFFECT_DEFAULT",False);
970         if( !_atom_comp_effect_none )
971                 _atom_comp_effect_none = XInternAtom(dpy, "_NET_CM_EFFECT_NONE",False);
972         if( !_atom_comp_effect_custom0 )
973                 _atom_comp_effect_custom0 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM0",False);
974         if( !_atom_comp_effect_custom1 )
975                 _atom_comp_effect_custom1 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM1",False);
976         if( !_atom_comp_effect_custom2 )
977                 _atom_comp_effect_custom2 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM2",False);
978         if( !_atom_comp_effect_custom3 )
979                 _atom_comp_effect_custom3 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM3",False);
980         if( !_atom_comp_effect_custom4 )
981                 _atom_comp_effect_custom4 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM4",False);
982         if( !_atom_comp_effect_custom5 )
983                 _atom_comp_effect_custom5 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM5",False);
984         if( !_atom_comp_effect_custom6 )
985                 _atom_comp_effect_custom6 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM6",False);
986         if( !_atom_comp_effect_custom7 )
987                 _atom_comp_effect_custom7 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM7",False);
988         if( !_atom_comp_effect_custom8 )
989                 _atom_comp_effect_custom8 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM8",False);
990         if( !_atom_comp_effect_custom9 )
991                 _atom_comp_effect_custom9 = XInternAtom(dpy, "_NET_CM_EFFECT_CUSTOM9",False);
992 }
993
994 static Atom _utilx_convert_style_to_atom( Display* dpy, Utilx_Effect_Style style )
995 {
996         if ( dpy == NULL )
997         {
998                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
999                 return _atom_comp_effect_none;
1000         }
1001         _utilx_effect_atom_check(dpy);
1002
1003         if ( style == UTILX_EFFECT_STYLE_DEFAULT )       return _atom_comp_effect_default;
1004         else if ( style == UTILX_EFFECT_STYLE_NONE )     return _atom_comp_effect_none;
1005         else if ( style == UTILX_EFFECT_STYLE_CUSTOM0 )  return _atom_comp_effect_custom0;
1006         else if ( style == UTILX_EFFECT_STYLE_CUSTOM1 )  return _atom_comp_effect_custom1;
1007         else if ( style == UTILX_EFFECT_STYLE_CUSTOM2 )  return _atom_comp_effect_custom2;
1008         else if ( style == UTILX_EFFECT_STYLE_CUSTOM3 )  return _atom_comp_effect_custom3;
1009         else if ( style == UTILX_EFFECT_STYLE_CUSTOM4 )  return _atom_comp_effect_custom4;
1010         else if ( style == UTILX_EFFECT_STYLE_CUSTOM5 )  return _atom_comp_effect_custom5;
1011         else if ( style == UTILX_EFFECT_STYLE_CUSTOM6 )  return _atom_comp_effect_custom6;
1012         else if ( style == UTILX_EFFECT_STYLE_CUSTOM7 )  return _atom_comp_effect_custom7;
1013         else if ( style == UTILX_EFFECT_STYLE_CUSTOM8 )  return _atom_comp_effect_custom8;
1014         else if ( style == UTILX_EFFECT_STYLE_CUSTOM9 )  return _atom_comp_effect_custom9;
1015         else                                             return _atom_comp_effect_none;
1016
1017 }
1018
1019 static Utilx_Effect_Style _utilx_convert_atom_to_style( Display* dpy, Atom style )
1020 {
1021         if ( dpy == NULL )
1022         {
1023                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1024                 return UTILX_EFFECT_STYLE_NONE;
1025         }
1026         _utilx_effect_atom_check(dpy);
1027
1028         if ( style == _atom_comp_effect_default )       return UTILX_EFFECT_STYLE_DEFAULT;
1029         else if ( style == _atom_comp_effect_none )     return UTILX_EFFECT_STYLE_NONE;
1030         else if ( style == _atom_comp_effect_custom0 )  return UTILX_EFFECT_STYLE_CUSTOM0;
1031         else if ( style == _atom_comp_effect_custom1 )  return UTILX_EFFECT_STYLE_CUSTOM1;
1032         else if ( style == _atom_comp_effect_custom2 )  return UTILX_EFFECT_STYLE_CUSTOM2;
1033         else if ( style == _atom_comp_effect_custom3 )  return UTILX_EFFECT_STYLE_CUSTOM3;
1034         else if ( style == _atom_comp_effect_custom4 )  return UTILX_EFFECT_STYLE_CUSTOM4;
1035         else if ( style == _atom_comp_effect_custom5 )  return UTILX_EFFECT_STYLE_CUSTOM5;
1036         else if ( style == _atom_comp_effect_custom6 )  return UTILX_EFFECT_STYLE_CUSTOM6;
1037         else if ( style == _atom_comp_effect_custom7 )  return UTILX_EFFECT_STYLE_CUSTOM7;
1038         else if ( style == _atom_comp_effect_custom8 )  return UTILX_EFFECT_STYLE_CUSTOM8;
1039         else if ( style == _atom_comp_effect_custom9 )  return UTILX_EFFECT_STYLE_CUSTOM9;
1040         else                                            return UTILX_EFFECT_STYLE_DEFAULT;
1041 }
1042
1043 API void utilx_set_window_effect_style(Display* dpy, Window win, Utilx_Effect_Type type, Utilx_Effect_Style style)
1044 {
1045         Atom *window_effect_type_list = NULL;
1046         if ( dpy == NULL )
1047         {
1048                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1049                 return;
1050         }
1051         _utilx_effect_atom_check(dpy);
1052
1053         window_effect_type_list = (Atom *)malloc(sizeof(Atom) * 6);
1054
1055         if ( !window_effect_type_list )
1056         {
1057                 fprintf (stderr, "[UTILX] Error.. malloc().. %s (%d)\n", __func__, __LINE__);
1058                 return;
1059         }
1060
1061         window_effect_type_list[0] = _atom_comp_effect_default;
1062         window_effect_type_list[1] = _atom_comp_effect_default;
1063         window_effect_type_list[2] = _atom_comp_effect_default;
1064         window_effect_type_list[3] = _atom_comp_effect_default;
1065         window_effect_type_list[4] = _atom_comp_effect_default;
1066         window_effect_type_list[5] = _atom_comp_effect_default;
1067
1068         _utilx_get_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6);
1069
1070         if ( type == UTILX_EFFECT_TYPE_MAP )             window_effect_type_list[0] = _utilx_convert_style_to_atom(dpy, style);
1071         else if ( type == UTILX_EFFECT_TYPE_UNMAP )      window_effect_type_list[1] = _utilx_convert_style_to_atom(dpy, style);
1072         else if ( type == UTILX_EFFECT_TYPE_RAISEABOVE ) window_effect_type_list[2] = _utilx_convert_style_to_atom(dpy, style);
1073         else if ( type == UTILX_EFFECT_TYPE_ROTATION )   window_effect_type_list[3] = _utilx_convert_style_to_atom(dpy, style);
1074         else if ( type == UTILX_EFFECT_TYPE_FOCUSIN )    window_effect_type_list[4] = _utilx_convert_style_to_atom(dpy, style);
1075         else if ( type == UTILX_EFFECT_TYPE_FOCUSOUT )   window_effect_type_list[5] = _utilx_convert_style_to_atom(dpy, style);
1076
1077         _utilx_set_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6);
1078
1079         XSync(dpy, 0 );
1080         free(window_effect_type_list);
1081 }
1082
1083 API Utilx_Effect_Style utilx_get_window_effect_style(Display* dpy, Window win, Utilx_Effect_Type type)
1084 {
1085         Atom *window_effect_type_list = NULL;
1086         Utilx_Effect_Style style = UTILX_EFFECT_STYLE_DEFAULT;
1087
1088         if ( dpy == NULL )
1089         {
1090                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1091                 return UTILX_EFFECT_STYLE_NONE;
1092         }
1093         _utilx_effect_atom_check(dpy);
1094
1095         window_effect_type_list = (Atom *)malloc(sizeof(Atom) * 6);
1096
1097         if ( !window_effect_type_list )
1098         {
1099                 fprintf (stderr, "[UTILX] Error.. malloc().. %s (%d)\n", __func__, __LINE__);
1100                 return UTILX_EFFECT_STYLE_NONE;
1101         }
1102
1103         if ( _utilx_get_window_property(dpy, win, _atom_comp_window_effect_type, XA_ATOM, (unsigned int *)window_effect_type_list, 6) != 6 )
1104         {
1105                 fprintf (stderr, "[UTILX] Error.. get property failed!.. %s (%d)\n", __func__, __LINE__);
1106                 free(window_effect_type_list);
1107                 return UTILX_EFFECT_STYLE_NONE;
1108         }
1109
1110         if ( type == UTILX_EFFECT_TYPE_MAP )             style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[0]);
1111         else if ( type == UTILX_EFFECT_TYPE_UNMAP )      style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[1]);
1112         else if ( type == UTILX_EFFECT_TYPE_RAISEABOVE ) style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[2]);
1113         else if ( type == UTILX_EFFECT_TYPE_ROTATION )   style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[3]);
1114         else if ( type == UTILX_EFFECT_TYPE_FOCUSIN )    style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[4]);
1115         else if ( type == UTILX_EFFECT_TYPE_FOCUSOUT )   style = _utilx_convert_atom_to_style(dpy, window_effect_type_list[5]);
1116
1117         XSync(dpy, 0 );
1118         free(window_effect_type_list);
1119         return style;
1120 }
1121
1122 API int utilx_set_window_opaque_state (Display* dpy, Window win, Utilx_Opaque_State state)
1123 {
1124         UTILX_TRACE ("[UTILX] utilx_set_window_opaque_state... win = %x, show_state = %d\n", win, state);
1125
1126         unsigned int is_opaque;
1127
1128         if (dpy == NULL)
1129         {
1130                 fprintf (stderr, "[UTILX] Error.. Invald Display.. %s (%d)\n", __func__, __LINE__);
1131                 return 0;
1132         }
1133
1134         switch (state)
1135         {
1136                 case UTILX_OPAQUE_STATE_OFF:
1137                         is_opaque = 0;
1138                         break;
1139
1140                 case UTILX_OPAQUE_STATE_ON:
1141                         is_opaque = 1;
1142                         break;
1143
1144                 default:
1145                         fprintf (stderr, "[UTILX] Error.. Invald State.. %s (%d)\n", __func__, __LINE__);
1146                         return 0;
1147         }
1148
1149         if (!_atom_window_opaque)
1150         {
1151                 _atom_window_opaque = XInternAtom (dpy, "_E_ILLUME_WINDOW_REGION_OPAQUE", False);
1152                 if (!_atom_window_opaque)
1153                 {
1154                         fprintf (stderr, "[UTILX] Error.. Cannot create _E_ILLUME_WINDOW_REGION_OPAQUE atom.. %s (%d)\n", __func__, __LINE__);
1155                         return 0;
1156                 }
1157         }
1158
1159         _utilx_set_window_property (dpy, win, _atom_window_opaque, XA_CARDINAL,
1160                         (unsigned int *)&is_opaque, 1);
1161
1162         return 1;
1163 }
1164
1165 static void
1166 _utilx_screen_capture_atom_ensure (Display* dpy)
1167 {
1168         if (_atom_screen_capture_disable)
1169                 return;
1170
1171         _atom_screen_capture_disable = XInternAtom (dpy, "_CB_SCREEN_CAPTURE_DISABLE", False);
1172         if (_atom_screen_capture_disable)
1173                 return;
1174
1175         fprintf (stderr, "[UTILX] Error.. Cannot create _CB_SCREEN_CAPTURE_DISABLE atom.. %s (%d)\n", __func__, __LINE__);
1176 }
1177
1178 API int
1179 utilx_set_screen_capture(Display* dpy, int enable)
1180 {
1181         Window root;
1182         int disable;
1183
1184         if (!dpy)
1185         {
1186                 fprintf (stderr, "[UTILX] Error.. dpy is NULL %s (%d)\n", __func__, __LINE__);
1187                 return 0;
1188         }
1189
1190         root = RootWindow (dpy, DefaultScreen(dpy));
1191         disable = (enable) ? 0 : 1;
1192
1193         _utilx_screen_capture_atom_ensure (dpy);
1194
1195         _utilx_set_window_property (dpy, root, _atom_screen_capture_disable, XA_CARDINAL, (unsigned int *)&disable, 1);
1196
1197         return 1;
1198 }
1199
1200 API int
1201 utilx_get_screen_capture(Display* dpy)
1202 {
1203         Window root;
1204         int disable = 0;
1205
1206         if (!dpy)
1207         {
1208                 fprintf (stderr, "[UTILX] Error.. dpy is NULL %s (%d)\n", __func__, __LINE__);
1209                 return 0;
1210         }
1211
1212         root = RootWindow (dpy, DefaultScreen(dpy));
1213
1214         _utilx_screen_capture_atom_ensure (dpy);
1215
1216         _utilx_get_window_property(dpy, root, _atom_screen_capture_disable, XA_CARDINAL,
1217                                     (unsigned int *)&disable, 1);
1218
1219         return (disable) ? 0 : 1;
1220 }
1221
1222 API void utilx_set_window_cardinal_property(Display* dpy, Window win, Atom atom, unsigned int *value)
1223 {
1224         _utilx_set_window_property(dpy, win, atom, XA_CARDINAL, value, 1);
1225 }
1226
1227 API int utilx_get_window_cardinal_property (Display* dpy, Window win, Atom atom, unsigned int *value)
1228 {
1229         return _utilx_get_window_property(dpy, win, atom, XA_CARDINAL, value, 1);
1230 }
1231
1232 API void utilx_show_capture_effect( Display *dpy, Window win)
1233 {
1234     XEvent xev;
1235
1236     _atom_comp_capture_effect = XInternAtom( dpy, "_E_COMP_CAPTURE_EFFECT", False );
1237     if(  !_atom_comp_capture_effect )
1238     {
1239         fprintf( stderr, "XInternAtom(_E_COMP_CAPTURE_EFFECT) failed.\n" );
1240         return;
1241     }
1242
1243     // send capture effect client message
1244     xev.xclient.type = ClientMessage;
1245     xev.xclient.display = dpy;
1246     xev.xclient.window = win;
1247     xev.xclient.message_type =  _atom_comp_capture_effect;
1248     xev.xclient.format = 32;
1249     xev.xclient.data.l[0] = 0;
1250     xev.xclient.data.l[1] = 0;
1251     xev.xclient.data.l[2] = 0;
1252     xev.xclient.data.l[3] = 0;
1253     xev.xclient.data.l[4] = 0;
1254
1255     XSendEvent( dpy, win, False,
1256                 SubstructureRedirectMask | SubstructureNotifyMask,
1257                 &xev );
1258     XSync(dpy, 0 );
1259 }
1260
1261 API UtilxScrnConf *utilx_scrnconf_allocate (void)
1262 {
1263     UtilxScrnConf *scrnconf = calloc (1, sizeof(UtilxScrnConf));
1264     if (!scrnconf)
1265     {
1266         fprintf (stderr, "fail to allocate UtilxScrnConf\n");
1267         return NULL;
1268     }
1269
1270     return scrnconf;
1271 }
1272
1273 API void utilx_scrnconf_free (UtilxScrnConf *scrnconf)
1274 {
1275     if (!scrnconf)
1276         return;
1277
1278     if (scrnconf->str_output)
1279         free (scrnconf->str_output);
1280
1281     if (scrnconf->str_resolution)
1282         free (scrnconf->str_resolution);
1283
1284     free(scrnconf);
1285     scrnconf = NULL;
1286 }
1287
1288 API void utilx_scrnconf_get_info (Display *dpy, UtilxScrnConf *scrnconf)
1289 {
1290     Window win = DefaultRootWindow(dpy);
1291         Atom scrnconf_atom = None;
1292     XTextProperty xtp;
1293     char *str = NULL;
1294     char *ptr = NULL;
1295     int items;
1296     char **list = NULL;
1297     int i = 0;
1298     int s;
1299
1300     scrnconf_atom = XInternAtom (dpy, "_SCRNCONF_INFO", False);
1301
1302     /* get property */
1303     if (XGetTextProperty (dpy, win, &xtp, scrnconf_atom))
1304     {
1305         s = XmbTextPropertyToTextList (dpy, &xtp, &list, &items);
1306         if ((s == XLocaleNotSupported) ||
1307             (s == XNoMemory) || (s == XConverterNotFound))
1308           str = strdup((char *)xtp.value);
1309         else if ((s >= Success) && (items > 0))
1310           str = strdup(list[0]);
1311
1312         if (list)
1313             XFreeStringList (list);
1314
1315         XFree(xtp.value);
1316     }
1317
1318     ptr = strtok (str, ",");
1319     while (ptr != NULL)
1320     {
1321         if (i == 0)
1322         {
1323             scrnconf->str_output = calloc (1, strlen(ptr));
1324             if (!scrnconf->str_output)
1325                 goto fail;
1326
1327             strcpy (scrnconf->str_output, ptr);
1328         }
1329         else if (i == 1)
1330         {
1331             if (!strcmp(ptr, "CONNECT"))
1332                 scrnconf->status = UTILX_SCRNCONF_STATUS_CONNECT;
1333             else if (!strcmp(ptr, "ACTIVE"))
1334                 scrnconf->status = UTILX_SCRNCONF_STATUS_ACTIVE;
1335             else
1336                 scrnconf->status = UTILX_SCRNCONF_STATUS_NULL;
1337         }
1338         else if (i == 2)
1339         {
1340             scrnconf->str_resolution = calloc (1, strlen(ptr));
1341             if (!scrnconf->str_resolution)
1342                 goto fail;
1343
1344             strcpy (scrnconf->str_resolution, ptr);
1345         }
1346         else if (i == 3)
1347         {
1348             if (!strcmp(ptr, "CLONE"))
1349                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_CLONE;
1350             else if (!strcmp(ptr, "EXTENDED"))
1351                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_EXTENDED;
1352             else
1353                 scrnconf->dispmode = UTILX_SCRNCONF_DISPMODE_NULL;
1354         }
1355         else
1356            break;
1357
1358         ptr = strtok (NULL, ",");
1359         i++;
1360     }
1361
1362     free (str);
1363
1364     return;
1365 fail:
1366     if (str)
1367         free (str);
1368
1369     if (scrnconf->str_output)
1370         free (scrnconf->str_output);
1371     if (scrnconf->str_resolution)
1372         free (scrnconf->str_resolution);
1373     if (scrnconf)
1374     {
1375         free (scrnconf);
1376         scrnconf = NULL;
1377     }
1378     return;
1379 }
1380
1381 API int utilx_scrnconf_set_dispmode (Display *dpy, Utilx_Scrnconf_Dispmode dispmode)
1382 {
1383     Window win = DefaultRootWindow(dpy);
1384         XEvent xev;
1385         Atom scrnconf_atom = None;
1386     UtilxScrnConf *scrnconf = NULL;
1387
1388     scrnconf = utilx_scrnconf_allocate ();
1389     if (!scrnconf)
1390         return 0;
1391
1392     utilx_scrnconf_get_info (dpy, scrnconf);
1393
1394     if (scrnconf->status  == UTILX_SCRNCONF_STATUS_NULL)
1395     {
1396         fprintf (stderr, "[utilx_scrnconf]: the status of screen configuration is null\n");
1397         return 0;
1398     }
1399
1400     if (scrnconf->dispmode == dispmode)
1401     {
1402         fprintf (stderr, "[utilx_scrnconf]: dispmode (%d) already set\n", dispmode);
1403         return 0;
1404     }
1405
1406     utilx_scrnconf_free (scrnconf);
1407
1408     scrnconf_atom = XInternAtom (dpy, "_SCRNCONF_DISPMODE_SET", False);
1409
1410         xev.xclient.window = win;
1411         xev.xclient.type = ClientMessage;
1412         xev.xclient.message_type = scrnconf_atom;
1413         xev.xclient.format = 32;
1414         xev.xclient.data.s[0] = dispmode;
1415
1416         XSendEvent(dpy, win, False, StructureNotifyMask, &xev);
1417         XSync(dpy, False);
1418
1419     return 1;
1420 }
1421
1422 typedef struct _ShotInfo
1423 {
1424     Display *dpy;
1425
1426     int      port;
1427     unsigned int width;
1428     unsigned int height;
1429     Pixmap   pixmap;
1430     GC       gc;
1431
1432     int      drm_fd;
1433     drm_slp_bufmgr bufmgr;
1434     void    *virtual;
1435
1436     DRI2Buffer* dri2_buffers;
1437     drm_slp_bo bo;
1438
1439     Damage   damage;
1440     int      damage_base;
1441 } ShotInfo;
1442
1443 #define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
1444
1445 #define FOURCC_RGB32    FOURCC('R','G','B','4')
1446
1447 static ShotInfo *shot_info;
1448
1449 static int
1450 _get_port (Display *dpy, unsigned int id)
1451 {
1452     unsigned int ver, rev, req_base, evt_base, err_base;
1453     unsigned int adaptors;
1454     XvAdaptorInfo *ai = NULL;
1455     XvImageFormatValues *fo = NULL;
1456     int formats;
1457     int i, j, p;
1458
1459     if (XvQueryExtension (dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
1460         return -1;
1461
1462     if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &adaptors, &ai) != Success)
1463         return -1;
1464
1465     if (!ai)
1466         return -1;
1467
1468     for (i = 0; i < adaptors; i++)
1469     {
1470         int support_format = False;
1471
1472         if (!(ai[i].type & XvStillMask))
1473             continue;
1474
1475         p = ai[i].base_id;
1476
1477         fo = XvListImageFormats (dpy, p, &formats);
1478         for (j = 0; j < formats; j++)
1479             if (fo[j].id == (int)id)
1480                 support_format = True;
1481
1482         if (fo)
1483             XFree (fo);
1484
1485         if (!support_format)
1486             continue;
1487
1488         if (XvGrabPort (dpy, p, 0) == Success)
1489         {
1490             XvFreeAdaptorInfo (ai);
1491             return p;
1492         }
1493
1494         fprintf (stderr, "[UTILX] fail : grab port. \n");
1495     }
1496
1497     XvFreeAdaptorInfo (ai);
1498
1499     return -1;
1500 }
1501
1502 static void
1503 _deinit_screen_shot (ShotInfo *info)
1504 {
1505     Atom atom_stream_off;
1506
1507     if (!info)
1508         return;
1509
1510     atom_stream_off = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);    
1511     if (atom_stream_off > 0)
1512         XvSetPortAttribute (info->dpy, info->port, atom_stream_off, 1);
1513
1514     if (info->dri2_buffers)
1515         free(info->dri2_buffers);
1516     if (info->bo)
1517         drm_slp_bo_unref(info->bo);
1518     if (info->bufmgr)
1519         drm_slp_bufmgr_destroy (info->bufmgr);
1520     if (info->gc)
1521         XFreeGC (info->dpy, info->gc);
1522     if (info->pixmap > 0)
1523         XFreePixmap (info->dpy, info->pixmap);
1524     if (info->port > 0)
1525         XvUngrabPort (info->dpy, info->port, 0);
1526     if (info->dpy)
1527         XCloseDisplay (info->dpy);
1528
1529     free (info);
1530     shot_info = NULL;
1531 }
1532
1533 static ShotInfo*
1534 _init_screen_shot (Display* dpy, unsigned int width, unsigned int height)
1535 {
1536     ShotInfo *info = NULL;
1537     int screen;
1538     int dri2_base = 0;
1539     int dri2_err_base = 0;
1540     int damage_err_base = 0;
1541     int dri2Major, dri2Minor;
1542     char *driverName = NULL, *deviceName = NULL;
1543     Atom atom_capture;
1544     unsigned int attachments[1];
1545     int dri2_count, dri2_out_count;
1546     int dri2_width, dri2_height, dri2_stride;
1547     drm_magic_t magic;
1548
1549     if (shot_info)
1550     {
1551         if (shot_info->width == width && shot_info->height == height)
1552             return shot_info;
1553
1554         _deinit_screen_shot (shot_info);
1555     }
1556
1557     info = calloc (1, sizeof (ShotInfo));
1558     if (!info)
1559         goto fail_init;
1560
1561     shot_info = info;
1562
1563     /* dpy */
1564 #if 0
1565     info->dpy = XOpenDisplay (NULL);
1566 #else
1567     info->dpy = dpy;
1568 #endif
1569
1570     /* port */
1571     info->port = _get_port (info->dpy, FOURCC_RGB32);
1572     if (info->port <= 0)
1573         goto fail_init;
1574
1575     /* width, height */
1576     atom_capture = XInternAtom (info->dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1577     XvSetPortAttribute (info->dpy, info->port, atom_capture, 1);
1578     XvQueryBestSize (info->dpy, info->port, 0, 0, 0, width, height, &width, &height);
1579     if (width <= 0 || height <= 0)
1580         goto fail_init;
1581     info->width = width;
1582     info->height = height;
1583
1584     /* pixmap */
1585     info->pixmap = XCreatePixmap (info->dpy,
1586                                   DefaultRootWindow (info->dpy),
1587                                   width, height,
1588                                   DefaultDepth (info->dpy, DefaultScreen (info->dpy)));
1589     if (info->pixmap <= 0)
1590         goto fail_init;
1591
1592     /* gc */
1593     info->gc = XCreateGC (info->dpy, info->pixmap, 0, 0);
1594     if (info->gc <= 0)
1595         goto fail_init;
1596
1597     XSetForeground (info->dpy, info->gc, 0xFF000000);
1598     XFillRectangle (info->dpy, info->pixmap, info->gc, 0, 0, width, height);
1599
1600     screen = DefaultScreen(info->dpy);
1601     if (!DRI2QueryExtension (info->dpy, &dri2_base, &dri2_err_base))
1602     {
1603         fprintf (stderr, "[UTILX] fail : DRI2QueryExtension !!\n");
1604         goto fail_init;
1605     }
1606
1607     if (!DRI2QueryVersion (info->dpy, &dri2Major, &dri2Minor))
1608     {
1609         fprintf (stderr, "[UTILX] fail : DRI2QueryVersion !!\n");
1610         goto fail_init;
1611     }
1612
1613     if (!DRI2Connect (info->dpy, RootWindow(info->dpy, screen), &driverName, &deviceName))
1614     {
1615         fprintf (stderr, "[UTILX] fail : DRI2Connect !!\n");
1616         goto fail_init;
1617     }
1618
1619     /* drm_fd */
1620     info->drm_fd = open (deviceName, O_RDWR);
1621     if (info->drm_fd < 0)
1622     {
1623         fprintf (stderr, "[UTILX] fail : open drm device (%s)\n", deviceName);
1624         goto fail_init;
1625     }
1626
1627     /* get the drm magic */
1628     drmGetMagic(info->drm_fd, &magic);
1629     if (!DRI2Authenticate(info->dpy, RootWindow(info->dpy, screen), magic))
1630     {
1631         fprintf (stderr, "[UTILX] fail : DRI2Authenticate (%d)\n", magic);
1632         goto fail_init;
1633     }
1634
1635     /* bufmgr */
1636     info->bufmgr = drm_slp_bufmgr_init (info->drm_fd, NULL);
1637     if (!info->bufmgr)
1638     {
1639         fprintf (stderr, "[UTILX] fail : init buffer manager \n");
1640         goto fail_init;
1641     }
1642
1643     DRI2CreateDrawable (info->dpy, info->pixmap);
1644
1645     attachments[0] = DRI2BufferFrontLeft;
1646     dri2_count = 1;
1647     info->dri2_buffers = DRI2GetBuffers (info->dpy, info->pixmap, &dri2_width, &dri2_height,
1648                                          attachments, dri2_count, &dri2_out_count);
1649
1650     if (!info->dri2_buffers)
1651     {
1652         fprintf (stderr, "[UTILX] fail : get buffers\n");
1653         goto fail_init;
1654     }
1655
1656     if (!info->dri2_buffers[0].name)
1657     {
1658         fprintf (stderr, "[UTILX] fail : a handle of the dri2 buffer is null \n ");
1659         goto fail_init;
1660     }
1661
1662     info->bo = drm_slp_bo_import (info->bufmgr, info->dri2_buffers[0].name);
1663     if (!info->bo)
1664     {
1665         fprintf (stderr, "[UTILX] fail : import bo (key:%d)\n", info->dri2_buffers[0].name);
1666         goto fail_init;
1667     }
1668
1669     dri2_stride = info->dri2_buffers[0].pitch;
1670
1671     /* virtual */
1672     info->virtual = (void*)drm_slp_bo_get_handle (info->bo, DRM_SLP_DEVICE_CPU);
1673     if (!info->virtual)
1674     {
1675         fprintf (stderr, "[UTILX] fail : map \n");
1676         goto fail_init;
1677     }
1678
1679     if (!XDamageQueryExtension(info->dpy, &info->damage_base, &damage_err_base))
1680         goto fail_init;
1681
1682     info->damage = XDamageCreate (info->dpy, info->pixmap, XDamageReportNonEmpty);
1683     if (info->damage <= 0)
1684     {
1685         fprintf (stderr, "[UTILX] fail : create damage \n");
1686         goto fail_init;
1687     }
1688
1689     XFlush (info->dpy);
1690
1691     return info;
1692
1693 fail_init:
1694     _deinit_screen_shot (info);
1695     return NULL;
1696 }
1697
1698 API void*
1699 utilx_create_screen_shot (Display* dpy, int width, int height)
1700 {
1701     ShotInfo *info;
1702     XEvent ev;
1703
1704     if (dpy <= 0)
1705     {
1706         fprintf (stderr, "[UTILX] invalid display(%p) \n", dpy);
1707         return NULL;
1708     }
1709
1710     if (width <= 0 || height <= 0)
1711     {
1712         fprintf (stderr, "[UTILX] invalid size(%dx%d) \n", width, height);
1713         return NULL;
1714     }
1715
1716     info = _init_screen_shot (dpy, width, height);
1717     if (!info)
1718     {
1719         fprintf (stderr, "[UTILX] fail : initialize screenshot. \n");
1720         return NULL;
1721     }
1722
1723     XSync (info->dpy, 0);
1724
1725     XvGetStill (info->dpy, info->port, info->pixmap, info->gc,
1726                 0, 0, info->width, info->height,
1727                 0, 0, info->width, info->height);
1728
1729     XSync (info->dpy, 0);
1730
1731     XNextEvent (info->dpy, &ev); /* wating for x event */
1732
1733     if (ev.type == (info->damage_base + XDamageNotify))
1734     {
1735         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1736         if (damage_ev->drawable == info->pixmap)
1737         {
1738             XDamageSubtract (info->dpy, info->damage, None, None );
1739             return info->virtual;
1740         }
1741
1742         XDamageSubtract (info->dpy, info->damage, None, None );
1743     }
1744
1745     utilx_release_screen_shot ();
1746
1747     return NULL;
1748 }
1749
1750 API void
1751 utilx_release_screen_shot (void)
1752 {
1753     _deinit_screen_shot (shot_info);
1754 }