3 #include "xcnphandler.h"
5 #include "clipdrawer.h"
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;
13 char *g_lastest_content = NULL;
14 int g_history_pos = 0;
16 int xcnp_init(void *data)
18 struct appdata *ad = data;
19 DTRACE("xcnp_init().. start!\n");
23 DTRACE("Failed - _cbhm_init()..!\n");
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);
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");
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);
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;
68 static int _init_atoms()
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);
85 static void _set_cbhmwin_prop()
87 Atom atomCbhmWin = XInternAtom(g_disp, "CBHM_XWIN", False);
88 XChangeProperty(g_disp, g_rootwin, atomCbhmWin, XA_WINDOW,
90 (unsigned char *)&g_evtwin, (int) 1);
93 int increment_current_history_position()
95 int pos = g_history_pos+1;
96 if (pos >= HISTORY_QUEUE_NUMBER)
102 int get_current_history_position()
104 int pos = g_history_pos-1;
106 pos = HISTORY_QUEUE_NUMBER;
111 int add_to_storage_buffer(void *data, char *src, int len)
113 struct appdata *ad = data;
118 if (g_lastest_content == NULL)
119 g_lastest_content = malloc(sizeof(char)*(4*1024));
120 if (g_history_pos >= HISTORY_QUEUE_NUMBER)
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();
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,
133 (unsigned char *)&nserial, (int) 1);
136 clipdrawer_update_contents(ad);
141 int print_storage_buffer()
145 for (i = 0; i < HISTORY_QUEUE_NUMBER; i++)
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");
154 int send_convert_selection()
156 XConvertSelection(g_disp, atomClipboard, atomUTF8String, atomCBOut, g_evtwin, CurrentTime);
157 DTRACE("sent convert selection\n");
161 int set_clipboard_manager_owner()
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);
169 int set_selection_owner()
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);
177 int get_selection_content(void *data)
181 unsigned long cbsize, cbitems;
182 unsigned char *cbbuf;
183 struct appdata *ad = data;
186 XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, 0, False,
187 AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
190 if (cbtype == atomInc)
192 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
198 DTRACE("cbsize = %d\n", cbsize);
202 DTRACE("There're nothing to read = %d\n", cbformat);
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);
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);
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")))
220 fprintf(stderr, "## clipdrawer add path = %s\n", unesc);
221 clipdrawer_add_image_item(unesc);
224 add_to_storage_buffer(ad, unesc, strlen(unesc));
225 DTRACE("len = %ld, data = %s\n", strlen(unesc), unesc);
229 print_storage_buffer();
237 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
241 Ecore_X_Window req_win;
244 req_size = XExtendedMaxRequestSize(g_disp) / 4;
247 req_size = XMaxRequestSize(g_disp) / 4;
250 req_win = ev->requestor;
251 req_atom = ev->property;
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));
257 /* TODO : if there are request which cbhm doesn't understand,
258 then reply None property to requestor */
259 if (ev->target == atomTargets)
261 // Atom types[2] = { atomTargets, atomUTF8String };
262 Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
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");
272 DTRACE("target mismatched. trying to txt\n");
275 if (g_lastest_content != NULL)
276 txt_len = strlen(g_lastest_content);
280 if (txt_len > req_size)
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);
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);
296 DTRACE("wanted window = 0x%x\n", req_win);
297 DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
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));
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;
311 XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
317 static int _cbhm_init()
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;
325 // do not x init in this module, it disconnect previous e17's X connection
326 //ecore_x_init(NULL);
328 g_disp = ecore_x_display_get();
332 DTRACE("Failed to get display\n");
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);
340 XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
341 // ecore_x_window_show(g_evtwin);
348 DTRACE("_cbhm_init ok\n");
350 set_clipboard_manager_owner();
351 send_convert_selection();
352 set_selection_owner();
357 static void _cbhm_fini()
364 static int _xsel_clear_cb(void *data, int ev_type, void *event)
366 struct appdata *ad = data;
368 Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
370 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
373 DTRACE("XE:SelectionClear\n");
375 send_convert_selection();
377 /* TODO : set selection request is should after convert selection
379 set_selection_owner();
384 static int _xsel_request_cb(void *data, int ev_type, void *event)
386 Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
388 if (ev->selection != atomClipboard)
391 DTRACE("XE:SelectionRequest\n");
393 processing_selection_request(ev);
398 static int _xsel_notify_cb(void *data, int ev_type, void *event)
400 struct appdata *ad = data;
402 Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
403 Ecore_X_Selection_Data_Text *text_data = NULL;
405 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
408 DTRACE("XE:SelectionNotify\n");
410 text_data = ev->data;
411 DTRACE("content type = %d\n", text_data->data.content);
412 get_selection_content(ad);
414 if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
416 DTRACE("content isn't text\n");
422 static int _xclient_msg_cb(void *data, int ev_type, void *event)
424 struct appdata *ad = data;
426 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
428 Atom atomCBHM_MSG = XInternAtom(g_disp, "CBHM_MSG", False);
429 Atom atomCBHM_cRAW = XInternAtom(g_disp, "CBHM_cRAW", False);
431 Atom cbhm_atoms[HISTORY_QUEUE_NUMBER];
432 Ecore_X_Window reqwin = ev->win;
435 if (ev->message_type != atomCBHM_MSG)
438 DTRACE("XE:ClientMessage for CBHM\n");
440 DTRACE("## %s\n", ev->data.b);
442 if (strcmp("get count", ev->data.b) == 0)
444 int icount = get_item_counts();
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,
452 (unsigned char *) countbuf,
453 (int) strlen(countbuf));
456 else if (strncmp("get #", ev->data.b, 5) == 0)
458 // FIXME : handle greater than 9
459 int num = ev->data.b[5] - '0';
460 int cur = get_current_history_position();
462 if (num > HISTORY_QUEUE_NUMBER-1)
463 num = num-HISTORY_QUEUE_NUMBER;
465 if (num >= 0 && num < HISTORY_QUEUE_NUMBER)
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)
473 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
475 (unsigned char *) get_item_contents_by_pos(num),
476 (int) strlen(get_item_contents_by_pos(num)));
480 else if (strcmp("get all", ev->data.b) == 0)
482 // print_history_buffer();
483 pos = get_current_history_position();
484 for (i = 0; i < 5; i++)
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)
491 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
493 (unsigned char *) get_item_contents_by_pos(pos) ,
494 (int) strlen(get_item_contents_by_pos(pos)));
498 pos = HISTORY_QUEUE_NUMBER-1;
501 else if (strcmp("get raw", ev->data.b) == 0)
503 if (get_storage_start_addr != NULL)
505 XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
507 (unsigned char *) get_storage_start_addr(),
508 (int) get_total_storage_size());
511 else if (strcmp("show", ev->data.b) == 0)
513 clipdrawer_activate_view(ad);
521 static int _xfocus_out_cb(void *data, int ev_type, void *event)
523 struct appdata *ad = data;
525 DTRACE("XE:FOCUS OUT\n");
527 clipdrawer_lower_view(ad);
532 static Ecore_X_Window get_selection_secondary_target_win()
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;
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) &&
549 xtarget = *(Ecore_X_Window*)prop_return;
551 fprintf(stderr, "## find clipboard secondary target at root\n");
556 int set_selection_secondary_data(char *sdata)
558 // elm_selection_set(1, obj, /*mark up*/1, p);
559 Ecore_X_Window setwin = get_selection_secondary_target_win();
566 int slen = strlen(sdata);
568 fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
570 ecore_x_selection_secondary_set(setwin, sdata, slen);