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_MAX_TXT_ITEMS)
102 int get_current_history_position()
104 int pos = g_history_pos-1;
106 pos = HISTORY_QUEUE_MAX_TXT_ITEMS-1;
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)*(HISTORY_QUEUE_TXT_ITEM_SIZE));
120 if (g_history_pos >= HISTORY_QUEUE_MAX_TXT_ITEMS)
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();
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,
135 (unsigned char *)&nserial, (int) 1);
138 clipdrawer_update_contents(ad);
143 int print_storage_buffer()
147 for (i = 0; i < HISTORY_QUEUE_MAX_TXT_ITEMS; i++)
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");
156 int send_convert_selection()
158 XConvertSelection(g_disp, atomClipboard, atomUTF8String, atomCBOut, g_evtwin, CurrentTime);
159 DTRACE("sent convert selection\n");
163 int set_clipboard_manager_owner()
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);
171 int set_selection_owner()
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);
179 int get_selection_content(void *data)
183 unsigned long cbsize, cbitems;
184 unsigned char *cbbuf;
185 struct appdata *ad = data;
187 size_t unesc_len = 0;
190 XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, 0, False,
191 AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
194 if (cbtype == atomInc)
196 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
202 DTRACE("cbsize = %d\n", cbsize);
206 DTRACE("There're nothing to read = %d\n", cbformat);
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);
214 unesc = clipdrawer_get_plain_string_from_escaped(cbbuf);
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--)
221 // avoid control characters
222 if (unesc[i] >= 0x01 && unesc[i] <= 0x1F)
226 DTRACE("before right trim len = %d\n", unesc_len);
228 DTRACE("after right trim len = %d\n", unesc_len);
236 // add_to_storage_buffer(ad, cbbuf, cbitems);
237 // DTRACE("len = %ld, data = %s\n", cbitems, cbbuf);
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--)
246 // avoid control characters
247 if (cbbuf[i] >= 0x01 && cbbuf[i] <= 0x1F)
251 DTRACE("before right trim len = %d\n", unesc_len);
253 DTRACE("after right trim len = %d\n", unesc_len);
261 if (!strncmp(cbbuf, "file://", 7) &&
262 (strcasestr(cbbuf,".png") || strcasestr(cbbuf,".jpg") || strcasestr(cbbuf,".bmp")) &&
263 check_regular_file(cbbuf+7))
265 DTRACE("clipdrawer add path = %s\n", cbbuf+7);
266 clipdrawer_add_image_item(cbbuf+7);
269 add_to_storage_buffer(ad, cbbuf, unesc_len);
270 DTRACE("len = %ld, data = %s\n", unesc_len, cbbuf);
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))
281 DTRACE("clipdrawer add path = %s\n", unesc+7);
282 clipdrawer_add_image_item(unesc+7);
285 add_to_storage_buffer(ad, unesc, unesc_len);
286 DTRACE("len = %ld, data = %s\n", unesc_len, unesc);
290 print_storage_buffer();
298 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
302 Ecore_X_Window req_win;
305 req_size = XExtendedMaxRequestSize(g_disp) / 4;
308 req_size = XMaxRequestSize(g_disp) / 4;
311 req_win = ev->requestor;
312 req_atom = ev->property;
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));
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)
323 // Atom types[2] = { atomTargets, atomUTF8String };
324 Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
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");
334 DTRACE("target mismatched. trying to txt\n");
337 if (g_lastest_content != NULL)
338 txt_len = strlen(g_lastest_content);
342 if (txt_len > req_size)
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);
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);
358 DTRACE("wanted window = 0x%x\n", req_win);
359 DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
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));
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;
373 XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
379 static int _cbhm_init(void *data)
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;
388 // do not x init in this module, it disconnect previous e17's X connection
389 //ecore_x_init(NULL);
391 g_disp = ecore_x_display_get();
395 DTRACE("Failed to get display\n");
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);
403 XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
404 XSelectInput(g_disp, g_rootwin, StructureNotifyMask);
405 // ecore_x_window_show(g_evtwin);
412 DTRACE("_cbhm_init ok\n");
414 set_clipboard_manager_owner();
415 send_convert_selection();
416 set_selection_owner();
421 static void _cbhm_fini()
428 static int _xsel_clear_cb(void *data, int ev_type, void *event)
430 struct appdata *ad = data;
432 Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
434 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
437 DTRACE("XE:SelectionClear\n");
439 send_convert_selection();
441 /* TODO : set selection request is should after convert selection
443 set_selection_owner();
448 static int _xsel_request_cb(void *data, int ev_type, void *event)
450 Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
452 if (ev->selection != atomClipboard)
455 DTRACE("XE:SelectionRequest\n");
457 processing_selection_request(ev);
462 static int _xsel_notify_cb(void *data, int ev_type, void *event)
464 struct appdata *ad = data;
466 Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
467 Ecore_X_Selection_Data_Text *text_data = NULL;
469 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
472 DTRACE("XE:SelectionNotify\n");
474 text_data = ev->data;
475 DTRACE("content type = %d\n", text_data->data.content);
476 get_selection_content(ad);
478 if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
480 DTRACE("content isn't text\n");
486 static int _xclient_msg_cb(void *data, int ev_type, void *event)
488 struct appdata *ad = data;
490 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
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);
496 Atom cbhm_atoms[HISTORY_QUEUE_MAX_TXT_ITEMS];
497 Ecore_X_Window reqwin = ev->win;
500 if (ev->message_type == atomXKey_MSG)
502 DTRACE("XE:ClientMessage for Screen capture\n");
504 capture_current_screen(ad);
509 if (ev->message_type != atomCBHM_MSG)
512 DTRACE("XE:ClientMessage for CBHM\n");
514 DTRACE("## %s\n", ev->data.b);
516 if (strcmp("get count", ev->data.b) == 0)
518 int icount = get_item_counts();
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,
526 (unsigned char *) countbuf,
527 (int) strlen(countbuf));
530 else if (strncmp("get #", ev->data.b, 5) == 0)
532 // FIXME : handle greater than 9
533 int num = ev->data.b[5] - '0';
534 int cur = get_current_history_position();
536 if (num > HISTORY_QUEUE_MAX_TXT_ITEMS-1)
537 num = num-HISTORY_QUEUE_MAX_TXT_ITEMS;
539 if (num >= 0 && num < HISTORY_QUEUE_MAX_TXT_ITEMS)
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)
547 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
549 (unsigned char *) get_item_contents_by_pos(num),
550 (int) strlen(get_item_contents_by_pos(num)));
554 else if (strcmp("get all", ev->data.b) == 0)
556 // print_history_buffer();
557 pos = get_current_history_position();
558 for (i = 0; i < 5; i++)
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)
565 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
567 (unsigned char *) get_item_contents_by_pos(pos) ,
568 (int) strlen(get_item_contents_by_pos(pos)));
572 pos = HISTORY_QUEUE_MAX_TXT_ITEMS-1;
575 else if (strcmp("get raw", ev->data.b) == 0)
577 if (get_storage_start_addr != NULL)
579 XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
581 (unsigned char *) get_storage_start_addr(),
582 (int) get_total_storage_size());
585 else if (strcmp("show", ev->data.b) == 0)
587 clipdrawer_activate_view(ad);
595 static int _xfocus_out_cb(void *data, int ev_type, void *event)
597 struct appdata *ad = data;
599 DTRACE("XE:FOCUS OUT\n");
601 clipdrawer_lower_view(ad);
606 static Ecore_X_Window get_selection_secondary_target_win()
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;
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) &&
623 xtarget = *(Ecore_X_Window*)prop_return;
625 fprintf(stderr, "## find clipboard secondary target at root\n");
630 int set_selection_secondary_data(char *sdata)
632 Ecore_X_Window setwin = get_selection_secondary_target_win();
639 int slen = strlen(sdata);
641 fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
643 ecore_x_selection_secondary_set(setwin, sdata, slen);