3 #include "xcnphandler.h"
5 #include "clipdrawer.h"
6 #include "scrcapture.h"
8 static Ecore_Event_Handler *xsel_clear_handler = NULL;
9 static Ecore_Event_Handler *xsel_request_handler = NULL;
10 static Ecore_Event_Handler *xsel_notify_handler = NULL;
11 static Ecore_Event_Handler *xclient_msg_handler = NULL;
12 static Ecore_Event_Handler *xfocus_out_handler = NULL;
14 char *g_lastest_content = NULL;
15 int g_history_pos = 0;
17 int xcnp_init(void *data)
19 struct appdata *ad = data;
20 DTRACE("xcnp_init().. start!\n");
24 DTRACE("Failed - _cbhm_init()..!\n");
28 //Adding Event Handlers
29 xsel_clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _xsel_clear_cb, ad);
30 xsel_request_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, _xsel_request_cb, ad);
31 xsel_notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _xsel_notify_cb, ad);
32 xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _xclient_msg_cb, ad);
33 xfocus_out_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _xfocus_out_cb, ad);
35 if(!xsel_clear_handler)
36 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_CLEAR handler\n");
37 if(!xsel_request_handler)
38 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_REQUEST handler\n");
39 if(!xsel_notify_handler)
40 DTRACE("Failed to add ECORE_X_EVENT_SELECTION_NOTIFY handler\n");
41 if(!xclient_msg_handler)
42 DTRACE("Failed to add ECORE_X_EVENT_CLIENT_MESSAGE handler\n");
43 if(!xfocus_out_handler)
44 DTRACE("Failed to add ECORE_X_EVENT_WINDOW_FOCUS_OUT handler\n");
51 //Removing Event Handlers
52 ecore_event_handler_del(xsel_clear_handler);
53 ecore_event_handler_del(xsel_request_handler);
54 ecore_event_handler_del(xsel_notify_handler);
55 ecore_event_handler_del(xclient_msg_handler);
56 ecore_event_handler_del(xfocus_out_handler);
58 xsel_clear_handler = NULL;
59 xsel_request_handler = NULL;
60 xsel_notify_handler = NULL;
61 xclient_msg_handler = NULL;
62 xfocus_out_handler = NULL;
69 static int _init_atoms()
71 /* all atoms are global variables */
72 atomPrimary = XA_PRIMARY;
73 atomSecondary = XA_SECONDARY;
74 // atomTarget = XA_STRING;
75 atomClipboard = XInternAtom(g_disp, ATOM_CLIPBOARD_NAME, False);
76 atomCBHM = XInternAtom (g_disp, ATOM_CLIPBOARD_MANAGER_NAME, False);
77 atomCBOut = XInternAtom(g_disp, ATOM_CBHM_OUTBUF, False);
78 atomInc = XInternAtom(g_disp, "INCR", False);
79 atomTargets = XInternAtom(g_disp, "TARGETS", False);
80 atomUTF8String = XInternAtom(g_disp, "UTF8_STRING", False);
81 atomHtmltext = XInternAtom(g_disp, "text/html;charset=utf-8", False);
86 static void _set_cbhmwin_prop()
88 Atom atomCbhmWin = XInternAtom(g_disp, "CBHM_XWIN", False);
89 XChangeProperty(g_disp, g_rootwin, atomCbhmWin, XA_WINDOW,
91 (unsigned char *)&g_evtwin, (int) 1);
94 int increment_current_history_position()
96 int pos = g_history_pos+1;
97 if (pos >= HISTORY_QUEUE_MAX_ITEMS)
103 int get_current_history_position()
105 int pos = g_history_pos-1;
107 pos = HISTORY_QUEUE_MAX_ITEMS-1;
112 int add_to_storage_buffer(void *data, char *src, int len)
114 struct appdata *ad = data;
119 if (g_lastest_content != NULL)
120 free(g_lastest_content);
121 g_lastest_content = malloc(sizeof(char)*(len+1));
122 if (g_history_pos >= HISTORY_QUEUE_MAX_ITEMS)
125 // FIXME: remove g_lasteset_content
126 memcpy(g_lastest_content, src, len);
127 g_lastest_content[len] = '\0';
128 adding_item_to_storage(ad, g_history_pos, g_lastest_content);
129 increment_current_history_position();
132 nserial = get_storage_serial_code(ad);
133 Atom atomCbhmSerial = XInternAtom(g_disp, "CBHM_SERIAL_NUMBER", False);
134 XChangeProperty(g_disp, g_evtwin, atomCbhmSerial, XA_INTEGER,
136 (unsigned char *)&nserial, (int) 1);
142 int print_storage_buffer(void *data)
144 struct appdata *ad = data;
148 for (i = 0; i < HISTORY_QUEUE_MAX_ITEMS; i++)
150 pos = get_current_history_position()+i;
151 if (pos > HISTORY_QUEUE_MAX_ITEMS-1)
152 pos = pos-HISTORY_QUEUE_MAX_ITEMS;
153 DTRACE("%d: %s\n", i,
154 clipdrawer_get_item_data(ad, pos) != NULL ? clipdrawer_get_item_data(ad, pos) : "NULL");
158 int send_convert_selection()
160 XConvertSelection(g_disp, atomClipboard, atomUTF8String, atomCBOut, g_evtwin, CurrentTime);
161 DTRACE("sent convert selection\n");
165 int set_clipboard_manager_owner()
167 XSetSelectionOwner(g_disp, atomCBHM, g_evtwin, CurrentTime);
168 Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomCBHM);
169 DTRACE("g_evtwin = 0x%x, setted clipboard manager owner is = 0x%x\n", g_evtwin, selowner_window);
173 int set_selection_owner()
175 XSetSelectionOwner(g_disp, atomClipboard, g_evtwin, CurrentTime);
176 Ecore_X_Window selowner_window = XGetSelectionOwner(g_disp, atomClipboard);
177 DTRACE("evtwin = 0x%x, setted selection owner is = 0x%x\n", g_evtwin, selowner_window);
181 int get_selection_content(void *data)
185 unsigned long cbsize, cbitems;
186 unsigned char *cbbuf;
187 struct appdata *ad = data;
189 size_t unesc_len = 0;
192 XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, 0, False,
193 AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
196 if (cbtype == atomInc)
198 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
204 DTRACE("cbsize = %d\n", cbsize);
208 DTRACE("There're nothing to read = %d\n", cbformat);
212 XGetWindowProperty(g_disp, g_evtwin, atomCBOut, 0, (long) cbsize, False,
213 AnyPropertyType, &cbtype, &cbformat, &cbitems, &cbsize, &cbbuf);
214 XDeleteProperty(g_disp, g_evtwin, atomCBOut);
218 unesc = clipdrawer_get_plain_string_from_escaped(cbbuf);
221 unesc_len = strlen(unesc);
222 // FIXME: invent more clever way to right trim the string
223 for (i = unesc_len-1; i > 0; i--)
225 // avoid control characters
226 if (unesc[i] >= 0x01 && unesc[i] <= 0x1F)
230 DTRACE("before right trim len = %d\n", unesc_len);
232 DTRACE("after right trim len = %d\n", unesc_len);
243 DTRACE("len = %ld, data = %s\n", cbitems, cbbuf);
247 unesc_len = strlen(cbbuf);
248 // FIXME: invent more clever way to right trim the string
249 for (i = unesc_len-1; i > 0; i--)
251 // avoid control characters
252 if (cbbuf[i] >= 0x01 && cbbuf[i] <= 0x1F)
256 DTRACE("before right trim len = %d\n", unesc_len);
258 DTRACE("after right trim len = %d\n", unesc_len);
266 if (!strncmp(cbbuf, "file://", 7) &&
267 (strcasestr(cbbuf,".png") || strcasestr(cbbuf,".jpg") || strcasestr(cbbuf,".bmp")) &&
268 check_regular_file(cbbuf+7))
270 DTRACE("clipdrawer add path = %s\n", cbbuf+7);
271 clipdrawer_add_item(ad, cbbuf+7, GI_IMAGE);
275 add_to_storage_buffer(ad, cbbuf, unesc_len);
276 clipdrawer_add_item(ad, cbbuf, GI_TEXT);
278 DTRACE("len = %ld, data = %s\n", unesc_len, cbbuf);
282 /* FIXME : it needs two verification.
283 1. does the file exist?
284 2. dose the file wanted type? */
285 if (!strncmp(unesc, "file://", 7) &&
286 (strcasestr(unesc,".png") || strcasestr(unesc,".jpg") || strcasestr(unesc,".bmp")) &&
287 check_regular_file(unesc+7))
289 DTRACE("clipdrawer add path = %s\n", unesc+7);
290 clipdrawer_add_item(unesc+7, GI_IMAGE);
294 DTRACE("clipdrawer add string = %s\n", unesc);
295 add_to_storage_buffer(ad, unesc, unesc_len);
296 clipdrawer_add_item(unesc, GI_TEXT);
298 DTRACE("len = %ld, data = %s\n", unesc_len, unesc);
303 print_storage_buffer(ad);
311 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
315 Ecore_X_Window req_win;
318 req_size = XExtendedMaxRequestSize(g_disp) / 4;
321 req_size = XMaxRequestSize(g_disp) / 4;
324 req_win = ev->requestor;
325 req_atom = ev->property;
327 DTRACE("## wanted target = %d\n", ev->target);
328 DTRACE("## wanted target = %s\n", XGetAtomName(g_disp, ev->target));
329 DTRACE("## req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
331 /* TODO : if there are request which cbhm doesn't understand,
332 then reply None property to requestor */
333 /* TODO : add image type */
334 if (ev->target == atomTargets)
336 // Atom types[2] = { atomTargets, atomUTF8String };
337 Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
339 // send all (not using INCR)
340 XChangeProperty(g_disp, req_win, req_atom, XA_ATOM,
341 32, PropModeReplace, (unsigned char *) types,
342 (int) (sizeof(types) / sizeof(Atom)));
343 DTRACE("target matched\n");
347 DTRACE("target mismatched. trying to txt\n");
350 if (g_lastest_content != NULL)
351 txt_len = strlen(g_lastest_content);
355 if (txt_len > req_size)
361 // send all (not using INCR)
362 XChangeProperty(g_disp, req_win, req_atom, atomUTF8String,
363 8, PropModeReplace, (unsigned char *) g_lastest_content, (int) txt_len);
365 DTRACE("txt target, len = %d\n", txt_len);
366 if (txt_len > 0 && g_lastest_content != NULL)
367 DTRACE("txt target, content = %s\n", g_lastest_content);
371 DTRACE("wanted window = 0x%x\n", req_win);
372 DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
374 DTRACE("selection target = %s\n", XGetAtomName(g_disp, ev->selection));
375 DTRACE("getted atom name = %s\n", XGetAtomName(g_disp, req_atom));
376 DTRACE("req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
378 req_evt.xselection.property = req_atom;
379 req_evt.xselection.type = SelectionNotify;
380 req_evt.xselection.display = g_disp;
381 req_evt.xselection.requestor = req_win;
382 req_evt.xselection.selection = ev->selection;
383 req_evt.xselection.target = ev->target;
384 req_evt.xselection.time = ev->time;
386 XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
392 static int _cbhm_init(void *data)
394 struct appdata *ad = data;
395 //Set default data structure
396 //Control that the libraries are properly initialized
397 if (!ecore_init()) return EXIT_FAILURE;
398 if (!ecore_evas_init()) return EXIT_FAILURE;
399 if (!edje_init()) return EXIT_FAILURE;
401 // do not x init in this module, it disconnect previous e17's X connection
402 //ecore_x_init(NULL);
404 g_disp = ecore_x_display_get();
408 DTRACE("Failed to get display\n");
412 g_rootwin = DefaultRootWindow(g_disp);
413 g_evtwin = ecore_x_window_new(g_rootwin, 0, 0, 19, 19);
414 ecore_x_netwm_name_set(g_evtwin, CLIPBOARD_MANAGER_WINDOW_TITLE_STRING);
416 XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
417 XSelectInput(g_disp, g_rootwin, StructureNotifyMask);
418 // ecore_x_window_show(g_evtwin);
425 DTRACE("_cbhm_init ok\n");
427 set_clipboard_manager_owner();
428 send_convert_selection();
429 set_selection_owner();
434 static void _cbhm_fini()
436 struct appdata *ad = g_get_main_appdata();
443 static int _xsel_clear_cb(void *data, int ev_type, void *event)
445 struct appdata *ad = data;
447 Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
449 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
452 DTRACE("XE:SelectionClear\n");
454 send_convert_selection();
456 /* TODO : set selection request is should after convert selection
458 set_selection_owner();
463 static int _xsel_request_cb(void *data, int ev_type, void *event)
465 Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
467 if (ev->selection != atomClipboard)
470 DTRACE("XE:SelectionRequest\n");
472 processing_selection_request(ev);
477 static int _xsel_notify_cb(void *data, int ev_type, void *event)
479 struct appdata *ad = data;
481 Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
482 Ecore_X_Selection_Data_Text *text_data = NULL;
484 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
487 DTRACE("XE:SelectionNotify\n");
489 text_data = ev->data;
490 DTRACE("content type = %d\n", text_data->data.content);
491 get_selection_content(ad);
493 if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
495 DTRACE("content isn't text\n");
501 static int _xclient_msg_cb(void *data, int ev_type, void *event)
503 struct appdata *ad = data;
505 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
507 Atom atomCBHM_MSG = XInternAtom(g_disp, "CBHM_MSG", False);
508 Atom atomCBHM_cRAW = XInternAtom(g_disp, "CBHM_cRAW", False);
509 Atom atomXKey_MSG = XInternAtom(g_disp, "_XKEY_COMPOSITION", False);
511 Atom cbhm_atoms[HISTORY_QUEUE_MAX_ITEMS];
512 Ecore_X_Window reqwin = ev->win;
515 if (ev->message_type == atomXKey_MSG)
517 DTRACE("XE:ClientMessage for Screen capture\n");
519 capture_current_screen(ad);
524 if (ev->message_type != atomCBHM_MSG)
527 DTRACE("XE:ClientMessage for CBHM\n");
529 DTRACE("## %s\n", ev->data.b);
531 if (strcmp("get count", ev->data.b) == 0)
533 int icount = get_item_counts(ad);
535 DTRACE("## cbhm count : %d\n", icount);
536 sprintf(countbuf, "%d", icount);
537 sprintf(atomname, "CBHM_cCOUNT");
538 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
539 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
541 (unsigned char *) countbuf,
542 (int) strlen(countbuf));
545 else if (strncmp("get #", ev->data.b, 5) == 0)
547 // FIXME : handle greater than 9
548 int num = ev->data.b[5] - '0';
549 int cur = get_current_history_position();
551 if (num > HISTORY_QUEUE_MAX_ITEMS-1)
552 num = num-HISTORY_QUEUE_MAX_ITEMS;
554 if (num >= 0 && num < HISTORY_QUEUE_MAX_ITEMS)
556 DTRACE("## pos : #%d\n", num);
557 // FIXME : handle with correct atom
558 sprintf(atomname, "CBHM_c%d", num);
559 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
560 if (clipdrawer_get_item_data(ad, num) != NULL)
562 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
564 (unsigned char *) clipdrawer_get_item_data(ad, num),
565 (int) strlen(clipdrawer_get_item_data(ad, num)));
569 else if (strcmp("get all", ev->data.b) == 0)
571 // print_history_buffer();
572 pos = get_current_history_position();
573 for (i = 0; i < 5; i++)
575 DTRACE("## %d -> %d\n", i, pos);
576 sprintf(atomname, "CBHM_c%d", i);
577 cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
578 if (clipdrawer_get_item_data(ad, pos) != NULL)
580 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
582 (unsigned char *) clipdrawer_get_item_data(ad, pos),
583 (int) strlen(clipdrawer_get_item_data(ad, pos)));
587 pos = HISTORY_QUEUE_MAX_ITEMS-1;
590 else if (strcmp("get raw", ev->data.b) == 0)
593 if (get_storage_start_addr != NULL)
595 XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
597 (unsigned char *) get_storage_start_addr(),
598 (int) get_total_storage_size());
602 else if (strncmp("show", ev->data.b, 4) == 0)
604 if (ev->data.b[4] != NULL && ev->data.b[4] == '1')
605 clipdrawer_paste_textonly_set(ad, EINA_FALSE);
607 clipdrawer_paste_textonly_set(ad, EINA_TRUE);
609 clipdrawer_activate_view(ad);
617 static int _xfocus_out_cb(void *data, int ev_type, void *event)
619 struct appdata *ad = data;
621 DTRACE("XE:FOCUS OUT\n");
623 clipdrawer_lower_view(ad);
628 void set_transient_for(void *data)
630 struct appdata *ad = data;
632 Ecore_X_Window xwin_active = None;
633 Atom atomActive = XInternAtom(g_disp, "_NET_ACTIVE_WINDOW", False);
635 if (ecore_x_window_prop_window_get(DefaultRootWindow(g_disp),
636 atomActive, &xwin_active, 1) != -1)
638 ecore_x_icccm_transient_for_set (elm_win_xwindow_get(ad->win_main), xwin_active);
639 DTRACE("Success to set transient_for active window = 0x%X\n", xwin_active);
643 DTRACE("Failed to find active window for transient_for\n");
647 void unset_transient_for(void *data)
649 struct appdata *ad = data;
651 ecore_x_icccm_transient_for_unset(elm_win_xwindow_get(ad->win_main));
654 static Ecore_X_Window get_selection_secondary_target_win()
658 unsigned long nitems, bytes_after;
659 unsigned char *prop_return = NULL;
660 Atom atomCbhmXTarget = XInternAtom(g_disp, "CBHM_XTARGET", False);
661 static Ecore_X_Window xtarget = None;
666 XGetWindowProperty(g_disp, DefaultRootWindow(g_disp), atomCbhmXTarget,
667 0, sizeof(Ecore_X_Window), False, XA_WINDOW,
668 &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) &&
671 xtarget = *(Ecore_X_Window*)prop_return;
673 fprintf(stderr, "## find clipboard secondary target at root\n");
678 int set_selection_secondary_data(char *sdata)
680 Ecore_X_Window setwin = get_selection_secondary_target_win();
687 int slen = strlen(sdata);
689 fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
691 ecore_x_selection_secondary_set(setwin, sdata, slen);