2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
13 #include "ecore_private.h"
14 #include "ecore_x_private.h"
16 #include "Ecore_X_Atoms.h"
18 static Ecore_X_Selection_Intern selections[4];
19 static Ecore_X_Selection_Converter *converters = NULL;
20 static Ecore_X_Selection_Parser *parsers = NULL;
22 static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
23 static int _ecore_x_selection_data_default_free(void *data);
24 static void *_ecore_x_selection_parser_files(const char *target, void *data, int size, int format);
25 static int _ecore_x_selection_data_files_free(void *data);
26 static void *_ecore_x_selection_parser_text(const char *target, void *data, int size, int format);
27 static int _ecore_x_selection_data_text_free(void *data);
28 static void *_ecore_x_selection_parser_targets(const char *target, void *data, int size, int format);
29 static int _ecore_x_selection_data_targets_free(void *data);
31 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
34 _ecore_x_selection_data_init(void)
36 /* Initialize global data */
37 memset(selections, 0, sizeof(selections));
39 /* Initialize converters */
40 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
41 _ecore_x_selection_converter_text);
42 #ifdef X_HAVE_UTF8_STRING
43 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
44 _ecore_x_selection_converter_text);
46 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
47 _ecore_x_selection_converter_text);
48 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
49 _ecore_x_selection_converter_text);
51 /* Initialize parsers */
52 ecore_x_selection_parser_add("text/plain",
53 _ecore_x_selection_parser_text);
54 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
55 _ecore_x_selection_parser_text);
56 ecore_x_selection_parser_add("text/uri-list",
57 _ecore_x_selection_parser_files);
58 ecore_x_selection_parser_add("_NETSCAPE_URL",
59 _ecore_x_selection_parser_files);
60 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
61 _ecore_x_selection_parser_targets);
65 _ecore_x_selection_shutdown(void)
67 Ecore_X_Selection_Converter *cnv;
68 Ecore_X_Selection_Parser *prs;
70 /* free the selection converters */
74 Ecore_X_Selection_Converter *tmp;
82 /* free the selection parsers */
86 Ecore_X_Selection_Parser *tmp;
96 Ecore_X_Selection_Intern *
97 _ecore_x_selection_get(Ecore_X_Atom selection)
99 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
100 return &selections[0];
101 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
102 return &selections[1];
103 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
104 return &selections[2];
105 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
106 return &selections[3];
112 _ecore_x_selection_set(Window w, const void *data, int size, Ecore_X_Atom selection)
115 unsigned char *buf = NULL;
117 XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
118 if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
121 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
123 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
125 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
127 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
134 selections[in].win = w;
135 selections[in].selection = selection;
136 selections[in].length = size;
137 selections[in].time = _ecore_x_event_last_time;
140 memcpy(buf, data, size);
141 selections[in].data = buf;
145 if (selections[in].data)
147 free(selections[in].data);
148 memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
156 * Claim ownership of the PRIMARY selection and set its data.
157 * @param w The window to which this selection belongs
158 * @param data The data associated with the selection
159 * @param size The size of the data buffer in bytes
160 * @return Returns 1 if the ownership of the selection was successfully
161 * claimed, or 0 if unsuccessful.
164 ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size)
166 LOGFN(__FILE__, __LINE__, __FUNCTION__);
167 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
171 * Release ownership of the primary selection
172 * @return Returns 1 if the selection was successfully cleared,
173 * or 0 if unsuccessful.
177 ecore_x_selection_primary_clear(void)
179 LOGFN(__FILE__, __LINE__, __FUNCTION__);
180 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
184 * Claim ownership of the SECONDARY selection and set its data.
185 * @param w The window to which this selection belongs
186 * @param data The data associated with the selection
187 * @param size The size of the data buffer in bytes
188 * @return Returns 1 if the ownership of the selection was successfully
189 * claimed, or 0 if unsuccessful.
192 ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size)
194 LOGFN(__FILE__, __LINE__, __FUNCTION__);
195 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_SECONDARY);
199 * Release ownership of the secondary selection
200 * @return Returns 1 if the selection was successfully cleared,
201 * or 0 if unsuccessful.
205 ecore_x_selection_secondary_clear(void)
207 LOGFN(__FILE__, __LINE__, __FUNCTION__);
208 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY);
212 * Claim ownership of the XDND selection and set its data.
213 * @param w The window to which this selection belongs
214 * @param data The data associated with the selection
215 * @param size The size of the data buffer in bytes
216 * @return Returns 1 if the ownership of the selection was successfully
217 * claimed, or 0 if unsuccessful.
220 ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size)
222 LOGFN(__FILE__, __LINE__, __FUNCTION__);
223 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
227 * Release ownership of the XDND selection
228 * @return Returns 1 if the selection was successfully cleared,
229 * or 0 if unsuccessful.
233 ecore_x_selection_xdnd_clear(void)
235 LOGFN(__FILE__, __LINE__, __FUNCTION__);
236 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
240 * Claim ownership of the CLIPBOARD selection and set its data.
241 * @param w The window to which this selection belongs
242 * @param data The data associated with the selection
243 * @param size The size of the data buffer in bytes
244 * @return Returns 1 if the ownership of the selection was successfully
245 * claimed, or 0 if unsuccessful.
247 * Get the converted data from a previous CLIPBOARD selection
248 * request. The buffer must be freed when done with.
251 ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size)
253 LOGFN(__FILE__, __LINE__, __FUNCTION__);
254 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD);
258 * Release ownership of the clipboard selection
259 * @return Returns 1 if the selection was successfully cleared,
260 * or 0 if unsuccessful.
264 ecore_x_selection_clipboard_clear(void)
266 LOGFN(__FILE__, __LINE__, __FUNCTION__);
267 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD);
271 _ecore_x_selection_target_atom_get(const char *target)
273 Ecore_X_Atom x_target;
275 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
276 x_target = ECORE_X_ATOM_TEXT;
277 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
278 x_target = ECORE_X_ATOM_COMPOUND_TEXT;
279 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
280 x_target = ECORE_X_ATOM_STRING;
281 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
282 x_target = ECORE_X_ATOM_UTF8_STRING;
283 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
284 x_target = ECORE_X_ATOM_FILE_NAME;
287 x_target = ecore_x_atom_get(target);
294 _ecore_x_selection_target_get(Ecore_X_Atom target)
296 /* FIXME: Should not return mem allocated with strdup or X mixed,
297 * one should use free to free, the other XFree */
298 if (target == ECORE_X_ATOM_FILE_NAME)
299 return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
300 else if (target == ECORE_X_ATOM_STRING)
301 return strdup(ECORE_X_SELECTION_TARGET_STRING);
302 else if (target == ECORE_X_ATOM_UTF8_STRING)
303 return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
304 else if (target == ECORE_X_ATOM_TEXT)
305 return strdup(ECORE_X_SELECTION_TARGET_TEXT);
307 return XGetAtomName(_ecore_x_disp, target);
311 _ecore_x_selection_request(Ecore_X_Window w, Ecore_X_Atom selection, const char *target_str)
313 Ecore_X_Atom target, prop;
315 target = _ecore_x_selection_target_atom_get(target_str);
317 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
318 prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
319 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
320 prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
321 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
322 prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
326 XConvertSelection(_ecore_x_disp, selection, target, prop,
331 ecore_x_selection_primary_request(Ecore_X_Window w, const char *target)
333 LOGFN(__FILE__, __LINE__, __FUNCTION__);
334 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
338 ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target)
340 LOGFN(__FILE__, __LINE__, __FUNCTION__);
341 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
345 ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target)
348 Ecore_X_DND_Target *_target;
350 LOGFN(__FILE__, __LINE__, __FUNCTION__);
351 _target = _ecore_x_dnd_target_get();
352 atom = _ecore_x_selection_target_atom_get(target);
353 XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
354 ECORE_X_ATOM_SELECTION_PROP_XDND, w,
359 ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target)
361 LOGFN(__FILE__, __LINE__, __FUNCTION__);
362 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
366 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
367 int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
369 Ecore_X_Selection_Converter *cnv;
371 LOGFN(__FILE__, __LINE__, __FUNCTION__);
377 if (cnv->target == target)
388 cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
393 converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
396 cnv->target = target;
401 ecore_x_selection_converter_add(char *target,
402 int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
404 Ecore_X_Atom x_target;
406 if (!func || !target)
409 LOGFN(__FILE__, __LINE__, __FUNCTION__);
410 x_target = _ecore_x_selection_target_atom_get(target);
412 ecore_x_selection_converter_atom_add(x_target, func);
416 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
418 Ecore_X_Selection_Converter *cnv, *prev_cnv;
420 LOGFN(__FILE__, __LINE__, __FUNCTION__);
426 if (cnv->target == target)
429 prev_cnv->next = cnv->next;
431 converters = cnv->next; /* This was the first converter */
442 ecore_x_selection_converter_del(char *target)
444 Ecore_X_Atom x_target;
449 LOGFN(__FILE__, __LINE__, __FUNCTION__);
450 x_target = _ecore_x_selection_target_atom_get(target);
451 ecore_x_selection_converter_atom_del(x_target);
455 ecore_x_selection_notify_send(Ecore_X_Window requestor, Ecore_X_Atom selection, Ecore_X_Atom target, Ecore_X_Atom property, Ecore_X_Time time)
458 XSelectionEvent xnotify;
460 LOGFN(__FILE__, __LINE__, __FUNCTION__);
461 xnotify.type = SelectionNotify;
462 xnotify.display = _ecore_x_disp;
463 xnotify.requestor = requestor;
464 xnotify.selection = selection;
465 xnotify.target = target;
466 xnotify.property = property;
468 xnotify.send_event = True;
471 xev.xselection = xnotify;
472 return ((XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? 1 : 0);
475 /* Locate and run conversion callback for specified selection target */
477 ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret)
479 Ecore_X_Selection_Intern *sel;
480 Ecore_X_Selection_Converter *cnv;
485 LOGFN(__FILE__, __LINE__, __FUNCTION__);
486 sel = _ecore_x_selection_get(selection);
487 tgt_str = _ecore_x_selection_target_get(target);
489 for (cnv = converters; cnv; cnv = cnv->next)
491 if (cnv->target == target)
494 r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
506 /* 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." */
509 /* Default, just return the data
510 *data_ret = malloc(sel->length);
511 memcpy(*data_ret, sel->data, sel->length);
517 /* TODO: We need to work out a mechanism for automatic conversion to any requested
518 * locale using Ecore_Txt functions */
519 /* Converter for standard non-utf8 text targets */
521 _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret)
523 XTextProperty text_prop;
525 XICCEncodingStyle style;
530 LOGFN(__FILE__, __LINE__, __FUNCTION__);
531 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
533 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
534 style = XCompoundTextStyle;
535 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
536 style = XStringStyle;
537 #ifdef X_HAVE_UTF8_STRING
538 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
539 style = XUTF8StringStyle;
544 if (!(mystr = strdup(data)))
547 #ifdef X_HAVE_UTF8_STRING
548 if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
550 int bufsize = strlen((char *)text_prop.value) + 1;
551 *data_ret = malloc(bufsize);
552 memcpy(*data_ret, text_prop.value, bufsize);
554 XFree(text_prop.value);
559 if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
561 int bufsize = strlen(text_prop.value) + 1;
562 *data_ret = malloc(bufsize);
563 memcpy(*data_ret, text_prop.value, bufsize);
565 XFree(text_prop.value);
578 ecore_x_selection_parser_add(const char *target,
579 void *(*func)(const char *target, void *data, int size, int format))
581 Ecore_X_Selection_Parser *prs;
586 LOGFN(__FILE__, __LINE__, __FUNCTION__);
592 if (!strcmp(prs->target, target))
600 prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
605 parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
608 prs->target = strdup(target);
613 ecore_x_selection_parser_del(const char *target)
615 Ecore_X_Selection_Parser *prs, *prev_prs;
620 LOGFN(__FILE__, __LINE__, __FUNCTION__);
626 if (!strcmp(prs->target, target))
629 prev_prs->next = prs->next;
631 parsers = prs->next; /* This was the first parser */
642 /* Locate and run conversion callback for specified selection target */
644 _ecore_x_selection_parse(const char *target, void *data, int size, int format)
646 Ecore_X_Selection_Parser *prs;
647 Ecore_X_Selection_Data *sel;
649 for (prs = parsers; prs; prs = prs->next)
651 if (!strcmp(prs->target, target))
653 sel = prs->parse(target, data, size, format);
658 /* Default, just return the data */
659 sel = calloc(1, sizeof(Ecore_X_Selection_Data));
660 sel->free = _ecore_x_selection_data_default_free;
662 sel->format = format;
668 _ecore_x_selection_data_default_free(void *data)
670 Ecore_X_Selection_Data *sel;
679 _ecore_x_selection_parser_files(const char *target, void *_data, int size, int format __UNUSED__)
681 Ecore_X_Selection_Data_Files *sel;
686 if (strcmp(target, "text/uri-list") &&
687 strcmp(target, "_NETSCAPE_URL"))
690 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
691 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
695 /* Isn't nul terminated */
697 data = realloc(data, size);
704 while ((is < size) && (data[is]))
706 if ((i == 0) && (data[is] == '#'))
708 for (; ((data[is]) && (data[is] != '\n')); is++);
712 if ((data[is] != '\r') &&
715 tmp[i++] = data[is++];
719 while ((data[is] == '\r') || (data[is] == '\n')) is++;
722 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
723 sel->files[sel->num_files - 1] = strdup(tmp);
733 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
734 sel->files[sel->num_files - 1] = strdup(tmp);
739 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
740 ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
742 return ECORE_X_SELECTION_DATA(sel);
746 _ecore_x_selection_data_files_free(void *data)
748 Ecore_X_Selection_Data_Files *sel;
754 for (i = 0; i < sel->num_files; i++)
763 _ecore_x_selection_parser_text(const char *target __UNUSED__, void *_data, int size, int format __UNUSED__)
765 Ecore_X_Selection_Data_Text *sel;
768 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
772 /* Isn't nul terminated */
774 data = realloc(data, size);
778 sel->text = (char *)data;
779 ECORE_X_SELECTION_DATA(sel)->length = size;
780 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
781 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
786 _ecore_x_selection_data_text_free(void *data)
788 Ecore_X_Selection_Data_Text *sel;
797 _ecore_x_selection_parser_targets(const char *target __UNUSED__, void *data, int size, int format __UNUSED__)
799 Ecore_X_Selection_Data_Targets *sel;
800 unsigned long *targets;
803 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
804 targets = (unsigned long *)data;
806 sel->num_targets = size - 2;
807 sel->targets = malloc((size - 2) * sizeof(char *));
808 for (i = 2; i < size; i++)
809 sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
812 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
813 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
814 ECORE_X_SELECTION_DATA(sel)->length = size;
819 _ecore_x_selection_data_targets_free(void *data)
821 Ecore_X_Selection_Data_Targets *sel;
828 for (i = 0; i < sel->num_targets; i++)
829 XFree(sel->targets[i]);