Revert - [xhandler] Fix not to activate clipboard window again if clipboard window...
[framework/uifw/cbhm.git] / src / xhandler.c
1 /*
2  * cbhm
3  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19
20 #include "xhandler.h"
21 #include <X11/Xatom.h>
22 #include <X11/Xlib.h>
23
24 Eina_Bool cbhm_send_event(AppData *ad, Ecore_X_Window xwin, char *msg)
25 {
26         ClipdrawerData *cd = ad->clipdrawer;
27
28         Ecore_X_Atom x_atom_cbhm_msg = ecore_x_atom_get("CBHM_MSG");
29         XClientMessageEvent m;
30         memset(&m, 0, sizeof(m));
31         m.type = ClientMessage;
32         m.display = ecore_x_display_get();
33         m.window = cd->x_main_win;
34         m.message_type = x_atom_cbhm_msg;
35         m.format = 8;
36         snprintf(m.data.b, 20, "%s", msg);
37
38         XSendEvent(ecore_x_display_get(), xwin, False, NoEventMask, (XEvent*)&m);
39
40         ecore_x_sync();
41
42         return EINA_TRUE;
43 }
44
45 Ecore_X_Window get_selection_owner(AppData *ad, Ecore_X_Selection selection)
46 {
47         CALLED();
48         if (!ad) return 0;
49         Ecore_X_Atom sel = 0;
50         switch(selection)
51         {
52                 case ECORE_X_SELECTION_SECONDARY:
53                         sel = ECORE_X_ATOM_SELECTION_SECONDARY;
54                         break;
55                 case ECORE_X_SELECTION_CLIPBOARD:
56                         sel = ECORE_X_ATOM_SELECTION_CLIPBOARD;
57                         break;
58                 default:
59                         return 0;
60         }
61         return XGetSelectionOwner(ad->x_disp, sel);
62 }
63
64 Eina_Bool is_cbhm_selection_owner(AppData *ad, Ecore_X_Selection selection)
65 {
66         CALLED();
67         if (!ad) return EINA_FALSE;
68         Ecore_X_Window sel_owner = get_selection_owner(ad, selection);
69         DMSG("selection_owner: 0x%x, x_event_win: 0x%x \n", sel_owner, ad->x_event_win);
70         if (sel_owner == ad->x_event_win)
71                 return EINA_TRUE;
72         return EINA_FALSE;
73 }
74
75 Eina_Bool set_selection_owner(AppData *ad, Ecore_X_Selection selection, CNP_ITEM *item)
76 {
77         CALLED();
78         if (!ad) return EINA_FALSE;
79
80         if (!item && is_cbhm_selection_owner(ad, selection))
81                 return EINA_TRUE;
82
83         Ecore_X_Atom sel = 0;
84         Eina_Bool (*selection_func)(Ecore_X_Window win, const void *data, int size) = NULL;
85
86         switch(selection)
87         {
88                 case ECORE_X_SELECTION_SECONDARY:
89 //                      ecore_x_selection_secondary_clear();
90                         selection_func = ecore_x_selection_secondary_set;
91                         ad->clip_selected_item = item;
92                         break;
93                 case ECORE_X_SELECTION_CLIPBOARD:
94 //                      ecore_x_selection_clipboard_clear();
95                         selection_func = ecore_x_selection_clipboard_set;
96                         break;
97                 default:
98                         return EINA_FALSE;
99         }
100
101         slot_selected_item_set(ad);
102         if (selection_func(ad->x_event_win, NULL, 0))
103                 return EINA_TRUE;
104
105         DMSG("ERROR: set selection failed\n");
106         return EINA_FALSE;
107 }
108
109 static Eina_Bool selection_timer_cb(void *data)
110 {
111         CALLED();
112         AppData *ad = data;
113         XHandlerData *xd = ad->xhandler;
114
115         set_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD, NULL);
116         if (is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
117         {
118                 ecore_timer_del(xd->selection_timer);
119                 xd->selection_timer = NULL;
120                 return ECORE_CALLBACK_CANCEL;
121         }
122         return ECORE_CALLBACK_RENEW;
123 }
124
125 static Eina_Bool _xsel_clear_cb(void *data, int type, void *event)
126 {
127         CALLED();
128         if (!data || !event) return EINA_TRUE;
129         AppData *ad = data;
130         XHandlerData *xd = ad->xhandler;
131         Ecore_X_Event_Selection_Clear *ev = event;
132
133         DMSG("in %s, ev->win: 0x%x\n", __func__, ev->win);
134
135         if (is_cbhm_selection_owner(ad, ev->selection)) return EINA_TRUE;
136         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
137                 return ECORE_CALLBACK_PASS_ON;
138
139         ecore_x_selection_clipboard_request(ad->x_event_win, ECORE_X_SELECTION_TARGET_TARGETS);
140
141         if (xd->selection_timer)
142         {
143                 ecore_timer_del(xd->selection_timer);
144                 xd->selection_timer = NULL;
145         }
146         xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
147
148         return ECORE_CALLBACK_DONE;
149 }
150
151 static Eina_Bool _xsel_request_cb(void *data, int type, void *event)
152 {
153         CALLED();
154         if (!data || !event) return ECORE_CALLBACK_PASS_ON;
155         AppData *ad = data;
156         Ecore_X_Event_Selection_Request *ev = event;
157
158 #ifdef DEBUG
159         char *names[3];
160         DMSG("selection_owner: 0x%x, ev->... owner: 0x%x, req: 0x%x, selection: %s, target: %s, property: %s\n",
161                         get_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD), ev->owner, ev->requestor,
162                         names[0] = ecore_x_atom_name_get(ev->selection),
163                         names[1] = ecore_x_atom_name_get(ev->target),
164                         names[2] = ecore_x_atom_name_get(ev->property));
165         FREE(names[0]);
166         FREE(names[1]);
167         FREE(names[2]);
168 #endif
169
170         CNP_ITEM *item = NULL;
171         if (ev->selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
172                 item = item_get_last(ad);
173         else if (ev->selection == ECORE_X_ATOM_SELECTION_SECONDARY)
174                 item = ad->clip_selected_item;
175         else
176                 return ECORE_CALLBACK_PASS_ON;
177
178         if (!item)
179         {
180                 DMSG("has no item\n");
181                 ecore_x_selection_notify_send(ev->requestor,
182                                 ev->selection,
183                                 None,
184                                 None,
185                                 CurrentTime);
186                 DMSG("change property notify\n");
187                 ecore_x_flush();
188                 return ECORE_CALLBACK_DONE;
189         }
190
191         Ecore_X_Atom property = None;
192         void *data_ret = NULL;
193         int size_ret;
194         Ecore_X_Atom ttype;
195         int tsize;
196
197         if (!generic_converter(ad, ev->target, item, &data_ret, &size_ret, &ttype, &tsize))
198                 /*      if (!ecore_x_selection_convert(ev->selection,
199                         ev->target,
200                         &data_ret, &len, &typeAtom, &typesize))*/
201
202         {
203                 /* Refuse selection, conversion to requested target failed */
204                 DMSG("converter return FALSE\n");
205         }
206         else if (data_ret)
207         {
208                 /* FIXME: This does not properly handle large data transfers */
209                 ecore_x_window_prop_property_set(
210                                 ev->requestor,
211                                 ev->property,
212                                 ttype,
213                                 tsize,
214                                 data_ret,
215                                 size_ret);
216                 property = ev->property;
217                 FREE(data_ret);
218                 DMSG("change property\n");
219         }
220
221         ecore_x_selection_notify_send(ev->requestor,
222                         ev->selection,
223                         ev->target,
224                         property,
225                         CurrentTime);
226         DMSG("change property notify\n");
227         ecore_x_flush();
228         return ECORE_CALLBACK_DONE;
229 }
230
231 static void send_convert_selection_target(AppData *ad, Ecore_X_Selection_Data_Targets *targets_data)
232 {
233         CALLED();
234         /*      struct _Ecore_X_Selection_Data_Targets {
235                 Ecore_X_Selection_Data data;
236                 struct _Ecore_X_Selection_Data {
237                 enum {
238                 ECORE_X_SELECTION_CONTENT_NONE,
239                 ECORE_X_SELECTION_CONTENT_TEXT,
240                 ECORE_X_SELECTION_CONTENT_FILES,
241                 ECORE_X_SELECTION_CONTENT_TARGETS,
242                 ECORE_X_SELECTION_CONTENT_CUSTOM
243                 } content;
244                 unsigned char *data;
245                 int            length;
246                 int            format;
247                 int            (*FREE)(void *data);
248                 };
249
250                 char                 **targets;
251                 int                    num_targets;
252                 };*/
253         if (!targets_data || !ad)
254                 return;
255         Ecore_X_Atom *atomlist = (Ecore_X_Atom *)targets_data->data.data;
256         if (!atomlist)
257                 return;
258
259         DMSG("targets_data->num_targets: 0x%x\n", targets_data->num_targets);
260         int i, j, k;
261         for (i = 0; i < targets_data->num_targets; i++)
262         {
263                 DMSG("get target: %s\n", targets_data->targets[i]);
264                 for (j = 0; j < ATOM_INDEX_MAX; j++)
265                 {
266                         for (k = 0; k < ad->targetAtoms[j].atom_cnt; k++)
267                         {
268                                 if (!strcmp(targets_data->targets[i], ad->targetAtoms[j].name[k]))
269                                 {
270                                         DMSG("find matched target: %s\n", ad->targetAtoms[j].name[k]);
271                                         ecore_x_selection_clipboard_request(ad->x_event_win, ad->targetAtoms[j].name[k]);
272                                         return;
273                                 }
274                         }
275                 }
276         }
277         DMSG("ERROR: get target atom failed\n");
278 }
279
280 static Eina_Bool _add_selection_imagepath(AppData* ad, char *str)
281 {
282         if (!ad || !str)
283                 return EINA_FALSE;
284         DMSG("get FILE: %s\n", str);
285         char *slash = strchr(str, '/');
286         while (slash && slash[0] == '/')
287         {
288                 if (slash[1] != '/')
289                 {
290                         char *filepath;
291                         filepath = strdup(slash);
292                         if (filepath)
293                         {
294                                 if (ecore_file_exists(filepath))
295                                 {
296                                         item_add_by_data(ad, ad->targetAtoms[ATOM_INDEX_IMAGE].atom[0], filepath, strlen(filepath) + 1);
297                                         return EINA_TRUE;
298                                 }
299                                 else
300                                         FREE(filepath);
301                         }
302                         break;
303                 }
304                 slash++;
305         }
306         DMSG("Error : it isn't normal file = %s\n", str);
307         return EINA_FALSE;
308 }
309
310 static void _get_selection_data_files(AppData* ad, Ecore_X_Selection_Data_Files *files_data)
311 {
312 /*      struct _Ecore_X_Selection_Data_Files {
313                 Ecore_X_Selection_Data data;
314                 char                 **files;
315                 int                    num_files;
316         }; */
317
318         int i;
319         for (i = 0; i < files_data->num_files; i++)
320         {
321                 _add_selection_imagepath(ad, files_data->files[i]);
322         }
323 }
324
325 static Eina_Bool _xsel_notify_cb(void *data, int type, void *event)
326 {
327         CALLED();
328         if (!data || !event)
329                 return ECORE_CALLBACK_PASS_ON;
330
331         AppData *ad = data;
332         XHandlerData *xd = ad->xhandler;
333         if (xd->selection_timer)
334         {
335                 ecore_timer_del(xd->selection_timer);
336                 xd->selection_timer = NULL;
337         }
338
339 /*      struct _Ecore_X_Event_Selection_Notify
340         {
341                 Ecore_X_Window    win;
342                 Ecore_X_Time      time;
343                 Ecore_X_Selection selection;
344                 Ecore_X_Atom      atom;
345                 char             *target;
346                 void             *data;
347         };*/
348         Ecore_X_Event_Selection_Notify *ev = event;
349
350         switch (ev->selection)
351         {
352                 case ECORE_X_SELECTION_CLIPBOARD:
353                         break;
354                 case ECORE_X_SELECTION_SECONDARY:
355                 case ECORE_X_SELECTION_PRIMARY:
356                 case ECORE_X_SELECTION_XDND:
357                 default:
358                         return ECORE_CALLBACK_PASS_ON;
359         }
360         if (!ev->data)
361                 goto set_clipboard_selection_owner;
362
363 /*      struct _Ecore_X_Selection_Data {
364                 enum {
365                         ECORE_X_SELECTION_CONTENT_NONE,
366                         ECORE_X_SELECTION_CONTENT_TEXT,
367                         ECORE_X_SELECTION_CONTENT_FILES,
368                         ECORE_X_SELECTION_CONTENT_TARGETS,
369                         ECORE_X_SELECTION_CONTENT_CUSTOM
370                 } content;
371                 unsigned char *data;
372                 int            length;
373                 int            format;
374                 int            (*FREE)(void *data);
375         };*/
376         Ecore_X_Selection_Data *sel_data = ev->data;
377         switch (sel_data->content)
378         {
379                 case ECORE_X_SELECTION_CONTENT_NONE:
380                         DMSG("ECORE_X_SELECTION_CONTENT_NONE\n");
381                         break;
382                 case ECORE_X_SELECTION_CONTENT_TEXT:
383                         DMSG("ECORE_X_SELECTION_CONTENT_TEXT\n");
384                 /*      struct _Ecore_X_Selection_Data_Text {
385                                 Ecore_X_Selection_Data data;
386                                 char                  *text;
387                         };
388                         Ecore_X_Selection_Data_Text *text_data = ev->data;*/
389                 //      DMSG("sel_data->data: 0x%x, text_data->text: 0x%x\n", sel_data->data, text_data->text);
390                         break;
391                 case ECORE_X_SELECTION_CONTENT_FILES:
392                         DMSG("ECORE_X_SELECTION_CONTENT_FILES\n");
393                         _get_selection_data_files(ad, ev->data);
394                         goto set_clipboard_selection_owner;
395                         break;
396                 case ECORE_X_SELECTION_CONTENT_TARGETS:
397                         DMSG("ECORE_X_SELECTION_CONTENT_TARGETS\n");
398                         send_convert_selection_target(ad, ev->data);
399                         if (!is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
400                                 xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
401                         return ECORE_CALLBACK_DONE;
402                 case ECORE_X_SELECTION_CONTENT_CUSTOM:
403                         DMSG("ECORE_X_SELECTION_CONTENT_CUSTOM\n");
404                         break;
405         }
406 #ifdef DEBUG
407         char *name;
408         DMSG("get atom: %d(%s), target: %s, length: %d, format: %d\n",
409                         ev->atom, name = ecore_x_atom_name_get(ev->atom), ev->target, sel_data->length, sel_data->format);
410         FREE(name);
411 #endif
412
413         Ecore_X_Atom targetAtom = ecore_x_atom_get(ev->target);
414         char *stripstr = strndup(sel_data->data, sel_data->length);
415         DMSG("get data: %s, len: %d\n", stripstr, strlen(stripstr));
416         if (atom_type_index_get(ad, targetAtom) == ATOM_INDEX_IMAGE)
417         {
418                 _add_selection_imagepath(ad, stripstr);
419                 FREE(stripstr);
420         }
421         else
422                 item_add_by_data(ad, targetAtom, stripstr, strlen(stripstr) + 1);
423
424 //      FREE(stripstr);
425
426 set_clipboard_selection_owner:
427         set_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD, NULL);
428         if (!is_cbhm_selection_owner(ad, ECORE_X_SELECTION_CLIPBOARD))
429                 xd->selection_timer = ecore_timer_add(SELECTION_CHECK_TIME, selection_timer_cb, ad);
430
431         return ECORE_CALLBACK_DONE;
432 }
433
434 static Eina_Bool _xclient_msg_cb(void *data, int type, void *event)
435 {
436         CALLED();
437         AppData *ad = data;
438         XHandlerData *xd = ad->xhandler;
439         ClipdrawerData *cd = ad->clipdrawer;
440
441         /*      struct _Ecore_X_Event_Client_Message {
442                 Ecore_X_Window win;
443                 Ecore_X_Atom   message_type;
444                 int            format;
445                 union
446                 {
447                         char        b[20];
448                         short       s[10];
449                         long        l[5];
450                 } data;
451                 Ecore_X_Time   time;
452         };*/
453         Ecore_X_Event_Client_Message *ev = event;
454
455         if (ev->message_type != xd->atomCBHM_MSG)
456                 return -1;
457
458         DTRACE("## %s\n", ev->data.b);
459
460 /*      Atom cbhm_atoms[ITEM_CNT_MAX];
461         char atomname[10];
462         Ecore_X_Window reqwin = ev->win;*/
463
464         if (strcmp("set_owner", ev->data.b) == 0)
465         {
466                 cbhm_send_event(ad, ev->win, "SET_OWNER");
467         }
468         else if (strncmp("show", ev->data.b, 4) == 0)
469         {
470                 ad->x_active_win = ev->win;
471                 if (ev->data.b[4] == '1')
472                         clipdrawer_paste_textonly_set(ad, EINA_FALSE);
473                 else
474                         clipdrawer_paste_textonly_set(ad, EINA_TRUE);
475
476                 clipdrawer_activate_view(ad);
477         }
478         else if (!strcmp("cbhm_hide", ev->data.b))
479         {
480                 clipdrawer_lower_view(ad);
481         }
482         else if (!strcmp("get count", ev->data.b))
483         {
484                 int icount = item_count_get(ad);
485                 char countbuf[10];
486                 DMSG("## cbhm count : %d\n", icount);
487                 snprintf(countbuf, 10, "%d", icount);
488                 ecore_x_window_prop_property_set(
489                                 ev->win,
490                                 xd->atomCBHMCount,
491                                 xd->atomUTF8String,
492                                 8,
493                                 countbuf,
494                                 strlen(countbuf)+1);
495         }
496         /* for OSP */
497         else if (strncmp("GET_ITEM", ev->data.b, 8) == 0)
498         {
499                 int itempos = 0;
500                 int index = 8;
501                 xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
502
503                 while ('0' <= ev->data.b[index] && ev->data.b[index] <= '9')
504                 {
505                         itempos = (itempos * 10) + (ev->data.b[index] - '0');
506                         index++;
507                 }
508
509                 CNP_ITEM *item = item_get_by_index(ad, itempos);
510                 if (!item)
511                 {
512                         Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
513
514                         char error_buf[] = "OUT OF BOUND";
515                         int bufsize = sizeof(error_buf);
516                         ecore_x_window_prop_property_set(
517                                         ev->win,
518                                         xd->atomCBHM_ITEM,
519                                         itemtype,
520                                         8,
521                                         error_buf,
522                                         bufsize);
523                         DMSG("GET ITEM ERROR msg: %s, index: %d, item count: %d\n",
524                                         ev->data.b, itempos, item_count_get(ad));
525                 }
526                 else
527                 {
528                         ecore_x_window_prop_property_set(
529                                         ev->win,
530                                         xd->atomCBHM_ITEM,
531                                         ad->targetAtoms[item->type_index].atom[0],
532                                         8,
533                                         item->data,
534                                         item->len);
535                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
536                                         itempos, ad->targetAtoms[item->type_index].atom[0],
537                                         item->data, item->len);
538                 }
539         }
540         else if (strncmp("SET_ITEM", ev->data.b, 8) == 0)
541         {
542                 int ret = 0;
543                 int size_ret = 0;
544                 unsigned long num_ret = 0;
545                 unsigned long bytes = 0;
546                 unsigned char *item_data = NULL;
547                 unsigned char *prop_ret = NULL;
548                 Ecore_X_Atom format = 0;
549                 int i;
550                 xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
551                 ret = XGetWindowProperty(ecore_x_display_get(), ad->x_event_win, xd->atomCBHM_ITEM, 0, LONG_MAX, False, ecore_x_window_prop_any_type(),
552                                 (Atom*)&format, &size_ret, &num_ret, &bytes, &prop_ret);
553                 ecore_x_sync();
554                 if (ret != Success)
555                 {
556                         DMSG("Failed Set Item\n");
557                         return EINA_FALSE;
558                 }
559                 if (!num_ret)
560                 {
561                         XFree(prop_ret);
562                         return EINA_FALSE;
563                 }
564
565                 if (!(item_data = malloc(num_ret * size_ret / 8)))
566                 {
567                         XFree(item_data);
568                         return EINA_FALSE;
569                 }
570
571                 switch (size_ret)
572                 {
573                         case 8:
574                         default:
575                                 for (i = 0; i < num_ret; i++)
576                                         item_data[i] = prop_ret[i];
577                                 break;
578                         case 16:
579                                 for (i = 0; i < num_ret; i++)
580                                         ((unsigned short *)item_data)[i] = ((unsigned short *)prop_ret)[i];
581                                 break;
582                         case 32:
583                                 for (i = 0; i < num_ret; i++)
584                                         ((unsigned int *)item_data)[i] = ((unsigned long *)prop_ret)[i];
585                                 break;
586                 }
587
588                 XFree(prop_ret);
589
590                 DMSG("item_data:%s format:%s(%d)\n", item_data, ecore_x_atom_name_get(format), format);
591                 item_add_by_data(ad, format, item_data, strlen(item_data) + 1);
592         }
593         else if (strncmp("DEL_ITEM", ev->data.b, 8) == 0)
594         {
595                 int itempos = 0;
596                 int index = 8;
597
598                 while ('0' <= ev->data.b[index] && ev->data.b[index] <= '9')
599                 {
600                         itempos = (itempos * 10) + (ev->data.b[index] - '0');
601                         index++;
602                 }
603
604                 item_delete_by_index(ad, itempos);
605         }
606 /*      else if (strncmp("get #", ev->data.b, 5) == 0)
607         {
608                 // FIXME : handle greater than 9
609                 int num = ev->data.b[5] - '0';
610                 int cur = get_current_history_position();
611                 num = cur + num - 1;
612                 if (num > ITEMS_CNT_MAX-1)
613                         num = num-ITEMS_CNT_MAX;
614
615                 if (num >= 0 && num < ITEMS_CNT_MAX)
616                 {
617                         DTRACE("## pos : #%d\n", num);
618                         // FIXME : handle with correct atom
619                         sprintf(atomname, "CBHM_c%d", num);
620                         cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
621
622                         CNP_ITEM *item = clipdr;
623
624
625                         if (clipdrawer_get_item_data(ad, num) != NULL)
626                         {
627                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
628                                                                 8, PropModeReplace,
629                                                                 (unsigned char *) clipdrawer_get_item_data(ad, num),
630                                                                 (int) strlen(clipdrawer_get_item_data(ad, num)));
631                         }
632                 }
633         }
634         else if (strcmp("get all", ev->data.b) == 0)
635         {
636 //              print_history_buffer();
637                 pos = get_current_history_position();
638                 for (i = 0; i < 5; i++)
639                 {
640                         DTRACE("## %d -> %d\n", i, pos);
641                         sprintf(atomname, "CBHM_c%d", i);
642                         cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
643                         if (clipdrawer_get_item_data(ad, pos) != NULL)
644                         {
645                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
646                                                                 8, PropModeReplace,
647                                                                 (unsigned char *) clipdrawer_get_item_data(ad, pos),
648                                                                 (int) strlen(clipdrawer_get_item_data(ad, pos)));
649                         }
650                         pos--;
651                         if (pos < 0)
652                                 pos = ITEMS_CNT_MAX-1;
653                 }
654         }*/
655 /*      else if (strcmp("get raw", ev->data.b) == 0)
656         {
657
658                 if (get_storage_start_addr != NULL)
659                 {
660                         XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
661                                                         8, PropModeReplace,
662                                                         (unsigned char *) get_storage_start_addr(),
663                                                         (int) get_total_storage_size());
664                 }
665         }
666         */
667         XFlush(ad->x_disp);
668
669         return EINA_TRUE;
670 }
671
672 static Eina_Bool _xfocus_out_cb(void *data, int type, void *event)
673 {
674         CALLED();
675         AppData *ad = data;
676         DTRACE("XE:FOCUS OUT\n");
677         clipdrawer_lower_view(ad);
678         return EINA_TRUE;
679 }
680
681 static Eina_Bool _xproperty_notify_cb(void *data, int type, void *event)
682 {
683         CALLED();
684         AppData *ad = data;
685         XHandlerData *xd = ad->xhandler;
686         ClipdrawerData *cd = ad->clipdrawer;
687         Ecore_X_Event_Window_Property *pevent = (Ecore_X_Event_Window_Property *)event;
688
689         if (ad->x_active_win != pevent->win)
690                 return EINA_TRUE;
691
692         if (xd->atomWindowRotate == pevent->atom)
693         {
694                 int angle = get_active_window_degree(ad->x_active_win);
695                 if (angle != cd->o_degree)
696                 {
697                         cd->o_degree = angle;
698                         elm_win_rotation_set(cd->main_win, angle);
699                         set_rotation_to_clipdrawer(cd);
700                 }
701         }
702
703         return EINA_TRUE;
704 }
705
706 static Eina_Bool _xzone_init_cb(void *data, int type, void *event)
707 {
708         CALLED();
709         if (!data || !event) return EINA_FALSE;
710         AppData *ad = data;
711         ClipdrawerData *cd = ad->clipdrawer;
712         XHandlerData *xd = ad->xhandler;
713         Ecore_X_Event_Window_Property *pevent = (Ecore_X_Event_Window_Property *)event;
714
715         if (pevent->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
716         {
717                 Ecore_X_Window zone;
718                 int val_len = ecore_x_window_prop_window_get(cd->x_main_win, ECORE_X_ATOM_E_ILLUME_ZONE, &zone, 1);
719                 if (val_len > 0)
720                 {
721                         Ecore_X_Window zone = ecore_x_e_illume_zone_get(cd->x_main_win);
722                         ecore_x_e_illume_clipboard_state_set(zone, ECORE_X_ILLUME_CLIPBOARD_STATE_OFF);
723
724                         /* hide clipboard elm_win after initializing zone x_win */
725                         evas_object_hide(cd->main_win);
726                         ecore_event_handler_del(xd->xproperty_notify_handler);
727                         xd->xproperty_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _xproperty_notify_cb, ad);
728                 }
729         }
730
731         return EINA_TRUE;
732 }
733
734 static Eina_Bool _xwin_destroy_cb(void *data, int type, void *event)
735 {
736         CALLED();
737         AppData *ad = data;
738         Ecore_X_Event_Window_Destroy *pevent = event;
739         if (ad->x_active_win != pevent->win)
740                 return ECORE_CALLBACK_PASS_ON;
741         clipdrawer_lower_view(ad);
742         return ECORE_CALLBACK_DONE;
743 }
744
745 XHandlerData *init_xhandler(AppData *ad)
746 {
747         XHandlerData *xd = CALLOC(1, sizeof(XHandlerData));
748         if (!xd)
749                 return NULL;
750         xd->xsel_clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _xsel_clear_cb, ad);
751         xd->xsel_request_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, _xsel_request_cb, ad);
752         xd->xsel_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _xsel_notify_cb, ad);
753         xd->xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _xclient_msg_cb, ad);
754         xd->xfocus_out_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _xfocus_out_cb, ad);
755         xd->xproperty_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _xzone_init_cb, ad);
756         xd->xwindow_destroy_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _xwin_destroy_cb, ad);
757
758         ClipdrawerData *cd = ad->clipdrawer;
759         /* show clipboard elm_win to initialize zone x_win */
760         evas_object_show(cd->main_win);
761
762         xd->atomInc = ecore_x_atom_get("INCR");
763         xd->atomWindowRotate = ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE");
764         xd->atomCBHM_MSG = ecore_x_atom_get("CBHM_MSG");
765         xd->atomCBHM_ITEM = ecore_x_atom_get("CBHM_ITEM");
766         xd->atomCBHMCount = ecore_x_atom_get("CBHM_cCOUNT");
767         xd->atomUTF8String = ecore_x_atom_get("UTF8_STRING");
768         xd->atomCBHM_SELECTED_ITEM = ecore_x_atom_get("CBHM_SELECTED_ITEM");
769
770         int i;
771         for (i = 0; i < ITEM_CNT_MAX; i++)
772         {
773                 char buf[20];
774                 snprintf(buf, sizeof(buf), "CBHM_ITEM%d", i);
775                 xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
776         }
777
778         return xd;
779 }
780
781 void depose_xhandler(XHandlerData *xd)
782 {
783         ecore_event_handler_del(xd->xsel_clear_handler);
784         ecore_event_handler_del(xd->xsel_request_handler);
785         ecore_event_handler_del(xd->xsel_notify_handler);
786         ecore_event_handler_del(xd->xclient_msg_handler);
787         ecore_event_handler_del(xd->xfocus_out_handler);
788         ecore_event_handler_del(xd->xproperty_notify_handler);
789         ecore_event_handler_del(xd->xwindow_destroy_handler);
790         FREE(xd);
791 }
792
793 int get_active_window_degree(Ecore_X_Window active)
794 {
795         //ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE
796
797         int rotation = 0;
798         unsigned char *prop_data = NULL;
799         int count;
800         int ret = ecore_x_window_prop_property_get(
801                         active, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
802                         ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
803         if (ret && prop_data) memcpy(&rotation, prop_data, sizeof(int));
804         if (prop_data) FREE(prop_data);
805         return rotation;
806 }
807
808 void slot_property_set(AppData *ad, int index)
809 {
810         XHandlerData *xd = ad->xhandler;
811
812         if (index < 0)
813         {
814                 int i = 0;
815                 char buf[12];
816                 CNP_ITEM *item;
817                 Eina_List *l;
818
819                 EINA_LIST_FOREACH(ad->item_list, l, item)
820                 {
821                         snprintf(buf, sizeof(buf), "CBHM_ITEM%d", i);
822                         xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
823                         if (item)
824                         {
825                                 ecore_x_window_prop_property_set(
826                                         ad->x_event_win,
827                                         xd->atomCBHM_ITEM,
828                                         ad->targetAtoms[item->type_index].atom[0],
829                                         8,
830                                         item->data,
831                                         item->len);
832                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
833                                         i, ad->targetAtoms[item->type_index].atom[0],
834                                         item->data, item->len);
835                         }
836
837                         i++;
838                 }
839         }
840         else if (index < ITEM_CNT_MAX)
841         {
842                 char buf[12];
843                 snprintf(buf, sizeof(buf), "CBHM_ITEM%d", index);
844                 xd->atomCBHM_ITEM = ecore_x_atom_get(buf);
845
846                 CNP_ITEM *item = item_get_by_index(ad, index);
847                 if (!item)
848                 {
849                         Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
850
851                         char error_buf[] = "OUT OF BOUND";
852                         int bufsize = sizeof(error_buf);
853                         ecore_x_window_prop_property_set(
854                                         ad->x_event_win,
855                                         xd->atomCBHM_ITEM,
856                                         itemtype,
857                                         8,
858                                         error_buf,
859                                         bufsize);
860                         DMSG("CBHM Error: index: %d, item count: %d\n",
861                                         index, item_count_get(ad));
862                 }
863                 else
864                 {
865                         ecore_x_window_prop_property_set(
866                                         ad->x_event_win,
867                                         xd->atomCBHM_ITEM,
868                                         ad->targetAtoms[item->type_index].atom[0],
869                                         8,
870                                         item->data,
871                                         item->len);
872                         DMSG("GET ITEM index: %d, item type: %d, item data: %s, item->len: %d\n",
873                                         index, ad->targetAtoms[item->type_index].atom[0],
874                                         item->data, item->len);
875                 }
876         }
877         else
878         {
879                 DMSG("can't set property\n");
880         }
881 }
882
883 void slot_item_count_set(AppData *ad)
884 {
885         XHandlerData *xd = ad->xhandler;
886
887         int icount = item_count_get(ad);
888         char countbuf[10];
889         snprintf(countbuf, 10, "%d", icount);
890         ecore_x_window_prop_property_set(
891                         ad->x_event_win,
892                         xd->atomCBHMCount,
893                         xd->atomUTF8String,
894                         8,
895                         countbuf,
896                         strlen(countbuf)+1);
897 }
898
899 void slot_selected_item_set(AppData *ad)
900 {
901         XHandlerData *xd = ad->xhandler;
902         CNP_ITEM *item = ad->clip_selected_item;
903
904         if (item)
905         {
906                 char buf[20];
907                 snprintf(buf, sizeof(buf), "CBHM_SELECTED_ITEM");
908                 xd->atomCBHM_SELECTED_ITEM = ecore_x_atom_get(buf);
909
910                 ecore_x_window_prop_property_set(
911                                 ad->x_event_win,
912                                 xd->atomCBHM_SELECTED_ITEM,
913                                 ad->targetAtoms[item->type_index].atom[0],
914                                 8,
915                                 item->data,
916                                 item->len);
917         }
918         else
919         {
920                 Ecore_X_Atom itemtype = ecore_x_atom_get("CBHM_ERROR");
921
922                 char error_buf[] = "NOT EXIST SELECTED ITEM";
923                 int bufsize = sizeof(error_buf);
924                 ecore_x_window_prop_property_set(
925                                 ad->x_event_win,
926                                 xd->atomCBHM_SELECTED_ITEM,
927                                 itemtype,
928                                 8,
929                                 error_buf,
930                                 bufsize);
931
932         }
933 }
934
935