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_ITEMS)
102 int get_current_history_position()
104 int pos = g_history_pos-1;
106 pos = HISTORY_QUEUE_MAX_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_ITEM_SIZE));
120 if (g_history_pos >= HISTORY_QUEUE_MAX_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_ITEMS; i++)
149 pos = get_current_history_position()+i;
150 if (pos > HISTORY_QUEUE_MAX_ITEMS-1)
151 pos = pos-HISTORY_QUEUE_MAX_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_item(cbbuf+7, GI_IMAGE);
270 add_to_storage_buffer(ad, cbbuf, unesc_len);
271 clipdrawer_add_item(cbbuf, GI_TEXT);
273 DTRACE("len = %ld, data = %s\n", unesc_len, cbbuf);
277 /* FIXME : it needs two verification.
278 1. does the file exist?
279 2. dose the file wanted type? */
280 if (!strncmp(unesc, "file://", 7) &&
281 (strcasestr(unesc,".png") || strcasestr(unesc,".jpg") || strcasestr(unesc,".bmp")) &&
282 check_regular_file(unesc+7))
284 DTRACE("clipdrawer add path = %s\n", unesc+7);
285 clipdrawer_add_item(unesc+7, GI_IMAGE);
289 add_to_storage_buffer(ad, unesc, unesc_len);
290 clipdrawer_add_item(unesc, GI_TEXT);
292 DTRACE("len = %ld, data = %s\n", unesc_len, unesc);
296 print_storage_buffer();
304 int processing_selection_request(Ecore_X_Event_Selection_Request *ev)
308 Ecore_X_Window req_win;
311 req_size = XExtendedMaxRequestSize(g_disp) / 4;
314 req_size = XMaxRequestSize(g_disp) / 4;
317 req_win = ev->requestor;
318 req_atom = ev->property;
320 DTRACE("## wanted target = %d\n", ev->target);
321 DTRACE("## wanted target = %s\n", XGetAtomName(g_disp, ev->target));
322 DTRACE("## req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
324 /* TODO : if there are request which cbhm doesn't understand,
325 then reply None property to requestor */
326 /* TODO : add image type */
327 if (ev->target == atomTargets)
329 // Atom types[2] = { atomTargets, atomUTF8String };
330 Atom types[3] = { atomTargets, atomUTF8String, atomHtmltext };
332 // send all (not using INCR)
333 XChangeProperty(g_disp, req_win, req_atom, XA_ATOM,
334 32, PropModeReplace, (unsigned char *) types,
335 (int) (sizeof(types) / sizeof(Atom)));
336 DTRACE("target matched\n");
340 DTRACE("target mismatched. trying to txt\n");
343 if (g_lastest_content != NULL)
344 txt_len = strlen(g_lastest_content);
348 if (txt_len > req_size)
354 // send all (not using INCR)
355 XChangeProperty(g_disp, req_win, req_atom, atomUTF8String,
356 8, PropModeReplace, (unsigned char *) g_lastest_content, (int) txt_len);
358 DTRACE("txt target, len = %d\n", txt_len);
359 if (txt_len > 0 && g_lastest_content != NULL)
360 DTRACE("txt target, content = %s\n", g_lastest_content);
364 DTRACE("wanted window = 0x%x\n", req_win);
365 DTRACE("wanted target = %s\n", XGetAtomName(g_disp, ev->target));
367 DTRACE("selection target = %s\n", XGetAtomName(g_disp, ev->selection));
368 DTRACE("getted atom name = %s\n", XGetAtomName(g_disp, req_atom));
369 DTRACE("req target atom name = %s\n", XGetAtomName(g_disp, ev->target));
371 req_evt.xselection.property = req_atom;
372 req_evt.xselection.type = SelectionNotify;
373 req_evt.xselection.display = g_disp;
374 req_evt.xselection.requestor = req_win;
375 req_evt.xselection.selection = ev->selection;
376 req_evt.xselection.target = ev->target;
377 req_evt.xselection.time = ev->time;
379 XSendEvent(g_disp, ev->requestor, 0, 0, &req_evt);
385 static int _cbhm_init(void *data)
387 struct appdata *ad = data;
388 //Set default data structure
389 //Control that the libraries are properly initialized
390 if (!ecore_init()) return EXIT_FAILURE;
391 if (!ecore_evas_init()) return EXIT_FAILURE;
392 if (!edje_init()) return EXIT_FAILURE;
394 // do not x init in this module, it disconnect previous e17's X connection
395 //ecore_x_init(NULL);
397 g_disp = ecore_x_display_get();
401 DTRACE("Failed to get display\n");
405 g_rootwin = DefaultRootWindow(g_disp);
406 g_evtwin = ecore_x_window_new(g_rootwin, 0, 0, 19, 19);
407 ecore_x_netwm_name_set(g_evtwin, CLIPBOARD_MANAGER_WINDOW_TITLE_STRING);
409 XSelectInput(g_disp, g_evtwin, PropertyChangeMask);
410 XSelectInput(g_disp, g_rootwin, StructureNotifyMask);
411 // ecore_x_window_show(g_evtwin);
418 DTRACE("_cbhm_init ok\n");
420 set_clipboard_manager_owner();
421 send_convert_selection();
422 set_selection_owner();
427 static void _cbhm_fini()
434 static int _xsel_clear_cb(void *data, int ev_type, void *event)
436 struct appdata *ad = data;
438 Ecore_X_Event_Selection_Clear *ev = (Ecore_X_Event_Selection_Clear *)event;
440 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
443 DTRACE("XE:SelectionClear\n");
445 send_convert_selection();
447 /* TODO : set selection request is should after convert selection
449 set_selection_owner();
454 static int _xsel_request_cb(void *data, int ev_type, void *event)
456 Ecore_X_Event_Selection_Request *ev = (Ecore_X_Event_Selection_Request *)event;
458 if (ev->selection != atomClipboard)
461 DTRACE("XE:SelectionRequest\n");
463 processing_selection_request(ev);
468 static int _xsel_notify_cb(void *data, int ev_type, void *event)
470 struct appdata *ad = data;
472 Ecore_X_Event_Selection_Notify *ev = (Ecore_X_Event_Selection_Notify *)event;
473 Ecore_X_Selection_Data_Text *text_data = NULL;
475 if (ev->selection != ECORE_X_SELECTION_CLIPBOARD)
478 DTRACE("XE:SelectionNotify\n");
480 text_data = ev->data;
481 DTRACE("content type = %d\n", text_data->data.content);
482 get_selection_content(ad);
484 if (text_data->data.content != ECORE_X_SELECTION_CONTENT_TEXT)
486 DTRACE("content isn't text\n");
492 static int _xclient_msg_cb(void *data, int ev_type, void *event)
494 struct appdata *ad = data;
496 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message*)event;
498 Atom atomCBHM_MSG = XInternAtom(g_disp, "CBHM_MSG", False);
499 Atom atomCBHM_cRAW = XInternAtom(g_disp, "CBHM_cRAW", False);
500 Atom atomXKey_MSG = XInternAtom(g_disp, "_XKEY_COMPOSITION", False);
502 Atom cbhm_atoms[HISTORY_QUEUE_MAX_ITEMS];
503 Ecore_X_Window reqwin = ev->win;
506 if (ev->message_type == atomXKey_MSG)
508 DTRACE("XE:ClientMessage for Screen capture\n");
510 capture_current_screen(ad);
515 if (ev->message_type != atomCBHM_MSG)
518 DTRACE("XE:ClientMessage for CBHM\n");
520 DTRACE("## %s\n", ev->data.b);
522 if (strcmp("get count", ev->data.b) == 0)
524 int icount = get_item_counts();
526 DTRACE("## cbhm count : %d\n", icount);
527 sprintf(countbuf, "%d", icount);
528 sprintf(atomname, "CBHM_cCOUNT");
529 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
530 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
532 (unsigned char *) countbuf,
533 (int) strlen(countbuf));
536 else if (strncmp("get #", ev->data.b, 5) == 0)
538 // FIXME : handle greater than 9
539 int num = ev->data.b[5] - '0';
540 int cur = get_current_history_position();
542 if (num > HISTORY_QUEUE_MAX_ITEMS-1)
543 num = num-HISTORY_QUEUE_MAX_ITEMS;
545 if (num >= 0 && num < HISTORY_QUEUE_MAX_ITEMS)
547 DTRACE("## pos : #%d\n", num);
548 // FIXME : handle with correct atom
549 sprintf(atomname, "CBHM_c%d", num);
550 cbhm_atoms[0] = XInternAtom(g_disp, atomname, False);
551 if (get_item_contents_by_pos(num) != NULL)
553 XChangeProperty(g_disp, reqwin, cbhm_atoms[0], atomUTF8String,
555 (unsigned char *) get_item_contents_by_pos(num),
556 (int) strlen(get_item_contents_by_pos(num)));
560 else if (strcmp("get all", ev->data.b) == 0)
562 // print_history_buffer();
563 pos = get_current_history_position();
564 for (i = 0; i < 5; i++)
566 DTRACE("## %d -> %d\n", i, pos);
567 sprintf(atomname, "CBHM_c%d", i);
568 cbhm_atoms[i] = XInternAtom(g_disp, atomname, False);
569 if (get_item_contents_by_pos(pos) != NULL)
571 XChangeProperty(g_disp, reqwin, cbhm_atoms[i], atomUTF8String,
573 (unsigned char *) get_item_contents_by_pos(pos) ,
574 (int) strlen(get_item_contents_by_pos(pos)));
578 pos = HISTORY_QUEUE_MAX_ITEMS-1;
581 else if (strcmp("get raw", ev->data.b) == 0)
583 if (get_storage_start_addr != NULL)
585 XChangeProperty(g_disp, reqwin, atomCBHM_cRAW, atomUTF8String,
587 (unsigned char *) get_storage_start_addr(),
588 (int) get_total_storage_size());
591 else if (strcmp("show", ev->data.b) == 0)
593 clipdrawer_activate_view(ad);
601 static int _xfocus_out_cb(void *data, int ev_type, void *event)
603 struct appdata *ad = data;
605 DTRACE("XE:FOCUS OUT\n");
607 clipdrawer_lower_view(ad);
612 void set_transient_for(void *data)
614 struct appdata *ad = data;
616 Ecore_X_Window xwin_active = None;
617 Atom atomActive = XInternAtom(g_disp, "_NET_ACTIVE_WINDOW", False);
619 if (ecore_x_window_prop_window_get(DefaultRootWindow(g_disp),
620 atomActive, &xwin_active, 1) != -1)
622 ecore_x_icccm_transient_for_set (elm_win_xwindow_get(ad->win_main), xwin_active);
623 DTRACE("Success to set transient_for active window = 0x%X\n", xwin_active);
627 DTRACE("Failed to find active window for transient_for\n");
631 void unset_transient_for(void *data)
633 struct appdata *ad = data;
635 ecore_x_icccm_transient_for_unset(elm_win_xwindow_get(ad->win_main));
638 static Ecore_X_Window get_selection_secondary_target_win()
642 unsigned long nitems, bytes_after;
643 unsigned char *prop_return = NULL;
644 Atom atomCbhmXTarget = XInternAtom(g_disp, "CBHM_XTARGET", False);
645 static Ecore_X_Window xtarget = None;
650 XGetWindowProperty(g_disp, DefaultRootWindow(g_disp), atomCbhmXTarget,
651 0, sizeof(Ecore_X_Window), False, XA_WINDOW,
652 &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) &&
655 xtarget = *(Ecore_X_Window*)prop_return;
657 fprintf(stderr, "## find clipboard secondary target at root\n");
662 int set_selection_secondary_data(char *sdata)
664 Ecore_X_Window setwin = get_selection_secondary_target_win();
671 int slen = strlen(sdata);
673 fprintf(stderr, "## cbhm xwin = 0x%x, d = %s\n", setwin, sdata);
675 ecore_x_selection_secondary_set(setwin, sdata, slen);