[cbhm] License is changed to Flora License
[framework/uifw/cbhm.git] / src / xhandler.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 = NULL;
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         {
156                 DMSG("has no item\n");
157                 ecore_x_selection_notify_send(ev->requestor,
158                                 ev->selection,
159                                 None,
160                                 None,
161                                 CurrentTime);
162                 DMSG("change property notify\n");
163                 ecore_x_flush();
164                 return ECORE_CALLBACK_DONE;
165         }
166
167         Ecore_X_Atom property = None;
168         void *data_ret = NULL;
169         int size_ret;
170         Ecore_X_Atom ttype;
171         int tsize;
172
173         if (!generic_converter(ad, ev->target, item, &data_ret, &size_ret, &ttype, &tsize))
174                 /*      if (!ecore_x_selection_convert(ev->selection,
175                         ev->target,
176                         &data_ret, &len, &typeAtom, &typesize))*/
177
178         {
179                 /* Refuse selection, conversion to requested target failed */
180                 DMSG("converter return FALSE\n");
181         }
182         else if (data_ret)
183         {
184                 /* FIXME: This does not properly handle large data transfers */
185                 ecore_x_window_prop_property_set(
186                                 ev->requestor,
187                                 ev->property,
188                                 ttype,
189                                 tsize,
190                                 data_ret,
191                                 size_ret);
192                 property = ev->property;
193                 FREE(data_ret);
194                 DMSG("change property\n");
195         }
196
197         ecore_x_selection_notify_send(ev->requestor,
198                         ev->selection,
199                         ev->target,
200                         property,
201                         CurrentTime);
202         DMSG("change property notify\n");
203         ecore_x_flush();
204         return ECORE_CALLBACK_DONE;
205 }
206
207 static void send_convert_selection_target(AppData *ad, Ecore_X_Selection_Data_Targets *targets_data)
208 {
209         CALLED();
210         /*      struct _Ecore_X_Selection_Data_Targets {
211                 Ecore_X_Selection_Data data;
212                 struct _Ecore_X_Selection_Data {
213                 enum {
214                 ECORE_X_SELECTION_CONTENT_NONE,
215                 ECORE_X_SELECTION_CONTENT_TEXT,
216                 ECORE_X_SELECTION_CONTENT_FILES,
217                 ECORE_X_SELECTION_CONTENT_TARGETS,
218                 ECORE_X_SELECTION_CONTENT_CUSTOM
219                 } content;
220                 unsigned char *data;
221                 int            length;
222                 int            format;
223                 int            (*FREE)(void *data);
224                 };
225
226                 char                 **targets;
227                 int                    num_targets;
228                 };*/
229         if (!targets_data || !ad)
230                 return;
231         Ecore_X_Atom *atomlist = (Ecore_X_Atom *)targets_data->data.data;
232         if (!atomlist)
233                 return;
234
235         DMSG("targets_data->num_targets: 0x%x\n", targets_data->num_targets);
236         int i, j, k;
237         for (i = 0; i < targets_data->num_targets; i++)
238         {
239                 DMSG("get target: %s\n", targets_data->targets[i]);
240                 for (j = 0; j < ATOM_INDEX_MAX; j++)
241                 {
242                         for (k = 0; k < ad->targetAtoms[j].atom_cnt; k++)
243                         {
244                                 if (!strcmp(targets_data->targets[i], ad->targetAtoms[j].name[k]))
245                                 {
246                                         DMSG("find matched target: %s\n", ad->targetAtoms[j].name[k]);
247                                         ecore_x_selection_clipboard_request(ad->x_event_win, ad->targetAtoms[j].name[k]);
248                                         return;
249                                 }
250                         }
251                 }
252         }
253         DMSG("ERROR: get target atom failed\n");
254 }
255
256 static Eina_Bool _add_selection_imagepath(AppData* ad, char *str)
257 {
258         if (!ad || !str)
259                 return EINA_FALSE;
260         DMSG("get FILE: %s\n", str);
261         char *slash = strchr(str, '/');
262         while (slash && slash[0] == '/')
263         {
264                 if (slash[1] != '/')
265                 {
266                         char *filepath;
267                         filepath = strdup(slash);
268                         if (filepath)
269                         {
270                                 if (ecore_file_exists(filepath))
271                                 {
272                                         item_add_by_data(ad, ad->targetAtoms[ATOM_INDEX_IMAGE].atom[0], filepath, strlen(filepath) + 1);
273                                         return EINA_TRUE;
274                                 }
275                                 else
276                                         FREE(filepath);
277                         }
278                         break;
279                 }
280                 slash++;
281         }
282         DMSG("Error : it isn't normal file = %s\n", str);
283         return EINA_FALSE;
284 }
285
286 static void _get_selection_data_files(AppData* ad, Ecore_X_Selection_Data_Files *files_data)
287 {
288 /*      struct _Ecore_X_Selection_Data_Files {
289                 Ecore_X_Selection_Data data;
290                 char                 **files;
291                 int                    num_files;
292         }; */
293
294         int i;
295         for (i = 0; i < files_data->num_files; i++)
296         {
297                 _add_selection_imagepath(ad, files_data->files[i]);
298         }
299 }
300
301 static Eina_Bool _xsel_notify_cb(void *data, int type, void *event)
302 {
303         CALLED();
304         if (!data || !event)
305                 return ECORE_CALLBACK_PASS_ON;
306
307         AppData *ad = data;
308         XHandlerData *xd = ad->xhandler;
309         if (xd->selection_timer)
310         {
311                 ecore_timer_del(xd->selection_timer);
312                 xd->selection_timer = NULL;
313         }
314
315 /*      struct _Ecore_X_Event_Selection_Notify
316         {
317                 Ecore_X_Window    win;
318                 Ecore_X_Time      time;
319                 Ecore_X_Selection selection;
320                 Ecore_X_Atom      atom;
321                 char             *target;
322                 void             *data;
323         };*/
324         Ecore_X_Event_Selection_Notify *ev = event;
325
326         switch (ev->selection)
327         {
328                 case ECORE_X_SELECTION_CLIPBOARD:
329                         break;
330                 case ECORE_X_SELECTION_SECONDARY:
331                 case ECORE_X_SELECTION_PRIMARY:
332                 case ECORE_X_SELECTION_XDND:
333                 default:
334                         return ECORE_CALLBACK_PASS_ON;
335         }
336         if (!ev->data)
337                 goto set_clipboard_selection_owner;
338
339 /*      struct _Ecore_X_Selection_Data {
340                 enum {
341                         ECORE_X_SELECTION_CONTENT_NONE,
342                         ECORE_X_SELECTION_CONTENT_TEXT,
343                         ECORE_X_SELECTION_CONTENT_FILES,
344                         ECORE_X_SELECTION_CONTENT_TARGETS,
345                         ECORE_X_SELECTION_CONTENT_CUSTOM
346                 } content;
347                 unsigned char *data;
348                 int            length;
349                 int            format;
350                 int            (*FREE)(void *data);
351         };*/
352         Ecore_X_Selection_Data *sel_data = ev->data;
353         switch (sel_data->content)
354         {
355                 case ECORE_X_SELECTION_CONTENT_NONE:
356                         DMSG("ECORE_X_SELECTION_CONTENT_NONE\n");
357                         break;
358                 case ECORE_X_SELECTION_CONTENT_TEXT:
359                         DMSG("ECORE_X_SELECTION_CONTENT_TEXT\n");
360                 /*      struct _Ecore_X_Selection_Data_Text {
361                                 Ecore_X_Selection_Data data;
362                                 char                  *text;
363                         };
364                         Ecore_X_Selection_Data_Text *text_data = ev->data;*/
365                 //      DMSG("sel_data->data: 0x%x, text_data->text: 0x%x\n", sel_data->data, text_data->text);
366                         break;
367                 case ECORE_X_SELECTION_CONTENT_FILES:
368                         DMSG("ECORE_X_SELECTION_CONTENT_FILES\n");
369                         _get_selection_data_files(ad, ev->data);
370                         goto set_clipboard_selection_owner;
371                         break;
372                 case ECORE_X_SELECTION_CONTENT_TARGETS:
373                         DMSG("ECORE_X_SELECTION_CONTENT_TARGETS\n");
374                         send_convert_selection_target(ad, ev->data);
375                         if (!is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
376                                 xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
377                         return ECORE_CALLBACK_DONE;
378                 case ECORE_X_SELECTION_CONTENT_CUSTOM:
379                         DMSG("ECORE_X_SELECTION_CONTENT_CUSTOM\n");
380                         break;
381         }
382 #ifdef DEBUG
383         char *name;
384         DMSG("get atom: %d(%s), target: %s, length: %d, format: %d\n",
385                         ev->atom, name = ecore_x_atom_name_get(ev->atom), ev->target, sel_data->length, sel_data->format);
386         FREE(name);
387 #endif
388
389         Ecore_X_Atom targetAtom = ecore_x_atom_get(ev->target);
390         char *stripstr = strndup(sel_data->data, sel_data->length);
391         DMSG("get data: %s, len: %d\n", stripstr, strlen(stripstr));
392         if (atom_type_index_get(ad, targetAtom) == ATOM_INDEX_IMAGE)
393         {
394                 _add_selection_imagepath(ad, stripstr);
395                 FREE(stripstr);
396         }
397         else
398                 item_add_by_data(ad, targetAtom, stripstr, strlen(stripstr) + 1);
399
400 //      FREE(stripstr);
401
402 set_clipboard_selection_owner:
403         set_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD, NULL);
404         if (!is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
405                 xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
406
407         return ECORE_CALLBACK_DONE;
408 }
409
410 static Eina_Bool _xclient_msg_cb(void *data, int type, void *event)
411 {
412         CALLED();
413         AppData *ad = data;
414         XHandlerData *xd = ad->xhandler;
415
416         /*      struct _Ecore_X_Event_Client_Message {
417                 Ecore_X_Window win;
418                 Ecore_X_Atom   message_type;
419                 int            format;
420                 union
421                 {
422                         char        b[20];
423                         short       s[10];
424                         long        l[5];
425                 } data;
426                 Ecore_X_Time   time;
427         };*/
428         Ecore_X_Event_Client_Message *ev = event;
429
430         if (ev->message_type != xd->atomCBHM_MSG)
431                 return -1;
432
433         DTRACE("## %s\n", ev->data.b);
434
435 /*      Atom cbhm_atoms[ITEM_CNT_MAX];
436         char atomname[10];
437         Ecore_X_Window reqwin = ev->win;*/
438
439         if (strncmp("show", ev->data.b, 4) == 0)
440         {
441                 ad->x_active_win = ev->win;
442                 if (ev->data.b[4] == '1')
443                         clipdrawer_paste_textonly_set(ad, EINA_FALSE);
444                 else
445                         clipdrawer_paste_textonly_set(ad, EINA_TRUE);
446
447                 clipdrawer_activate_view(ad);
448         }
449         else if (!strcmp("cbhm_hide", ev->data.b))
450         {
451                 clipdrawer_lower_view(ad);
452         }
453         else if (!strcmp("get count", ev->data.b))
454         {
455                 int icount = item_count_get(ad);
456                 char countbuf[10];
457                 DMSG("## cbhm count : %d\n", icount);
458                 snprintf(countbuf, 10, "%d", icount);
459                 ecore_x_window_prop_property_set(
460                                 ev->win,
461                                 xd->atomCBHMCount,
462                                 xd->atomUTF8String,
463                                 8,
464                                 countbuf,
465                                 strlen(countbuf)+1);
466         }
467         /* for OSP */
468         else if (strncmp("GET_ITEM", ev->data.b, 8) == 0)
469         {
470                 int itempos = 0;
471                 int index = 8;
472                 xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
473
474                 while ('0' <= ev->data.b[index] && ev->data.b[index] <= '9')
475                 {
476                         itempos = (itempos * 10) + (ev->data.b[index] - '0');
477                         index++;
478                 }
479
480                 CNP_ITEM *item = item_get_by_index(ad, itempos);
481                 if (!item)
482                 {
483                         Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
484
485                         char error_buf[] = "OUT OF BOUND";
486                         int bufsize = sizeof(error_buf);
487                         ecore_x_window_prop_property_set(
488                                         ev->win,
489                                         xd->atomCBHM_ITEM,
490                                         itemtype,
491                                         8,
492                                         error_buf,
493                                         bufsize);
494                         DMSG("GET ITEM ERROR msg: %s, index: %d, item count: %d\n",
495                                         ev->data.b, itempos, item_count_get(ad));
496                 }
497                 else
498                 {
499                         ecore_x_window_prop_property_set(
500                                         ev->win,
501                                         xd->atomCBHM_ITEM,
502                                         ad->targetAtoms[item->type_index].atom[0],
503                                         8,
504                                         item->data,
505                                         item->len);
506                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
507                                         itempos, ad->targetAtoms[item->type_index].atom[0],
508                                         item->data, item->len);
509                 }
510         }
511         else if (strncmp("SET_ITEM", ev->data.b, 8) == 0)
512         {
513                 int ret = 0;
514                 int size_ret = 0;
515                 int num_ret = 0;
516                 long unsigned int bytes = 0;
517                 unsigned char *item_data = NULL;
518                 unsigned char *prop_ret = NULL;
519                 Ecore_X_Atom format = 0;
520                 int i;
521                 xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
522                 ret = XGetWindowProperty(ecore_x_display_get(), ad->x_event_win, xd->atomCBHM_ITEM, 0, LONG_MAX, False, ecore_x_window_prop_any_type(),
523                                 (Atom*)&format, &size_ret, &num_ret, &bytes, &prop_ret);
524                 ecore_x_sync();
525                 if (ret != Success)
526                 {
527                         DMSG("Failed Set Item\n");
528                         return EINA_FALSE;
529                 }
530                 if (!num_ret)
531                 {
532                         XFree(prop_ret);
533                         return EINA_FALSE;
534                 }
535
536                 if (!(item_data = malloc(num_ret * size_ret / 8)))
537                 {
538                         XFree(item_data);
539                         return EINA_FALSE;
540                 }
541
542                 switch (size_ret)
543                 {
544                         case 8:
545                                 for (i = 0; i < num_ret; i++)
546                                         item_data[i] = prop_ret[i];
547                                 break;
548                         case 16:
549                                 for (i = 0; i < num_ret; i++)
550                                         ((unsigned short *)item_data)[i] = ((unsigned short *)prop_ret)[i];
551                                 break;
552                         case 32:
553                                 for (i = 0; i < num_ret; i++)
554                                         ((unsigned int *)item_data)[i] = ((unsigned long *)prop_ret)[i];
555                                 break;
556                 }
557
558                 XFree(prop_ret);
559
560                 DMSG("item_data:%s format:%s(%d)\n", item_data, ecore_x_atom_name_get(format), format);
561                 item_add_by_data(ad, format, item_data, strlen(item_data) + 1);
562         }
563         else if (strncmp("DEL_ITEM", ev->data.b, 8) == 0)
564         {
565                 int itempos = 0;
566                 int index = 8;
567
568                 while ('0' <= ev->data.b[index] && ev->data.b[index] <= '9')
569                 {
570                         itempos = (itempos * 10) + (ev->data.b[index] - '0');
571                         index++;
572                 }
573
574                 item_delete_by_index(ad, itempos);
575         }
576 /*      else if (strncmp("get #", ev->data.b, 5) == 0)
577         {
578                 // FIXME : handle greater than 9
579                 int num = ev->data.b[5] - '0';
580                 int cur = get_current_history_position();
581                 num = cur + num - 1;
582                 if (num > ITEMS_CNT_MAX-1)
583                         num = num-ITEMS_CNT_MAX;
584
585                 if (num >= 0 && num < ITEMS_CNT_MAX)
586                 {
587                         DTRACE("## pos : #%d\n", num);
588                         // FIXME : handle with correct atom
589                         sprintf(atomname, "CBHM_c%d", num);
590                         cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
591
592                         CNP_ITEM *item = clipdr;
593
594
595                         if (clipdrawer_get_item_data(ad, num) != NULL)
596                         {
597                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
598                                                                 8, PropModeReplace,
599                                                                 (unsigned char *) clipdrawer_get_item_data(ad, num),
600                                                                 (int) strlen(clipdrawer_get_item_data(ad, num)));
601                         }
602                 }
603         }
604         else if (strcmp("get all", ev->data.b) == 0)
605         {
606 //              print_history_buffer();
607                 pos = get_current_history_position();
608                 for (i = 0; i < 5; i++)
609                 {
610                         DTRACE("## %d -> %d\n", i, pos);
611                         sprintf(atomname, "CBHM_c%d", i);
612                         cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
613                         if (clipdrawer_get_item_data(ad, pos) != NULL)
614                         {
615                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
616                                                                 8, PropModeReplace,
617                                                                 (unsigned char *) clipdrawer_get_item_data(ad, pos),
618                                                                 (int) strlen(clipdrawer_get_item_data(ad, pos)));
619                         }
620                         pos--;
621                         if (pos < 0)
622                                 pos = ITEMS_CNT_MAX-1;
623                 }
624         }*/
625 /*      else if (strcmp("get raw", ev->data.b) == 0)
626         {
627
628                 if (get_storage_start_addr != NULL)
629                 {
630                         XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
631                                                         8, PropModeReplace,
632                                                         (unsigned char *) get_storage_start_addr(),
633                                                         (int) get_total_storage_size());
634                 }
635         }
636         */
637         XFlush(ad->x_disp);
638
639         return EINA_TRUE;
640 }
641
642 static Eina_Bool _xfocus_out_cb(void *data, int type, void *event)
643 {
644         CALLED();
645         AppData *ad = data;
646         DTRACE("XE:FOCUS OUT\n");
647         clipdrawer_lower_view(ad);
648         return EINA_TRUE;
649 }
650
651 static Eina_Bool _xproperty_notify_cb(void *data, int type, void *event)
652 {
653 //      CALLED();
654         AppData *ad = data;
655         XHandlerData *xd = ad->xhandler;
656         ClipdrawerData *cd = ad->clipdrawer;
657         Ecore_X_Event_Window_Property *pevent = (Ecore_X_Event_Window_Property *)event;
658
659         if (ad->x_active_win != pevent->win)
660                 return EINA_TRUE;
661
662         if (xd->atomWindowRotate == pevent->atom)
663         {
664                 int angle = get_active_window_degree(ad->x_active_win);
665                 if (angle != cd->o_degree)
666                 {
667                         cd->o_degree = angle;
668                         elm_win_rotation_set(cd->main_win, angle);
669                         set_rotation_to_clipdrawer(cd);
670                 }
671         }
672
673         return EINA_TRUE;
674 }
675
676 static Eina_Bool _xwin_destroy_cb(void *data, int type, void *event)
677 {
678         CALLED();
679         AppData *ad = data;
680         Ecore_X_Event_Window_Destroy *pevent = event;
681         if (ad->x_active_win != pevent->win)
682                 return EINA_TRUE;
683         clipdrawer_lower_view(ad);
684 }
685
686 XHandlerData *init_xhandler(AppData *ad)
687 {
688         XHandlerData *xd = CALLOC(1, sizeof(XHandlerData));
689         if (!xd)
690                 return NULL;
691         xd->xsel_clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _xsel_clear_cb, ad);
692         xd->xsel_request_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, _xsel_request_cb, ad);
693         xd->xsel_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _xsel_notify_cb, ad);
694         xd->xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _xclient_msg_cb, ad);
695         xd->xfocus_out_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _xfocus_out_cb, ad);
696         xd->xproperty_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _xproperty_notify_cb, ad);
697         xd->xwindow_destroy_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _xwin_destroy_cb, ad);
698
699         xd->atomInc = ecore_x_atom_get("INCR");
700         xd->atomWindowRotate = ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE");
701         xd->atomCBHM_MSG = ecore_x_atom_get("CBHM_MSG");
702         xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
703         xd->atomXKey_MSG = ecore_x_atom_get("_XKEY_COMPOSITION");
704         xd->atomCBHMCount = ecore_x_atom_get("CBHM_cCOUNT");
705         xd->atomUTF8String = ecore_x_atom_get("UTF8_STRING");
706
707         int i;
708         for (i = 0; i < ITEM_CNT_MAX; i++)
709         {
710                 char buf[20];
711                 snprintf(buf, sizeof(buf), "CBHM_ITEM%d", i);
712                 xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
713         }
714
715         return xd;
716 }
717
718 void depose_xhandler(XHandlerData *xd)
719 {
720         ecore_event_handler_del(xd->xsel_clear_handler);
721         ecore_event_handler_del(xd->xsel_request_handler);
722         ecore_event_handler_del(xd->xsel_notify_handler);
723         ecore_event_handler_del(xd->xclient_msg_handler);
724         ecore_event_handler_del(xd->xfocus_out_handler);
725         ecore_event_handler_del(xd->xproperty_notify_handler);
726         ecore_event_handler_del(xd->xwindow_destroy_handler);
727         FREE(xd);
728 }
729
730 int get_active_window_degree(Ecore_X_Window active)
731 {
732         //ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE
733
734         int rotation = 0;
735         unsigned char *prop_data = NULL;
736         int count;
737         int ret = ecore_x_window_prop_property_get(
738                         active, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
739                         ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
740         if (ret && prop_data) memcpy(&rotation, prop_data, sizeof(int));
741         if (prop_data) FREE(prop_data);
742         return rotation;
743 }
744
745 void slot_property_set(AppData *ad, int index)
746 {
747         XHandlerData *xd = ad->xhandler;
748
749         if (index < 0)
750         {
751                 int i = 0;
752                 char buf[12];
753                 CNP_ITEM *item;
754                 Eina_List *l;
755
756                 EINA_LIST_FOREACH(ad->item_list, l, item)
757                 {
758                         snprintf(buf, sizeof(buf), "CBHM_ITEM%d", i);
759                         xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
760                         if (item)
761                         {
762                                 ecore_x_window_prop_property_set(
763                                         ad->x_event_win,
764                                         xd->atomCBHM_ITEM,
765                                         ad->targetAtoms[item->type_index].atom[0],
766                                         8,
767                                         item->data,
768                                         item->len);
769                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
770                                         i, ad->targetAtoms[item->type_index].atom[0],
771                                         item->data, item->len);
772                         }
773
774                         i++;
775                 }
776         }
777         else if (index < ITEM_CNT_MAX)
778         {
779                 char buf[12];
780                 snprintf(buf, sizeof(buf), "CBHM_ITEM%d", index);
781                 xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
782
783                 CNP_ITEM *item = item_get_by_index(ad, index);
784                 if (!item)
785                 {
786                         Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
787
788                         char error_buf[] = "OUT OF BOUND";
789                         int bufsize = sizeof(error_buf);
790                         ecore_x_window_prop_property_set(
791                                         ad->x_event_win,
792                                         xd->atomCBHM_ITEM,
793                                         itemtype,
794                                         8,
795                                         error_buf,
796                                         bufsize);
797                         DMSG("CBHM Error: index: %d, item count: %d\n",
798                                         index, item_count_get(ad));
799                 }
800                 else
801                 {
802                         ecore_x_window_prop_property_set(
803                                         ad->x_event_win,
804                                         xd->atomCBHM_ITEM,
805                                         ad->targetAtoms[item->type_index].atom[0],
806                                         8,
807                                         item->data,
808                                         item->len);
809                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
810                                         index, ad->targetAtoms[item->type_index].atom[0],
811                                         item->data, item->len);
812                 }
813         }
814         else
815         {
816                 DMSG("can't set property\n");
817         }
818 }
819
820 void slot_item_count_set(AppData *ad)
821 {
822         XHandlerData *xd = ad->xhandler;
823
824         int icount = item_count_get(ad);
825         char countbuf[10];
826         snprintf(countbuf, 10, "%d", icount);
827         ecore_x_window_prop_property_set(
828                         ad->x_event_win,
829                         xd->atomCBHMCount,
830                         xd->atomUTF8String,
831                         8,
832                         countbuf,
833                         strlen(countbuf)+1);
834 }