code clean up
[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())
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_NUMBER)
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_NUMBER;
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)*(4*1024));
120         if (g_history_pos >= HISTORY_QUEUE_NUMBER)
121                 g_history_pos = 0;
122
123         // FIXME: remove g_lasteset_content
124         strcpy(g_lastest_content, src);
125         adding_item_to_storage(g_history_pos, g_lastest_content);
126         increment_current_history_position();
127
128         int nserial = 0;
129         nserial = get_storage_serial_code();
130         Atom atomCbhmSerial = XInternAtom(g_disp, "CBHM_SERIAL_NUMBER", False);
131         XChangeProperty(g_disp, g_evtwin, atomCbhmSerial, XA_INTEGER,
132                                         32, PropModeReplace,
133                                         (unsigned char *)&nserial, (int) 1);
134         XFlush(g_disp);
135
136         clipdrawer_update_contents(ad);
137
138         return 0;
139 }
140
141 int print_storage_buffer()
142 {
143         int pos;
144         int i = 0;
145         for (i = 0; i < HISTORY_QUEUE_NUMBER; i++)
146         {
147                 pos = get_current_history_position()+i;
148                 if (pos > HISTORY_QUEUE_NUMBER-1)
149                         pos = pos-HISTORY_QUEUE_NUMBER;
150                 DTRACE("%d: %s\n", i, get_item_contents_by_pos(pos) != NULL ? get_item_contents_by_pos(pos) : "NULL");
151         }
152 }
153
154 int send_convert_selection()
155 {
156         XConvertSelection(g_disp, atomClipboard, atomUTF8String, atomCBOut, g_evtwin, CurrentTime);
157         DTRACE("sent convert selection\n");
158         return 0;
159 }
160
161 int set_clipboard_manager_owner()
162 {
163         XSetSelectionOwner(g_disp, atomCBHM, g_evtwin, CurrentTime);
164         Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomCBHM);
165         DTRACE("g_evtwin = 0x%x, setted clipboard manager owner is = 0x%x\n", g_evtwin, selowner_window);
166         return 0;
167 }
168
169 int set_selection_owner()
170 {
171         XSetSelectionOwner(g_disp, atomClipboard, g_evtwin, CurrentTime);
172         Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomClipboard);
173         DTRACE("evtwin = 0x%x, setted selection owner is = 0x%x\n", g_evtwin, selowner_window);
174         return 0;
175 }
176
177 int get_selection_content(void *data)
178 {
179         Atom cbtype;
180         int cbformat;
181         unsigned long cbsize, cbitems;
182         unsigned char *cbbuf;
183         struct appdata *ad = data;
184         const char *unesc;
185
186         XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, 0, False,
187                                            AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
188         XFree(cbbuf);
189
190         if (cbtype == atomInc)
191         {
192                 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
193                 XFlush(g_disp);
194                 DTRACE("INCR \n");
195                 return -1;
196         }
197
198         DTRACE("cbsize = %d\n", cbsize);
199
200         if (cbformat != 8)
201         {
202                 DTRACE("There're nothing to read = %d\n", cbformat);
203                 return -2;
204         }
205
206         XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, (long) cbsize, False,
207                                            AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
208         XDeleteProperty(g_disp, g_evtwin, atomCBOut);
209
210         unesc = clipdrawer_get_plain_string_from_escaped(cbbuf);
211 //      add_to_storage_buffer(ad, cbbuf, cbitems);
212 //      DTRACE("len = %ld, data = %s\n", cbitems, cbbuf);
213
214         /* FIXME : it needs two verification. 
215                1. does the file exist?
216                2. dose the file wanted type? */
217         if (!strncmp(unesc, "file://", 7) && 
218                 (strstr(unesc,".png") || strstr(unesc,".jpg")))
219         {
220                 fprintf(stderr, "## clipdrawer add path = %s\n", unesc);
221                 clipdrawer_add_image_item(unesc);
222         }
223         else
224                 add_to_storage_buffer(ad, unesc, strlen(unesc));
225         DTRACE("len = %ld, data = %s\n", strlen(unesc), unesc);
226         free(unesc);
227
228         DTRACE("\n");
229         print_storage_buffer();
230         DTRACE("\n");
231
232         XFree(cbbuf);
233
234         return 0;
235 }
236
237 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
238 {
239         XEvent req_evt;
240         int req_size;
241         Ecore_X_Window req_win;
242         Atom req_atom;
243
244         req_size = XExtendedMaxRequestSize(g_disp) / 4;
245         if (!req_size)
246         {
247                 req_size = XMaxRequestSize(g_disp) / 4;
248         }
249
250     req_win = ev->requestor;
251         req_atom = ev->property;
252
253         DTRACE("## wanted target = %d\n", ev->target);
254         DTRACE("## wanted target = %s\n", XGetAtomName(g_disp, ev->target));
255         DTRACE("## req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
256
257         /* TODO : if there are request which cbhm doesn't understand,
258            then reply None property to requestor */
259         if (ev->target == atomTargets) 
260         {
261 //        Atom types[2] = { atomTargets, atomUTF8String };
262         Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
263
264         // send all (not using INCR) 
265         XChangeProperty(g_disp, req_win, req_atom, XA_ATOM,
266                                                 32, PropModeReplace, (unsigned char *) types,
267                                                 (int) (sizeof(types) / sizeof(Atom)));
268                 DTRACE("target matched\n");
269     }
270     else
271         {
272                 DTRACE("target mismatched. trying to txt\n");
273
274                 int txt_len;
275                 if (g_lastest_content != NULL)
276                         txt_len = strlen(g_lastest_content);
277                 else
278                         txt_len = 0;
279
280                 if (txt_len > req_size) 
281                 {
282                         // INCR 
283                 }
284                 else 
285                 {
286                         // send all (not using INCR) 
287                         XChangeProperty(g_disp, req_win, req_atom, atomUTF8String, 
288                                                         8, PropModeReplace, (unsigned char *) g_lastest_content, (int) txt_len);
289                 }
290                 DTRACE("txt target, len = %d\n", txt_len);
291                 if (txt_len > 0 && g_lastest_content != NULL)
292                         DTRACE("txt target, content = %s\n", g_lastest_content);
293         }
294
295 /*
296         DTRACE("wanted window = 0x%x\n", req_win);
297         DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
298 */
299         DTRACE("selection target = %s\n", XGetAtomName(g_disp, ev->selection));
300         DTRACE("getted atom name = %s\n", XGetAtomName(g_disp, req_atom));
301         DTRACE("req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
302
303     req_evt.xselection.property = req_atom;
304     req_evt.xselection.type = SelectionNotify;
305     req_evt.xselection.display = g_disp;
306     req_evt.xselection.requestor = req_win;
307     req_evt.xselection.selection = ev->selection;
308     req_evt.xselection.target = ev->target;
309     req_evt.xselection.time = ev->time;
310
311     XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
312     XFlush(g_disp);
313
314         return 0;
315 }
316
317 static int _cbhm_init()
318 {
319         //Set default data structure
320         //Control that the libraries are properly initialized
321         if (!ecore_init()) return EXIT_FAILURE;
322         if (!ecore_evas_init()) return EXIT_FAILURE;
323         if (!edje_init()) return EXIT_FAILURE;
324
325         // do not x init in this module, it disconnect previous e17's X connection
326         //ecore_x_init(NULL);
327
328         g_disp = ecore_x_display_get();
329
330         if( !g_disp )
331         {
332                 DTRACE("Failed to get display\n");
333                 return -1;
334         }
335
336         g_rootwin = DefaultRootWindow(g_disp);
337         g_evtwin = ecore_x_window_new(g_rootwin, 0, 0, 19, 19);
338         ecore_x_netwm_name_set(g_evtwin, CLIPBOARD_MANAGER_WINDOW_TITLE_STRING);
339
340         XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
341 //      ecore_x_window_show(g_evtwin);
342         ecore_x_flush();
343
344         _set_cbhmwin_prop();
345     _init_atoms();
346         init_storage();
347
348         DTRACE("_cbhm_init ok\n");
349
350         set_clipboard_manager_owner();
351         send_convert_selection();
352         set_selection_owner();
353
354         return TRUE;
355 }
356
357 static void _cbhm_fini()
358 {
359         close_storage();
360
361         return;
362 }
363
364 static int _xsel_clear_cb(void *data, int ev_type, void *event)
365 {
366         struct appdata *ad = data;
367
368         Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
369
370         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
371                 return TRUE;
372         
373         DTRACE("XE:SelectionClear\n");
374
375         send_convert_selection();
376         ecore_x_flush();
377         /* TODO : set selection request is should after convert selection
378          * is done */
379         set_selection_owner();
380
381         return TRUE;
382 }
383
384 static int _xsel_request_cb(void *data, int ev_type, void *event)
385 {
386         Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
387
388         if (ev->selection != atomClipboard)
389                 return TRUE;
390
391         DTRACE("XE:SelectionRequest\n");
392
393         processing_selection_request(ev);
394
395         return TRUE;
396 }
397
398 static int _xsel_notify_cb(void *data, int ev_type, void *event)
399 {
400         struct appdata *ad = data;
401
402         Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
403         Ecore_X_Selection_Data_Text *text_data = NULL;
404
405         if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
406                 return TRUE;
407         
408         DTRACE("XE:SelectionNotify\n");
409
410         text_data = ev->data;
411         DTRACE("content type = %d\n", text_data->data.content);
412         get_selection_content(ad);
413
414         if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
415         {
416                 DTRACE("content isn't text\n");
417         }
418
419         return TRUE;
420 }
421
422 static int _xclient_msg_cb(void *data, int ev_type, void *event)
423 {
424         struct appdata *ad = data;
425
426         Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
427
428         Atom atomCBHM_MSG = XInternAtom(g_disp, "CBHM_MSG", False);
429         Atom atomCBHM_cRAW = XInternAtom(g_disp, "CBHM_cRAW", False);
430         char atomname[10];
431         Atom cbhm_atoms[HISTORY_QUEUE_NUMBER];
432         Ecore_X_Window reqwin = ev->win;
433         int i, pos;
434
435         if (ev->message_type != atomCBHM_MSG)
436                 return -1;
437
438         DTRACE("XE:ClientMessage for CBHM\n");
439
440         DTRACE("## %s\n", ev->data.b);
441
442         if (strcmp("get count", ev->data.b) == 0)
443         {
444                 int icount = get_item_counts();
445                 char countbuf[10];
446                 DTRACE("## cbhm count : %d\n", icount);
447                 sprintf(countbuf, "%d", icount);
448                 sprintf(atomname, "CBHM_cCOUNT");
449                 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
450                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String, 
451                                                 8, PropModeReplace, 
452                                                 (unsigned char *) countbuf, 
453                                                 (int) strlen(countbuf));
454         
455         }
456         else if (strncmp("get #", ev->data.b, 5) == 0)
457         {
458                 // FIXME : handle greater than 9
459                 int num = ev->data.b[5] - '0';
460                 int cur = get_current_history_position();
461                 num = cur + num - 1;
462                 if (num > HISTORY_QUEUE_NUMBER-1)
463                         num = num-HISTORY_QUEUE_NUMBER;
464
465                 if (num >= 0 && num < HISTORY_QUEUE_NUMBER)
466                 {
467                         DTRACE("## pos : #%d\n", num);
468                         // FIXME : handle with correct atom
469                         sprintf(atomname, "CBHM_c%d", num);
470                         cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
471                         if (get_item_contents_by_pos(num) != NULL)
472                         {
473                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String, 
474                                                                 8, PropModeReplace, 
475                                                                 (unsigned char *) get_item_contents_by_pos(num), 
476                                                                 (int) strlen(get_item_contents_by_pos(num)));
477                         }
478                 }
479         }
480         else if (strcmp("get all", ev->data.b) == 0)
481         {
482 //              print_history_buffer();
483                 pos = get_current_history_position();
484                 for (i = 0; i < 5; i++)
485                 {
486                         DTRACE("## %d -> %d\n", i, pos);
487                         sprintf(atomname, "CBHM_c%d", i);
488                         cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
489                         if (get_item_contents_by_pos(pos) != NULL)
490                         {
491                                 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String, 
492                                                                 8, PropModeReplace, 
493                                                                 (unsigned char *) get_item_contents_by_pos(pos) , 
494                                                                 (int) strlen(get_item_contents_by_pos(pos)));
495                         }
496                         pos--;
497                         if (pos < 0)
498                                 pos = HISTORY_QUEUE_NUMBER-1;
499                 }
500         }
501         else if (strcmp("get raw", ev->data.b) == 0)
502         {
503                 if (get_storage_start_addr != NULL)
504                 {
505                         XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String, 
506                                                         8, PropModeReplace, 
507                                                         (unsigned char *) get_storage_start_addr(),
508                                                         (int) get_total_storage_size());
509                 }
510         }
511         else if (strcmp("show", ev->data.b) == 0)
512         {
513                 clipdrawer_activate_view(ad);
514         }
515
516         XFlush(g_disp);
517
518         return TRUE;
519 }
520
521 static int _xfocus_out_cb(void *data, int ev_type, void *event)
522 {
523         struct appdata *ad = data;
524
525         DTRACE("XE:FOCUS OUT\n");
526
527         clipdrawer_lower_view(ad);
528
529         return TRUE;
530 }
531
532 static Ecore_X_Window get_selection_secondary_target_win()
533 {
534         Atom actual_type;
535         int actual_format;
536         unsigned long nitems, bytes_after;
537         unsigned char *prop_return = NULL;
538         Atom atomCbhmXTarget = XInternAtom(g_disp, "CBHM_XTARGET", False);
539         static Ecore_X_Window xtarget = None;
540         if (xtarget != None)
541                 return xtarget;
542
543         if(Success == 
544            XGetWindowProperty(g_disp, DefaultRootWindow(g_disp), atomCbhmXTarget, 
545                                                   0, sizeof(Ecore_X_Window), False, XA_WINDOW, 
546                                                   &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) && 
547            prop_return)
548         {
549                 xtarget = *(Ecore_X_Window*)prop_return;
550                 XFree(prop_return);
551                 fprintf(stderr, "## find clipboard secondary target at root\n");
552         }
553         return xtarget;
554 }
555
556 int set_selection_secondary_data(char *sdata)
557 {
558 //      elm_selection_set(1, obj, /*mark up*/1, p);
559         Ecore_X_Window setwin = get_selection_secondary_target_win();
560         if (setwin == None)
561                 return 0;
562
563         if (sdata == NULL)
564                 return 0;
565
566         int slen = strlen(sdata);
567
568         fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
569
570         ecore_x_selection_secondary_set(setwin, sdata, slen);
571 }