disable window effect
[framework/uifw/cbhm.git] / src / xcnphandler.c
1 #include "common.h"
2 #include "cbhm_main.h"
3 #include "xcnphandler.h"
4 #include "storage.h"
5 #include "clipdrawer.h"
6
7 static Ecore_Event_Handler *xsel_clear_handler = NULL;
8 static Ecore_Event_Handler *xsel_request_handler = NULL;
9 static Ecore_Event_Handler *xsel_notify_handler = NULL;
10 static Ecore_Event_Handler *xclient_msg_handler = NULL;
11 static Ecore_Event_Handler *xfocus_out_handler = NULL;
12
13 char *g_lastest_content = NULL;
14 int g_history_pos = 0;
15
16 int xcnp_init(void *data)
17 {
18         struct appdata *ad = data;
19         DTRACE("xcnp_init().. start!\n");
20
21         if(!_cbhm_init(ad))
22         {
23                 DTRACE("Failed - _cbhm_init()..!\n");
24                 return NULL;
25         }
26
27         //Adding Event Handlers
28         xsel_clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _xsel_clear_cb, ad);
29         xsel_request_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, _xsel_request_cb, ad);
30         xsel_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _xsel_notify_cb, ad);
31         xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _xclient_msg_cb, ad);
32         xfocus_out_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _xfocus_out_cb, ad);
33
34         if(!xsel_clear_handler)
35                 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_CLEAR handler\n");
36         if(!xsel_request_handler)
37                 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_REQUEST handler\n");
38         if(!xsel_notify_handler)
39                 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_NOTIFY handler\n");
40         if(!xclient_msg_handler)
41                 DTRACE("Failed to add ECORE_X_EVENT_CLIENT_MESSAGE handler\n");
42         if(!xfocus_out_handler)
43                 DTRACE("Failed to add ECORE_X_EVENT_WINDOW_FOCUS_OUT handler\n");
44
45         return TRUE;
46 }
47
48 int xcnp_shutdown()
49 {
50         //Removing Event Handlers
51         ecore_event_handler_del(xsel_clear_handler);
52         ecore_event_handler_del(xsel_request_handler);
53         ecore_event_handler_del(xsel_notify_handler);
54         ecore_event_handler_del(xclient_msg_handler);
55         ecore_event_handler_del(xfocus_out_handler);
56
57         xsel_clear_handler = NULL;
58         xsel_request_handler = NULL;
59         xsel_notify_handler = NULL;
60         xclient_msg_handler = NULL;
61         xfocus_out_handler = NULL;
62
63         _cbhm_fini();
64
65         return TRUE;
66 }
67
68 static int _init_atoms()
69 {
70         /* all atoms are global variables */
71         atomPrimary = XA_PRIMARY; 
72         atomSecondary = XA_SECONDARY; 
73 //      atomTarget = XA_STRING;
74         atomClipboard = XInternAtom(g_disp, ATOM_CLIPBOARD_NAME, False);
75         atomCBHM = XInternAtom (g_disp, ATOM_CLIPBOARD_MANAGER_NAME, False);
76         atomCBOut = XInternAtom(g_disp, ATOM_CBHM_OUTBUF, False);
77         atomInc = XInternAtom(g_disp, "INCR", False);
78         atomTargets = XInternAtom(g_disp, "TARGETS", False);
79         atomUTF8String = XInternAtom(g_disp, "UTF8_STRING", False);
80         atomHtmltext = XInternAtom(g_disp, "text/html;charset=utf-8", False);
81
82         return TRUE;
83 }
84
85 static void _set_cbhmwin_prop()
86 {
87         Atom atomCbhmWin = XInternAtom(g_disp, "CBHM_XWIN", False);
88         XChangeProperty(g_disp, g_rootwin, atomCbhmWin, XA_WINDOW, 
89                                         32, PropModeReplace,
90                                         (unsigned char *)&g_evtwin, (int) 1);
91 }
92
93 int increment_current_history_position()
94 {
95         int pos = g_history_pos+1;
96         if (pos >= HISTORY_QUEUE_MAX_TXT_ITEMS)
97                 pos = 0;
98         g_history_pos = pos;
99         return pos;
100 }
101
102 int get_current_history_position()
103 {
104         int pos = g_history_pos-1;
105         if (pos < 0)
106                 pos = HISTORY_QUEUE_MAX_TXT_ITEMS-1;
107         
108         return pos;
109 }
110
111 int add_to_storage_buffer(void *data, char *src, int len)
112 {
113         struct appdata *ad = data;
114
115         if (len <= 0)
116                 return -1;
117
118         if (g_lastest_content == NULL)
119                 g_lastest_content = malloc(sizeof(char)*(HISTORY_QUEUE_TXT_ITEM_SIZE));
120         if (g_history_pos >= HISTORY_QUEUE_MAX_TXT_ITEMS)
121                 g_history_pos = 0;
122
123         // FIXME: remove g_lasteset_content
124         //strcpy(g_lastest_content, src);
125         memcpy(g_lastest_content, src, len);
126         g_lastest_content[len] = '\0';
127         adding_item_to_storage(g_history_pos, g_lastest_content);
128         increment_current_history_position();
129
130         int nserial = 0;
131         nserial = get_storage_serial_code();
132         Atom atomCbhmSerial = XInternAtom(g_disp, "CBHM_SERIAL_NUMBER", False);
133         XChangeProperty(g_disp, g_evtwin, atomCbhmSerial, XA_INTEGER,
134                                         32, PropModeReplace,
135                                         (unsigned char *)&nserial, (int) 1);
136         XFlush(g_disp);
137
138         clipdrawer_update_contents(ad);
139
140         return 0;
141 }
142
143 int print_storage_buffer()
144 {
145         int pos;
146         int i = 0;
147         for (i = 0; i < HISTORY_QUEUE_MAX_TXT_ITEMS; i++)
148         {
149                 pos = get_current_history_position()+i;
150                 if (pos > HISTORY_QUEUE_MAX_TXT_ITEMS-1)
151                         pos = pos-HISTORY_QUEUE_MAX_TXT_ITEMS;
152                 DTRACE("%d: %s\n", i, get_item_contents_by_pos(pos) != NULL ? get_item_contents_by_pos(pos) : "NULL");
153         }
154 }
155
156 int send_convert_selection()
157 {
158         XConvertSelection(g_disp, atomClipboard, atomUTF8String, atomCBOut, g_evtwin, CurrentTime);
159         DTRACE("sent convert selection\n");
160         return 0;
161 }
162
163 int set_clipboard_manager_owner()
164 {
165         XSetSelectionOwner(g_disp, atomCBHM, g_evtwin, CurrentTime);
166         Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomCBHM);
167         DTRACE("g_evtwin = 0x%x, setted clipboard manager owner is = 0x%x\n", g_evtwin, selowner_window);
168         return 0;
169 }
170
171 int set_selection_owner()
172 {
173         XSetSelectionOwner(g_disp, atomClipboard, g_evtwin, CurrentTime);
174         Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomClipboard);
175         DTRACE("evtwin = 0x%x, setted selection owner is = 0x%x\n", g_evtwin, selowner_window);
176         return 0;
177 }
178
179 int get_selection_content(void *data)
180 {
181         Atom cbtype;
182         int cbformat;
183         unsigned long cbsize, cbitems;
184         unsigned char *cbbuf;
185         struct appdata *ad = data;
186         const char *unesc;
187         size_t unesc_len = 0;
188         int i;
189
190         XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, 0, False,
191                                            AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
192         XFree(cbbuf);
193
194         if (cbtype == atomInc)
195         {
196                 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
197                 XFlush(g_disp);
198                 DTRACE("INCR \n");
199                 return -1;
200         }
201
202         DTRACE("cbsize = %d\n", cbsize);
203
204         if (cbformat != 8)
205         {
206                 DTRACE("There're nothing to read = %d\n", cbformat);
207                 return -2;
208         }
209
210         XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, (long) cbsize, False,
211                                            AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
212         XDeleteProperty(g_disp, g_evtwin, atomCBOut);
213
214         unesc = clipdrawer_get_plain_string_from_escaped(cbbuf);
215         if (unesc != NULL)
216         {
217                 unesc_len = strlen(unesc);
218                 // FIXME: invent more clever way to right trim the string
219                 for (i = unesc_len-1; i > 0; i--)
220                 {
221                         // avoid control characters
222                         if (unesc[i] >= 0x01 && unesc[i] <= 0x1F)
223                                 continue;
224                         else
225                         {
226                                 DTRACE("before right trim len = %d\n", unesc_len);
227                                 unesc_len = i+1;
228                                 DTRACE("after right trim len = %d\n", unesc_len);
229                                 break;
230                         }
231                 }
232         }
233         else
234                 unesc_len = 0;
235
236 //      add_to_storage_buffer(ad, cbbuf, cbitems);
237 //      DTRACE("len = %ld, data = %s\n", cbitems, cbbuf);
238
239 /*
240         if (cbbuf != NULL)
241         {
242                 unesc_len = strlen(cbbuf);
243                 // FIXME: invent more clever way to right trim the string
244                 for (i = unesc_len-1; i > 0; i--)
245                 {
246                         // avoid control characters
247                         if (cbbuf[i] >= 0x01 && cbbuf[i] <= 0x1F)
248                                 continue;
249                         else
250                         {
251                                 DTRACE("before right trim len = %d\n", unesc_len);
252                                 unesc_len = i+1;
253                                 DTRACE("after right trim len = %d\n", unesc_len);
254                                 break;
255                         }
256                 }
257         }
258         else
259                 unesc_len = 0;
260
261         if (!strncmp(cbbuf, "file://", 7) && 
262                 (strcasestr(cbbuf,".png") || strcasestr(cbbuf,".jpg") || strcasestr(cbbuf,".bmp")) &&
263                 check_regular_file(cbbuf+7))
264         {
265                 DTRACE("clipdrawer add path = %s\n", cbbuf+7);
266                 clipdrawer_add_image_item(cbbuf+7);
267         }
268         else
269                 add_to_storage_buffer(ad, cbbuf, unesc_len);
270         DTRACE("len = %ld, data = %s\n", unesc_len, cbbuf);
271 */
272
273
274         /* FIXME : it needs two verification. 
275                1. does the file exist?
276                2. dose the file wanted type? */
277         if (!strncmp(unesc, "file://", 7) && 
278                 (strcasestr(unesc,".png") || strcasestr(unesc,".jpg") || strcasestr(unesc,".bmp")) &&
279                 check_regular_file(unesc+7))
280         {
281                 DTRACE("clipdrawer add path = %s\n", unesc+7);
282                 clipdrawer_add_image_item(unesc+7);
283         }
284         else
285                 add_to_storage_buffer(ad, unesc, unesc_len);
286         DTRACE("len = %ld, data = %s\n", unesc_len, unesc);
287         free(unesc);
288
289         DTRACE("\n");
290         print_storage_buffer();
291         DTRACE("\n");
292
293         XFree(cbbuf);
294
295         return 0;
296 }
297
298 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
299 {
300         XEvent req_evt;
301         int req_size;
302         Ecore_X_Window req_win;
303         Atom req_atom;
304
305         req_size = XExtendedMaxRequestSize(g_disp) / 4;
306         if (!req_size)
307         {
308                 req_size = XMaxRequestSize(g_disp) / 4;
309         }
310
311     req_win = ev->requestor;
312         req_atom = ev->property;
313
314         DTRACE("## wanted target = %d\n", ev->target);
315         DTRACE("## wanted target = %s\n", XGetAtomName(g_disp, ev->target));
316         DTRACE("## req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
317
318         /* TODO : if there are request which cbhm doesn't understand,
319            then reply None property to requestor */
320         /* TODO : add image type */
321         if (ev->target == atomTargets) 
322         {
323 //        Atom types[2] = { atomTargets, atomUTF8String };
324         Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
325
326         // send all (not using INCR) 
327         XChangeProperty(g_disp, req_win, req_atom, XA_ATOM,
328                                                 32, PropModeReplace, (unsigned char *) types,
329                                                 (int) (sizeof(types) / sizeof(Atom)));
330                 DTRACE("target matched\n");
331     }
332     else
333         {
334                 DTRACE("target mismatched. trying to txt\n");
335
336                 int txt_len;
337                 if (g_lastest_content != NULL)
338                         txt_len = strlen(g_lastest_content);
339                 else
340                         txt_len = 0;
341
342                 if (txt_len > req_size) 
343                 {
344                         // INCR 
345                 }
346                 else 
347                 {
348                         // send all (not using INCR) 
349                         XChangeProperty(g_disp, req_win, req_atom, atomUTF8String, 
350                                                         8, PropModeReplace, (unsigned char *) g_lastest_content, (int) txt_len);
351                 }
352                 DTRACE("txt target, len = %d\n", txt_len);
353                 if (txt_len > 0 && g_lastest_content != NULL)
354                         DTRACE("txt target, content = %s\n", g_lastest_content);
355         }
356
357 /*
358         DTRACE("wanted window = 0x%x\n", req_win);
359         DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
360 */
361         DTRACE("selection target = %s\n", XGetAtomName(g_disp, ev->selection));
362         DTRACE("getted atom name = %s\n", XGetAtomName(g_disp, req_atom));
363         DTRACE("req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
364
365     req_evt.xselection.property = req_atom;
366     req_evt.xselection.type = SelectionNotify;
367     req_evt.xselection.display = g_disp;
368     req_evt.xselection.requestor = req_win;
369     req_evt.xselection.selection = ev->selection;
370     req_evt.xselection.target = ev->target;
371     req_evt.xselection.time = ev->time;
372
373     XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
374     XFlush(g_disp);
375
376         return 0;
377 }
378
379 static int _cbhm_init(void *data)
380 {
381         struct appdata *ad = data;
382         //Set default data structure
383         //Control that the libraries are properly initialized
384         if (!ecore_init()) return EXIT_FAILURE;
385         if (!ecore_evas_init()) return EXIT_FAILURE;
386         if (!edje_init()) return EXIT_FAILURE;
387
388         // do not x init in this module, it disconnect previous e17's X connection
389         //ecore_x_init(NULL);
390
391         g_disp = ecore_x_display_get();
392
393         if( !g_disp )
394         {
395                 DTRACE("Failed to get display\n");
396                 return -1;
397         }
398
399         g_rootwin = DefaultRootWindow(g_disp);
400         g_evtwin = ecore_x_window_new(g_rootwin, 0, 0, 19, 19);
401         ecore_x_netwm_name_set(g_evtwin, CLIPBOARD_MANAGER_WINDOW_TITLE_STRING);
402
403         XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
404         XSelectInput(g_disp, g_rootwin, StructureNotifyMask);
405 //      ecore_x_window_show(g_evtwin);
406         ecore_x_flush();
407
408         _set_cbhmwin_prop();
409     _init_atoms();
410         init_storage();
411
412         DTRACE("_cbhm_init ok\n");
413
414         set_clipboard_manager_owner();
415         send_convert_selection();
416         set_selection_owner();
417
418         return TRUE;
419 }
420
421 static void _cbhm_fini()
422 {
423         close_storage();
424
425         return;
426 }
427
428 static int _xsel_clear_cb(void *data, int ev_type, void *event)
429 {
430         struct appdata *ad = data;
431
432         Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
433
434         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
435                 return TRUE;
436         
437         DTRACE("XE:SelectionClear\n");
438
439         send_convert_selection();
440         ecore_x_flush();
441         /* TODO : set selection request is should after convert selection
442          * is done */
443         set_selection_owner();
444
445         return TRUE;
446 }
447
448 static int _xsel_request_cb(void *data, int ev_type, void *event)
449 {
450         Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
451
452         if (ev->selection != atomClipboard)
453                 return TRUE;
454
455         DTRACE("XE:SelectionRequest\n");
456
457         processing_selection_request(ev);
458
459         return TRUE;
460 }
461
462 static int _xsel_notify_cb(void *data, int ev_type, void *event)
463 {
464         struct appdata *ad = data;
465
466         Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
467         Ecore_X_Selection_Data_Text *text_data = NULL;
468
469         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
470                 return TRUE;
471         
472         DTRACE("XE:SelectionNotify\n");
473
474         text_data = ev->data;
475         DTRACE("content type = %d\n", text_data->data.content);
476         get_selection_content(ad);
477
478         if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
479         {
480                 DTRACE("content isn't text\n");
481         }
482
483         return TRUE;
484 }
485
486 static int _xclient_msg_cb(void *data, int ev_type, void *event)
487 {
488         struct appdata *ad = data;
489
490         Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
491
492         Atom atomCBHM_MSG = XInternAtom(g_disp, "CBHM_MSG", False);
493         Atom atomCBHM_cRAW = XInternAtom(g_disp, "CBHM_cRAW", False);
494         Atom atomXKey_MSG = XInternAtom(g_disp, "_XKEY_COMPOSITION", False);
495         char atomname[10];
496         Atom cbhm_atoms[HISTORY_QUEUE_MAX_TXT_ITEMS];
497         Ecore_X_Window reqwin = ev->win;
498         int i, pos;
499
500         if (ev->message_type == atomXKey_MSG)
501         {
502                 DTRACE("XE:ClientMessage for Screen capture\n");
503
504                 capture_current_screen(ad);
505
506                 return TRUE;
507         }
508
509         if (ev->message_type != atomCBHM_MSG)
510                 return -1;
511
512         DTRACE("XE:ClientMessage for CBHM\n");
513
514         DTRACE("## %s\n", ev->data.b);
515
516         if (strcmp("get count", ev->data.b) == 0)
517         {
518                 int icount = get_item_counts();
519                 char countbuf[10];
520                 DTRACE("## cbhm count : %d\n", icount);
521                 sprintf(countbuf, "%d", icount);
522                 sprintf(atomname, "CBHM_cCOUNT");
523                 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
524                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String, 
525                                                 8, PropModeReplace, 
526                                                 (unsigned char *) countbuf, 
527                                                 (int) strlen(countbuf));
528         
529         }
530         else if (strncmp("get #", ev->data.b, 5) == 0)
531         {
532                 // FIXME : handle greater than 9
533                 int num = ev->data.b[5] - '0';
534                 int cur = get_current_history_position();
535                 num = cur + num - 1;
536                 if (num > HISTORY_QUEUE_MAX_TXT_ITEMS-1)
537                         num = num-HISTORY_QUEUE_MAX_TXT_ITEMS;
538
539                 if (num >= 0 && num < HISTORY_QUEUE_MAX_TXT_ITEMS)
540                 {
541                         DTRACE("## pos : #%d\n", num);
542                         // FIXME : handle with correct atom
543                         sprintf(atomname, "CBHM_c%d", num);
544                         cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
545                         if (get_item_contents_by_pos(num) != NULL)
546                         {
547                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String, 
548                                                                 8, PropModeReplace, 
549                                                                 (unsigned char *) get_item_contents_by_pos(num), 
550                                                                 (int) strlen(get_item_contents_by_pos(num)));
551                         }
552                 }
553         }
554         else if (strcmp("get all", ev->data.b) == 0)
555         {
556 //              print_history_buffer();
557                 pos = get_current_history_position();
558                 for (i = 0; i < 5; i++)
559                 {
560                         DTRACE("## %d -> %d\n", i, pos);
561                         sprintf(atomname, "CBHM_c%d", i);
562                         cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
563                         if (get_item_contents_by_pos(pos) != NULL)
564                         {
565                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String, 
566                                                                 8, PropModeReplace, 
567                                                                 (unsigned char *) get_item_contents_by_pos(pos) , 
568                                                                 (int) strlen(get_item_contents_by_pos(pos)));
569                         }
570                         pos--;
571                         if (pos < 0)
572                                 pos = HISTORY_QUEUE_MAX_TXT_ITEMS-1;
573                 }
574         }
575         else if (strcmp("get raw", ev->data.b) == 0)
576         {
577                 if (get_storage_start_addr != NULL)
578                 {
579                         XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String, 
580                                                         8, PropModeReplace, 
581                                                         (unsigned char *) get_storage_start_addr(),
582                                                         (int) get_total_storage_size());
583                 }
584         }
585         else if (strcmp("show", ev->data.b) == 0)
586         {
587                 clipdrawer_activate_view(ad);
588         }
589
590         XFlush(g_disp);
591
592         return TRUE;
593 }
594
595 static int _xfocus_out_cb(void *data, int ev_type, void *event)
596 {
597         struct appdata *ad = data;
598
599         DTRACE("XE:FOCUS OUT\n");
600
601         clipdrawer_lower_view(ad);
602
603         return TRUE;
604 }
605
606 static Ecore_X_Window get_selection_secondary_target_win()
607 {
608         Atom actual_type;
609         int actual_format;
610         unsigned long nitems, bytes_after;
611         unsigned char *prop_return = NULL;
612         Atom atomCbhmXTarget = XInternAtom(g_disp, "CBHM_XTARGET", False);
613         static Ecore_X_Window xtarget = None;
614         if (xtarget != None)
615                 return xtarget;
616
617         if(Success == 
618            XGetWindowProperty(g_disp, DefaultRootWindow(g_disp), atomCbhmXTarget, 
619                                                   0, sizeof(Ecore_X_Window), False, XA_WINDOW, 
620                                                   &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) && 
621            prop_return)
622         {
623                 xtarget = *(Ecore_X_Window*)prop_return;
624                 XFree(prop_return);
625                 fprintf(stderr, "## find clipboard secondary target at root\n");
626         }
627         return xtarget;
628 }
629
630 int set_selection_secondary_data(char *sdata)
631 {
632         Ecore_X_Window setwin = get_selection_secondary_target_win();
633         if (setwin == None)
634                 return 0;
635
636         if (sdata == NULL)
637                 return 0;
638
639         int slen = strlen(sdata);
640
641         fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
642
643         ecore_x_selection_secondary_set(setwin, sdata, slen);
644 }