[cbhm] copy&paste error in webkit
[framework/uifw/cbhm.git] / src / xhandler.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  */
17
18 #include "xhandler.h"
19 #include <X11/Xatom.h>
20 #include <X11/Xlib.h>
21
22 Ecore_X_Window get_selection_owner(AppData *ad, Ecore_X_Selection selection)
23 {
24         CALLED();
25         if (!ad) return 0;
26         Ecore_X_Atom sel = 0;
27         switch(selection)
28         {
29                 case ECORE_X_SELECTION_SECONDARY:
30                         sel = ECORE_X_ATOM_SELECTION_SECONDARY;
31                         break;
32                 case ECORE_X_SELECTION_CLIPBOARD:
33                         sel = ECORE_X_ATOM_SELECTION_CLIPBOARD;
34                         break;
35                 default:
36                         return 0;
37         }
38         return XGetSelectionOwner(ad->x_disp, sel);
39 }
40
41 Eina_Bool is_cbhm_selection_owner(AppData *ad, Ecore_X_Selection selection)
42 {
43         CALLED();
44         if (!ad) return EINA_FALSE;
45         Ecore_X_Window sel_owner = get_selection_owner(ad, selection);
46         DMSG("selection_owner: 0x%x, x_event_win: 0x%x \n", sel_owner, ad->x_event_win);
47         if (sel_owner == ad->x_event_win)
48                 return EINA_TRUE;
49         return EINA_FALSE;
50 }
51
52 Eina_Bool set_selection_owner(AppData *ad, Ecore_X_Selection selection, CNP_ITEM *item)
53 {
54         CALLED();
55         if (!ad) return EINA_FALSE;
56
57         if (!item && is_cbhm_selection_owner(ad, selection))
58                 return EINA_TRUE;
59
60         Ecore_X_Atom sel = 0;
61         Eina_Bool (*selection_func)(Ecore_X_Window win, const void *data, int size) = NULL;
62
63         switch(selection)
64         {
65                 case ECORE_X_SELECTION_SECONDARY:
66 //                      ecore_x_selection_secondary_clear();
67                         selection_func = ecore_x_selection_secondary_set;
68                         ad->clip_selected_item = item;
69                         break;
70                 case ECORE_X_SELECTION_CLIPBOARD:
71 //                      ecore_x_selection_clipboard_clear();
72                         selection_func = ecore_x_selection_clipboard_set;
73                         break;
74                 default:
75                         return EINA_FALSE;
76         }
77
78         if (selection_func(ad->x_event_win, NULL, 0))
79                 return EINA_TRUE;
80
81         DMSG("ERROR: set selection failed\n");
82         return EINA_FALSE;
83 }
84
85 static Eina_Bool selection_timer_cb(void *data)
86 {
87         CALLED();
88         AppData *ad = data;
89         XHandlerData *xd = ad->xhandler;
90
91         set_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD, NULL);
92         if (is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
93         {
94                 ecore_timer_del(xd->selection_timer);
95                 xd->selection_timer = NULL;
96                 return ECORE_CALLBACK_CANCEL;
97         }
98         return ECORE_CALLBACK_RENEW;
99 }
100
101 static Eina_Bool _xsel_clear_cb(void *data, int type, void *event)
102 {
103         CALLED();
104         if (!data || !event) return EINA_TRUE;
105         AppData *ad = data;
106         XHandlerData *xd = ad->xhandler;
107         Ecore_X_Event_Selection_Clear *ev = event;
108
109         DMSG("in %s, ev->win: 0x%x\n", __func__, ev->win);
110
111         if (is_cbhm_selection_owner(ad, ev->selection)) return EINA_TRUE;
112         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
113                 return ECORE_CALLBACK_PASS_ON;
114
115         ecore_x_selection_clipboard_request(ad->x_event_win, ECORE_X_SELECTION_TARGET_TARGETS);
116
117         if (xd->selection_timer)
118         {
119                 ecore_timer_del(xd->selection_timer);
120                 xd->selection_timer = NULL;
121         }
122         xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
123
124         return ECORE_CALLBACK_DONE;
125 }
126
127 static Eina_Bool _xsel_request_cb(void *data, int type, void *event)
128 {
129         CALLED();
130         if (!data || !event) return ECORE_CALLBACK_PASS_ON;
131         AppData *ad = data;
132         Ecore_X_Event_Selection_Request *ev = event;
133
134 #ifdef DEBUG
135         char *names[3];
136         DMSG("selection_owner: 0x%x, ev->... owner: 0x%x, req: 0x%x, selection: %s, target: %s, property: %s\n",
137                         get_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD), ev->owner, ev->requestor,
138                         names[0] = ecore_x_atom_name_get(ev->selection),
139                         names[1] = ecore_x_atom_name_get(ev->target),
140                         names[2] = ecore_x_atom_name_get(ev->property));
141         FREE(names[0]);
142         FREE(names[1]);
143         FREE(names[2]);
144 #endif
145
146         CNP_ITEM *item;
147         if (ev->selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
148                 item = item_get_last(ad);
149         else if (ev->selection == ECORE_X_ATOM_SELECTION_SECONDARY)
150                 item = ad->clip_selected_item;
151         else
152                 return ECORE_CALLBACK_PASS_ON;
153
154         if (!item)
155                 return ECORE_CALLBACK_PASS_ON;
156
157
158         Ecore_X_Atom property = None;
159         void *data_ret = NULL;
160         int size_ret;
161         Ecore_X_Atom ttype;
162         int tsize;
163
164         if (!generic_converter(ad, ev->target, item, &data_ret, &size_ret, &ttype, &tsize))
165                 /*      if (!ecore_x_selection_convert(ev->selection,
166                         ev->target,
167                         &data_ret, &len, &typeAtom, &typesize))*/
168
169         {
170                 /* Refuse selection, conversion to requested target failed */
171                 DMSG("converter return FALSE\n");
172         }
173         else if (data_ret)
174         {
175                 /* FIXME: This does not properly handle large data transfers */
176                 ecore_x_window_prop_property_set(
177                                 ev->requestor,
178                                 ev->property,
179                                 ttype,
180                                 tsize,
181                                 data_ret,
182                                 size_ret);
183                 property = ev->property;
184                 FREE(data_ret);
185                 DMSG("change property\n");
186         }
187
188         ecore_x_selection_notify_send(ev->requestor,
189                         ev->selection,
190                         ev->target,
191                         property,
192                         CurrentTime);
193         DMSG("change property notify\n");
194         ecore_x_flush();
195         return ECORE_CALLBACK_DONE;
196 }
197
198 static void send_convert_selection_target(AppData *ad, Ecore_X_Selection_Data_Targets *targets_data)
199 {
200         CALLED();
201         /*      struct _Ecore_X_Selection_Data_Targets {
202                 Ecore_X_Selection_Data data;
203                 struct _Ecore_X_Selection_Data {
204                 enum {
205                 ECORE_X_SELECTION_CONTENT_NONE,
206                 ECORE_X_SELECTION_CONTENT_TEXT,
207                 ECORE_X_SELECTION_CONTENT_FILES,
208                 ECORE_X_SELECTION_CONTENT_TARGETS,
209                 ECORE_X_SELECTION_CONTENT_CUSTOM
210                 } content;
211                 unsigned char *data;
212                 int            length;
213                 int            format;
214                 int            (*FREE)(void *data);
215                 };
216
217                 char                 **targets;
218                 int                    num_targets;
219                 };*/
220         if (!targets_data || !ad)
221                 return;
222         Ecore_X_Atom *atomlist = (Ecore_X_Atom *)targets_data->data.data;
223         if (!atomlist)
224                 return;
225
226         DMSG("targets_data->num_targets: 0x%x\n", targets_data->num_targets);
227         int i, j, k;
228         for (i = 0; i < targets_data->num_targets; i++)
229         {
230                 DMSG("get target: %s\n", targets_data->targets[i]);
231                 for (j = 0; j < ATOM_INDEX_MAX; j++)
232                 {
233                         for (k = 0; k < ad->targetAtoms[j].atom_cnt; k++)
234                         {
235                                 if (!strcmp(targets_data->targets[i], ad->targetAtoms[j].name[k]))
236                                 {
237                                         DMSG("find matched target: %s\n", ad->targetAtoms[j].name[k]);
238                                         ecore_x_selection_clipboard_request(ad->x_event_win, ad->targetAtoms[j].name[k]);
239                                         return;
240                                 }
241                         }
242                 }
243         }
244         DMSG("ERROR: get target atom failed\n");
245 }
246
247 static Eina_Bool _add_selection_imagepath(AppData* ad, char *str)
248 {
249         if (!ad || !str)
250                 return EINA_FALSE;
251         DMSG("get FILE: %s\n", str);
252         char *slash = strchr(str, '/');
253         while (slash && slash[0] == '/')
254         {
255                 if (slash[1] != '/')
256                 {
257                         char *filepath;
258                         filepath = strdup(slash);
259                         if (filepath)
260                         {
261                                 if (ecore_file_exists(filepath))
262                                 {
263                                         item_add_by_data(ad, ad->targetAtoms[ATOM_INDEX_IMAGE].atom[0], filepath, strlen(filepath) + 1);
264                                         return EINA_TRUE;
265                                 }
266                                 else
267                                         FREE(filepath);
268                         }
269                         break;
270                 }
271                 slash++;
272         }
273         DMSG("Error : it isn't normal file = %s\n", str);
274         return EINA_FALSE;
275 }
276
277 static void _get_selection_data_files(AppData* ad, Ecore_X_Selection_Data_Files *files_data)
278 {
279 /*      struct _Ecore_X_Selection_Data_Files {
280                 Ecore_X_Selection_Data data;
281                 char                 **files;
282                 int                    num_files;
283         }; */
284
285         int i;
286         for (i = 0; i < files_data->num_files; i++)
287         {
288                 _add_selection_imagepath(ad, files_data->files[i]);
289         }
290 }
291
292 static Eina_Bool _xsel_notify_cb(void *data, int type, void *event)
293 {
294         CALLED();
295         if (!data || !event)
296                 return ECORE_CALLBACK_PASS_ON;
297
298         AppData *ad = data;
299         XHandlerData *xd = ad->xhandler;
300         if (xd->selection_timer)
301         {
302                 ecore_timer_del(xd->selection_timer);
303                 xd->selection_timer = NULL;
304         }
305
306 /*      struct _Ecore_X_Event_Selection_Notify
307         {
308                 Ecore_X_Window    win;
309                 Ecore_X_Time      time;
310                 Ecore_X_Selection selection;
311                 Ecore_X_Atom      atom;
312                 char             *target;
313                 void             *data;
314         };*/
315         Ecore_X_Event_Selection_Notify *ev = event;
316
317         switch (ev->selection)
318         {
319                 case ECORE_X_SELECTION_CLIPBOARD:
320                         break;
321                 case ECORE_X_SELECTION_SECONDARY:
322                 case ECORE_X_SELECTION_PRIMARY:
323                 case ECORE_X_SELECTION_XDND:
324                 default:
325                         return ECORE_CALLBACK_PASS_ON;
326         }
327         if (!ev->data)
328                 goto set_clipboard_selection_owner;
329
330 /*      struct _Ecore_X_Selection_Data {
331                 enum {
332                         ECORE_X_SELECTION_CONTENT_NONE,
333                         ECORE_X_SELECTION_CONTENT_TEXT,
334                         ECORE_X_SELECTION_CONTENT_FILES,
335                         ECORE_X_SELECTION_CONTENT_TARGETS,
336                         ECORE_X_SELECTION_CONTENT_CUSTOM
337                 } content;
338                 unsigned char *data;
339                 int            length;
340                 int            format;
341                 int            (*FREE)(void *data);
342         };*/
343         Ecore_X_Selection_Data *sel_data = ev->data;
344         switch (sel_data->content)
345         {
346                 case ECORE_X_SELECTION_CONTENT_NONE:
347                         DMSG("ECORE_X_SELECTION_CONTENT_NONE\n");
348                         break;
349                 case ECORE_X_SELECTION_CONTENT_TEXT:
350                         DMSG("ECORE_X_SELECTION_CONTENT_TEXT\n");
351                 /*      struct _Ecore_X_Selection_Data_Text {
352                                 Ecore_X_Selection_Data data;
353                                 char                  *text;
354                         };
355                         Ecore_X_Selection_Data_Text *text_data = ev->data;*/
356                 //      DMSG("sel_data->data: 0x%x, text_data->text: 0x%x\n", sel_data->data, text_data->text);
357                         break;
358                 case ECORE_X_SELECTION_CONTENT_FILES:
359                         DMSG("ECORE_X_SELECTION_CONTENT_FILES\n");
360                         _get_selection_data_files(ad, ev->data);
361                         goto set_clipboard_selection_owner;
362                         break;
363                 case ECORE_X_SELECTION_CONTENT_TARGETS:
364                         DMSG("ECORE_X_SELECTION_CONTENT_TARGETS\n");
365                         send_convert_selection_target(ad, ev->data);
366                         goto set_clipboard_selection_owner;
367                         break;
368                 case ECORE_X_SELECTION_CONTENT_CUSTOM:
369                         DMSG("ECORE_X_SELECTION_CONTENT_CUSTOM\n");
370                         break;
371         }
372 #ifdef DEBUG
373         char *name;
374         DMSG("get atom: %d(%s), target: %s, length: %d, format: %d\n",
375                         ev->atom, name = ecore_x_atom_name_get(ev->atom), ev->target, sel_data->length, sel_data->format);
376         FREE(name);
377 #endif
378
379         Ecore_X_Atom targetAtom = ecore_x_atom_get(ev->target);
380         char *stripstr = strndup(sel_data->data, sel_data->length);
381         DMSG("get data: %s, len: %d\n", stripstr, strlen(stripstr));
382         if (atom_type_index_get(ad, targetAtom) == ATOM_INDEX_IMAGE)
383         {
384                 _add_selection_imagepath(ad, stripstr);
385                 FREE(stripstr);
386         }
387         else
388                 item_add_by_data(ad, targetAtom, stripstr, strlen(stripstr) + 1);
389
390 //      FREE(stripstr);
391
392 set_clipboard_selection_owner:
393         set_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD, NULL);
394         if (!is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
395                 xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
396
397         return ECORE_CALLBACK_DONE;
398 }
399
400 static Eina_Bool _xclient_msg_cb(void *data, int type, void *event)
401 {
402         CALLED();
403         AppData *ad = data;
404         XHandlerData *xd = ad->xhandler;
405
406         /*      struct _Ecore_X_Event_Client_Message {
407                 Ecore_X_Window win;
408                 Ecore_X_Atom   message_type;
409                 int            format;
410                 union
411                 {
412                         char        b[20];
413                         short       s[10];
414                         long        l[5];
415                 } data;
416                 Ecore_X_Time   time;
417         };*/
418         Ecore_X_Event_Client_Message *ev = event;
419
420         if (ev->message_type == xd->atomXKey_MSG)
421         {
422                 DTRACE("XE:ClientMessage for Screen capture\n");
423                 capture_current_screen(ad);
424                 return TRUE;
425         }
426
427         if (ev->message_type != xd->atomCBHM_MSG)
428                 return -1;
429
430         DTRACE("## %s\n", ev->data.b);
431
432 /*      Atom cbhm_atoms[ITEM_CNT_MAX];
433         char atomname[10];
434         Ecore_X_Window reqwin = ev->win;*/
435
436         if (strncmp("show", ev->data.b, 4) == 0)
437         {
438                 ad->x_active_win = ev->win;
439                 if (ev->data.b[4] == '1')
440                         clipdrawer_paste_textonly_set(ad, EINA_FALSE);
441                 else
442                         clipdrawer_paste_textonly_set(ad, EINA_TRUE);
443
444                 clipdrawer_activate_view(ad);
445         }
446         else if (!strcmp("cbhm_hide", ev->data.b))
447         {
448                 clipdrawer_lower_view(ad);
449         }
450         else if (!strcmp("get count", ev->data.b))
451         {
452                 int icount = item_count_get(ad);
453                 char countbuf[10];
454                 DMSG("## cbhm count : %d\n", icount);
455                 snprintf(countbuf, 10, "%d", icount);
456                 ecore_x_window_prop_property_set(
457                                 ev->win,
458                                 xd->atomCBHMCount,
459                                 xd->atomUTF8String,
460                                 8,
461                                 countbuf,
462                                 strlen(countbuf));
463         }
464         /* for OSP */
465         else if (strncmp("GET_ITEM", ev->data.b, 8) == 0)
466         {
467                 int itempos = 0;
468                 int index = 8;
469                 xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
470
471                 while ('0' <= ev->data.b[index] && ev->data.b[index] <= '9')
472                 {
473                         itempos = (itempos * 10) + (ev->data.b[index] - '0');
474                         index++;
475                 }
476
477                 CNP_ITEM *item = item_get_by_index(ad, itempos);
478                 if (!item)
479                 {
480                         Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
481
482                         char error_buf[] = "OUT OF BOUND";
483                         int bufsize = sizeof(error_buf);
484                         ecore_x_window_prop_property_set(
485                                         ev->win,
486                                         xd->atomCBHM_ITEM,
487                                         itemtype,
488                                         8,
489                                         error_buf,
490                                         bufsize);
491                         DMSG("GET ITEM ERROR msg: %s, index: %d, item count: %d\n",
492                                         ev->data.b, itempos, item_count_get(ad));
493                 }
494                 else
495                 {
496                         ecore_x_window_prop_property_set(
497                                         ev->win,
498                                         xd->atomCBHM_ITEM,
499                                         ad->targetAtoms[item->type_index].atom[0],
500                                         8,
501                                         item->data,
502                                         item->len);
503                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
504                                         itempos, ad->targetAtoms[item->type_index].atom[0],
505                                         item->data, item->len);
506                 }
507         }
508 /*      else if (strncmp("get #", ev->data.b, 5) == 0)
509         {
510                 // FIXME : handle greater than 9
511                 int num = ev->data.b[5] - '0';
512                 int cur = get_current_history_position();
513                 num = cur + num - 1;
514                 if (num > ITEMS_CNT_MAX-1)
515                         num = num-ITEMS_CNT_MAX;
516
517                 if (num >= 0 && num < ITEMS_CNT_MAX)
518                 {
519                         DTRACE("## pos : #%d\n", num);
520                         // FIXME : handle with correct atom
521                         sprintf(atomname, "CBHM_c%d", num);
522                         cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
523
524                         CNP_ITEM *item = clipdr;
525
526
527                         if (clipdrawer_get_item_data(ad, num) != NULL)
528                         {
529                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
530                                                                 8, PropModeReplace,
531                                                                 (unsigned char *) clipdrawer_get_item_data(ad, num),
532                                                                 (int) strlen(clipdrawer_get_item_data(ad, num)));
533                         }
534                 }
535         }
536         else if (strcmp("get all", ev->data.b) == 0)
537         {
538 //              print_history_buffer();
539                 pos = get_current_history_position();
540                 for (i = 0; i < 5; i++)
541                 {
542                         DTRACE("## %d -> %d\n", i, pos);
543                         sprintf(atomname, "CBHM_c%d", i);
544                         cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
545                         if (clipdrawer_get_item_data(ad, pos) != NULL)
546                         {
547                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
548                                                                 8, PropModeReplace,
549                                                                 (unsigned char *) clipdrawer_get_item_data(ad, pos),
550                                                                 (int) strlen(clipdrawer_get_item_data(ad, pos)));
551                         }
552                         pos--;
553                         if (pos < 0)
554                                 pos = ITEMS_CNT_MAX-1;
555                 }
556         }*/
557 /*      else if (strcmp("get raw", ev->data.b) == 0)
558         {
559
560                 if (get_storage_start_addr != NULL)
561                 {
562                         XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
563                                                         8, PropModeReplace,
564                                                         (unsigned char *) get_storage_start_addr(),
565                                                         (int) get_total_storage_size());
566                 }
567         }
568         */
569         XFlush(ad->x_disp);
570
571         return EINA_TRUE;
572 }
573
574 static Eina_Bool _xfocus_out_cb(void *data, int type, void *event)
575 {
576         CALLED();
577         AppData *ad = data;
578         DTRACE("XE:FOCUS OUT\n");
579         clipdrawer_lower_view(ad);
580         return EINA_TRUE;
581 }
582
583 static Eina_Bool _xproperty_notify_cb(void *data, int type, void *event)
584 {
585 //      CALLED();
586         AppData *ad = data;
587         XHandlerData *xd = ad->xhandler;
588         ClipdrawerData *cd = ad->clipdrawer;
589         Ecore_X_Event_Window_Property *pevent = (Ecore_X_Event_Window_Property *)event;
590
591         if (ad->x_active_win != pevent->win)
592                 return EINA_TRUE;
593
594         if (xd->atomWindowRotate == pevent->atom)
595         {
596                 int angle = get_active_window_degree(ad->x_active_win);
597                 if (angle != cd->o_degree)
598                 {
599                         cd->o_degree = angle;
600                         elm_win_rotation_set(cd->main_win, angle);
601                         set_rotation_to_clipdrawer(cd);
602                 }
603         }
604
605         return EINA_TRUE;
606 }
607
608 static Eina_Bool _xwin_destroy_cb(void *data, int type, void *event)
609 {
610         CALLED();
611         AppData *ad = data;
612         Ecore_X_Event_Window_Destroy *pevent = event;
613         if (ad->x_active_win != pevent->win)
614                 return EINA_TRUE;
615         clipdrawer_lower_view(ad);
616 }
617
618 XHandlerData *init_xhandler(AppData *ad)
619 {
620         XHandlerData *xd = CALLOC(1, sizeof(XHandlerData));
621         if (!xd)
622                 return NULL;
623         xd->xsel_clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _xsel_clear_cb, ad);
624         xd->xsel_request_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, _xsel_request_cb, ad);
625         xd->xsel_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _xsel_notify_cb, ad);
626         xd->xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _xclient_msg_cb, ad);
627         xd->xfocus_out_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _xfocus_out_cb, ad);
628         xd->xproperty_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _xproperty_notify_cb, ad);
629         xd->xwindow_destroy_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _xwin_destroy_cb, ad);
630
631         xd->atomInc = ecore_x_atom_get("INCR");
632         xd->atomWindowRotate = ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE");
633         xd->atomCBHM_MSG = ecore_x_atom_get("CBHM_MSG");
634         xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
635         xd->atomXKey_MSG = ecore_x_atom_get("_XKEY_COMPOSITION");
636         xd->atomCBHMCount = ecore_x_atom_get("CBHM_cCOUNT");
637         xd->atomUTF8String = ecore_x_atom_get("UTF8_STRING");
638         return xd;
639 }
640
641 void depose_xhandler(XHandlerData *xd)
642 {
643         ecore_event_handler_del(xd->xsel_clear_handler);
644         ecore_event_handler_del(xd->xsel_request_handler);
645         ecore_event_handler_del(xd->xsel_notify_handler);
646         ecore_event_handler_del(xd->xclient_msg_handler);
647         ecore_event_handler_del(xd->xfocus_out_handler);
648         ecore_event_handler_del(xd->xproperty_notify_handler);
649         ecore_event_handler_del(xd->xwindow_destroy_handler);
650         FREE(xd);
651 }
652
653 int get_active_window_degree(Ecore_X_Window active)
654 {
655         //ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE
656
657         int rotation = 0;
658         unsigned char *prop_data = NULL;
659         int count;
660         int ret = ecore_x_window_prop_property_get(
661                         active, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
662                         ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
663         if (ret && prop_data) memcpy(&rotation, prop_data, sizeof(int));
664         if (prop_data) FREE(prop_data);
665         return rotation;
666 }