3 #endif /* ifdef HAVE_CONFIG_H */
9 #include "ecore_private.h"
10 #include "ecore_x_private.h"
12 #include "Ecore_X_Atoms.h"
14 static Ecore_X_Selection_Intern selections[4];
15 static Ecore_X_Selection_Converter *converters = NULL;
16 static Ecore_X_Selection_Parser *parsers = NULL;
18 static int _ecore_x_selection_data_default_free(void *data);
19 static void *_ecore_x_selection_parser_files(const char *target,
23 static int _ecore_x_selection_data_files_free(void *data);
24 static void *_ecore_x_selection_parser_text(const char *target,
28 static int _ecore_x_selection_data_text_free(void *data);
29 static void *_ecore_x_selection_parser_targets(const char *target,
33 static int _ecore_x_selection_data_targets_free(void *data);
35 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
38 _ecore_x_selection_data_init(void)
40 /* Initialize global data */
41 memset(selections, 0, sizeof(selections));
43 /* Initialize converters */
44 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
45 ecore_x_selection_converter_text);
46 #ifdef X_HAVE_UTF8_STRING
47 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
48 ecore_x_selection_converter_text);
49 #endif /* ifdef X_HAVE_UTF8_STRING */
50 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
51 ecore_x_selection_converter_text);
52 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
53 ecore_x_selection_converter_text);
55 /* Initialize parsers */
56 ecore_x_selection_parser_add("text/plain",
57 _ecore_x_selection_parser_text);
58 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
59 _ecore_x_selection_parser_text);
60 ecore_x_selection_parser_add("text/uri-list",
61 _ecore_x_selection_parser_files);
62 ecore_x_selection_parser_add("_NETSCAPE_URL",
63 _ecore_x_selection_parser_files);
64 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
65 _ecore_x_selection_parser_targets);
69 _ecore_x_selection_shutdown(void)
71 Ecore_X_Selection_Converter *cnv;
72 Ecore_X_Selection_Parser *prs;
74 /* free the selection converters */
78 Ecore_X_Selection_Converter *tmp;
86 /* free the selection parsers */
90 Ecore_X_Selection_Parser *tmp;
100 Ecore_X_Selection_Intern *
101 _ecore_x_selection_get(Ecore_X_Atom selection)
103 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
104 return &selections[0];
105 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
106 return &selections[1];
107 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
108 return &selections[2];
109 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
110 return &selections[3];
116 _ecore_x_selection_set(Window w,
119 Ecore_X_Atom selection)
122 unsigned char *buf = NULL;
124 XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
125 if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
128 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
130 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
132 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
134 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
141 selections[in].win = w;
142 selections[in].selection = selection;
143 selections[in].length = size;
144 selections[in].time = _ecore_x_event_last_time;
147 if (!buf) return EINA_FALSE;
148 memcpy(buf, data, size);
149 selections[in].data = buf;
151 else if (selections[in].data)
153 free(selections[in].data);
154 memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
161 * Claim ownership of the PRIMARY selection and set its data.
162 * @param w The window to which this selection belongs
163 * @param data The data associated with the selection
164 * @param size The size of the data buffer in bytes
165 * @return Returns 1 if the ownership of the selection was successfully
166 * claimed, or 0 if unsuccessful.
169 ecore_x_selection_primary_set(Ecore_X_Window w,
173 LOGFN(__FILE__, __LINE__, __FUNCTION__);
174 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
178 * Release ownership of the primary selection
179 * @return Returns 1 if the selection was successfully cleared,
180 * or 0 if unsuccessful.
184 ecore_x_selection_primary_clear(void)
186 LOGFN(__FILE__, __LINE__, __FUNCTION__);
187 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
191 * Claim ownership of the SECONDARY selection and set its data.
192 * @param w The window to which this selection belongs
193 * @param data The data associated with the selection
194 * @param size The size of the data buffer in bytes
195 * @return Returns 1 if the ownership of the selection was successfully
196 * claimed, or 0 if unsuccessful.
199 ecore_x_selection_secondary_set(Ecore_X_Window w,
203 LOGFN(__FILE__, __LINE__, __FUNCTION__);
204 return _ecore_x_selection_set(w,
207 ECORE_X_ATOM_SELECTION_SECONDARY);
211 * Release ownership of the secondary selection
212 * @return Returns 1 if the selection was successfully cleared,
213 * or 0 if unsuccessful.
217 ecore_x_selection_secondary_clear(void)
219 LOGFN(__FILE__, __LINE__, __FUNCTION__);
220 return _ecore_x_selection_set(None,
223 ECORE_X_ATOM_SELECTION_SECONDARY);
227 * Claim ownership of the XDND selection and set its data.
228 * @param w The window to which this selection belongs
229 * @param data The data associated with the selection
230 * @param size The size of the data buffer in bytes
231 * @return Returns 1 if the ownership of the selection was successfully
232 * claimed, or 0 if unsuccessful.
235 ecore_x_selection_xdnd_set(Ecore_X_Window w,
239 LOGFN(__FILE__, __LINE__, __FUNCTION__);
240 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
244 * Release ownership of the XDND selection
245 * @return Returns 1 if the selection was successfully cleared,
246 * or 0 if unsuccessful.
250 ecore_x_selection_xdnd_clear(void)
252 LOGFN(__FILE__, __LINE__, __FUNCTION__);
253 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
257 * Claim ownership of the CLIPBOARD selection and set its data.
258 * @param w The window to which this selection belongs
259 * @param data The data associated with the selection
260 * @param size The size of the data buffer in bytes
261 * @return Returns 1 if the ownership of the selection was successfully
262 * claimed, or 0 if unsuccessful.
264 * Get the converted data from a previous CLIPBOARD selection
265 * request. The buffer must be freed when done with.
268 ecore_x_selection_clipboard_set(Ecore_X_Window w,
272 LOGFN(__FILE__, __LINE__, __FUNCTION__);
273 return _ecore_x_selection_set(w,
276 ECORE_X_ATOM_SELECTION_CLIPBOARD);
280 * Release ownership of the clipboard selection
281 * @return Returns 1 if the selection was successfully cleared,
282 * or 0 if unsuccessful.
286 ecore_x_selection_clipboard_clear(void)
288 LOGFN(__FILE__, __LINE__, __FUNCTION__);
289 return _ecore_x_selection_set(None,
292 ECORE_X_ATOM_SELECTION_CLIPBOARD);
296 _ecore_x_selection_target_atom_get(const char *target)
298 Ecore_X_Atom x_target;
300 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
301 x_target = ECORE_X_ATOM_TEXT;
302 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
303 x_target = ECORE_X_ATOM_COMPOUND_TEXT;
304 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
305 x_target = ECORE_X_ATOM_STRING;
306 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
307 x_target = ECORE_X_ATOM_UTF8_STRING;
308 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
309 x_target = ECORE_X_ATOM_FILE_NAME;
311 x_target = ecore_x_atom_get(target);
317 _ecore_x_selection_target_get(Ecore_X_Atom target)
319 /* FIXME: Should not return mem allocated with strdup or X mixed,
320 * one should use free to free, the other XFree */
321 if (target == ECORE_X_ATOM_FILE_NAME)
322 return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
323 else if (target == ECORE_X_ATOM_STRING)
324 return strdup(ECORE_X_SELECTION_TARGET_STRING);
325 else if (target == ECORE_X_ATOM_UTF8_STRING)
326 return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
327 else if (target == ECORE_X_ATOM_TEXT)
328 return strdup(ECORE_X_SELECTION_TARGET_TEXT);
330 return XGetAtomName(_ecore_x_disp, target);
334 _ecore_x_selection_request(Ecore_X_Window w,
335 Ecore_X_Atom selection,
336 const char *target_str)
338 Ecore_X_Atom target, prop;
340 target = _ecore_x_selection_target_atom_get(target_str);
342 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
343 prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
344 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
345 prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
346 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
347 prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
351 XConvertSelection(_ecore_x_disp, selection, target, prop,
356 ecore_x_selection_primary_request(Ecore_X_Window w,
359 LOGFN(__FILE__, __LINE__, __FUNCTION__);
360 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
364 ecore_x_selection_secondary_request(Ecore_X_Window w,
367 LOGFN(__FILE__, __LINE__, __FUNCTION__);
368 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
372 ecore_x_selection_xdnd_request(Ecore_X_Window w,
376 Ecore_X_DND_Target *_target;
378 LOGFN(__FILE__, __LINE__, __FUNCTION__);
379 _target = _ecore_x_dnd_target_get();
380 atom = _ecore_x_selection_target_atom_get(target);
381 XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
382 ECORE_X_ATOM_SELECTION_PROP_XDND, w,
387 ecore_x_selection_clipboard_request(Ecore_X_Window w,
390 LOGFN(__FILE__, __LINE__, __FUNCTION__);
391 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
395 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
396 Eina_Bool (*func)(char *target,
404 Ecore_X_Selection_Converter *cnv;
406 LOGFN(__FILE__, __LINE__, __FUNCTION__);
412 if (cnv->target == target)
424 cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
425 if (!cnv->next) return;
430 converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
431 if (!converters) return;
435 cnv->target = target;
440 ecore_x_selection_converter_add(char *target,
441 Eina_Bool (*func)(char *target,
449 Ecore_X_Atom x_target;
451 if (!func || !target)
454 LOGFN(__FILE__, __LINE__, __FUNCTION__);
455 x_target = _ecore_x_selection_target_atom_get(target);
457 ecore_x_selection_converter_atom_add(x_target, func);
461 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
463 Ecore_X_Selection_Converter *cnv, *prev_cnv;
465 LOGFN(__FILE__, __LINE__, __FUNCTION__);
471 if (cnv->target == target)
474 prev_cnv->next = cnv->next;
477 converters = cnv->next; /* This was the first converter */
491 ecore_x_selection_converter_del(char *target)
493 Ecore_X_Atom x_target;
498 LOGFN(__FILE__, __LINE__, __FUNCTION__);
499 x_target = _ecore_x_selection_target_atom_get(target);
500 ecore_x_selection_converter_atom_del(x_target);
504 ecore_x_selection_notify_send(Ecore_X_Window requestor,
505 Ecore_X_Atom selection,
507 Ecore_X_Atom property,
511 XSelectionEvent xnotify;
513 LOGFN(__FILE__, __LINE__, __FUNCTION__);
514 xnotify.type = SelectionNotify;
515 xnotify.display = _ecore_x_disp;
516 xnotify.requestor = requestor;
517 xnotify.selection = selection;
518 xnotify.target = target;
519 xnotify.property = property;
521 xnotify.send_event = True;
524 xev.xselection = xnotify;
525 return (XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? EINA_TRUE : EINA_FALSE;
528 /* Locate and run conversion callback for specified selection target */
530 ecore_x_selection_convert(Ecore_X_Atom selection,
534 Ecore_X_Atom *targtype,
537 Ecore_X_Selection_Intern *sel;
538 Ecore_X_Selection_Converter *cnv;
542 LOGFN(__FILE__, __LINE__, __FUNCTION__);
543 sel = _ecore_x_selection_get(selection);
544 tgt_str = _ecore_x_selection_target_get(target);
546 for (cnv = converters; cnv; cnv = cnv->next)
548 if (cnv->target == target)
551 r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
564 /* ICCCM says "If the selection cannot be converted into a form based on the target (and parameters, if any), the owner should refuse the SelectionRequest as previously described." */
567 /* Default, just return the data
568 * data_ret = malloc(sel->length);
569 memcpy(*data_ret, sel->data, sel->length);
575 /* TODO: We need to work out a mechanism for automatic conversion to any requested
576 * locale using Ecore_Txt functions */
577 /* Converter for standard non-utf8 text targets */
579 ecore_x_selection_converter_text(char *target,
584 Ecore_X_Atom *targprop __UNUSED__,
587 XTextProperty text_prop;
589 XICCEncodingStyle style;
594 LOGFN(__FILE__, __LINE__, __FUNCTION__);
595 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
597 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
598 style = XCompoundTextStyle;
599 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
600 style = XStringStyle;
602 #ifdef X_HAVE_UTF8_STRING
603 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
604 style = XUTF8StringStyle;
605 #endif /* ifdef X_HAVE_UTF8_STRING */
609 mystr = alloca(size + 1);
610 memcpy(mystr, data, size);
613 #ifdef X_HAVE_UTF8_STRING
614 if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
615 &text_prop) == Success)
617 int bufsize = strlen((char *)text_prop.value) + 1;
618 *data_ret = malloc(bufsize);
623 memcpy(*data_ret, text_prop.value, bufsize);
625 XFree(text_prop.value);
629 #else /* ifdef X_HAVE_UTF8_STRING */
630 if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
631 &text_prop) == Success)
633 int bufsize = strlen(text_prop.value) + 1;
634 *data_ret = malloc(bufsize);
635 if (!*data_ret) return EINA_FALSE;
636 memcpy(*data_ret, text_prop.value, bufsize);
638 XFree(text_prop.value);
642 #endif /* ifdef X_HAVE_UTF8_STRING */
650 ecore_x_selection_parser_add(const char *target,
651 void *(*func)(const char *target, void *data,
655 Ecore_X_Selection_Parser *prs;
660 LOGFN(__FILE__, __LINE__, __FUNCTION__);
666 if (!strcmp(prs->target, target))
675 prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
676 if (!prs->next) return;
681 parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
682 if (!parsers) return;
686 prs->target = strdup(target);
691 ecore_x_selection_parser_del(const char *target)
693 Ecore_X_Selection_Parser *prs, *prev_prs;
698 LOGFN(__FILE__, __LINE__, __FUNCTION__);
704 if (!strcmp(prs->target, target))
707 prev_prs->next = prs->next;
710 parsers = prs->next; /* This was the first parser */
725 * Change the owner and last-change time for the specified selection.
726 * @param win The owner of the specified atom.
727 * @param atom The selection atom
728 * @param tim Specifies the time
732 ecore_x_selection_owner_set(Ecore_X_Window win,
736 XSetSelectionOwner(_ecore_x_disp, atom, win, tim);
740 * Return the window that currently owns the specified selection.
742 * @param atom The specified selection atom.
744 * @return The window that currently owns the specified selection.
748 ecore_x_selection_owner_get(Ecore_X_Atom atom)
750 return XGetSelectionOwner(_ecore_x_disp, atom);
753 /* Locate and run conversion callback for specified selection target */
755 _ecore_x_selection_parse(const char *target,
760 Ecore_X_Selection_Parser *prs;
761 Ecore_X_Selection_Data *sel;
763 for (prs = parsers; prs; prs = prs->next)
765 if (!strcmp(prs->target, target))
767 sel = prs->parse(target, data, size, format);
772 /* Default, just return the data */
773 sel = calloc(1, sizeof(Ecore_X_Selection_Data));
774 if (!sel) return NULL;
775 sel->free = _ecore_x_selection_data_default_free;
777 sel->format = format;
783 _ecore_x_selection_data_default_free(void *data)
785 Ecore_X_Selection_Data *sel;
794 _ecore_x_selection_parser_files(const char *target,
797 int format __UNUSED__)
799 Ecore_X_Selection_Data_Files *sel;
800 char *t, *data = _data;
805 if (strcmp(target, "text/uri-list") &&
806 strcmp(target, "_NETSCAPE_URL"))
809 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
810 if (!sel) return NULL;
811 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
815 /* Isn't nul terminated */
817 t = realloc(data, size);
835 while ((is < size) && (data[is]))
837 if ((i == 0) && (data[is] == '#'))
838 for (; ((data[is]) && (data[is] != '\n')); is++) ;
841 if ((data[is] != '\r') &&
843 tmp[i++] = data[is++];
846 while ((data[is] == '\r') || (data[is] == '\n'))
850 t2 = realloc(sel->files, sel->num_files * sizeof(char *));
854 sel->files[sel->num_files - 1] = strdup(tmp);
865 t2 = realloc(sel->files, sel->num_files * sizeof(char *));
869 sel->files[sel->num_files - 1] = strdup(tmp);
876 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
877 ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
879 return ECORE_X_SELECTION_DATA(sel);
883 _ecore_x_selection_data_files_free(void *data)
885 Ecore_X_Selection_Data_Files *sel;
891 for (i = 0; i < sel->num_files; i++)
901 _ecore_x_selection_parser_text(const char *target __UNUSED__,
904 int format __UNUSED__)
906 Ecore_X_Selection_Data_Text *sel;
907 unsigned char *data = _data;
910 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
911 if (!sel) return NULL;
914 /* Isn't nul terminated */
916 t = realloc(data, size);
926 sel->text = (char *)data;
927 ECORE_X_SELECTION_DATA(sel)->length = size;
928 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
929 ECORE_X_SELECTION_DATA(sel)->data = data;
930 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
935 _ecore_x_selection_data_text_free(void *data)
937 Ecore_X_Selection_Data_Text *sel;
946 _ecore_x_selection_parser_targets(const char *target __UNUSED__,
949 int format __UNUSED__)
951 Ecore_X_Selection_Data_Targets *sel;
952 unsigned long *targets;
955 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
956 if (!sel) return NULL;
957 targets = (unsigned long *)data;
959 sel->num_targets = size - 2;
960 sel->targets = malloc((size - 2) * sizeof(char *));
966 for (i = 2; i < size; i++)
967 sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
969 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
970 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
971 ECORE_X_SELECTION_DATA(sel)->length = size;
972 ECORE_X_SELECTION_DATA(sel)->data = data;
977 _ecore_x_selection_data_targets_free(void *data)
979 Ecore_X_Selection_Data_Targets *sel;
986 for (i = 0; i < sel->num_targets; i++)
987 XFree(sel->targets[i]);
991 free(ECORE_X_SELECTION_DATA(sel)->data);