2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4 #include "ecore_private.h"
6 #include "ecore_x_private.h"
8 #include "Ecore_X_Atoms.h"
10 static Ecore_X_Selection_Intern selections[4];
11 static Ecore_X_Selection_Converter *converters = NULL;
12 static Ecore_X_Selection_Parser *parsers = NULL;
14 static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
15 static int _ecore_x_selection_data_default_free(void *data);
16 static void *_ecore_x_selection_parser_files(const char *target, void *data, int size, int format);
17 static int _ecore_x_selection_data_files_free(void *data);
18 static void *_ecore_x_selection_parser_text(const char *target, void *data, int size, int format);
19 static int _ecore_x_selection_data_text_free(void *data);
20 static void *_ecore_x_selection_parser_targets(const char *target, void *data, int size, int format);
21 static int _ecore_x_selection_data_targets_free(void *data);
23 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
26 _ecore_x_selection_data_init(void)
28 /* Initialize global data */
29 memset(selections, 0, sizeof(selections));
31 /* Initialize converters */
32 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
33 _ecore_x_selection_converter_text);
34 #ifdef X_HAVE_UTF8_STRING
35 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
36 _ecore_x_selection_converter_text);
38 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
39 _ecore_x_selection_converter_text);
40 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
41 _ecore_x_selection_converter_text);
43 /* Initialize parsers */
44 ecore_x_selection_parser_add("text/plain",
45 _ecore_x_selection_parser_text);
46 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
47 _ecore_x_selection_parser_text);
48 ecore_x_selection_parser_add("text/uri-list",
49 _ecore_x_selection_parser_files);
50 ecore_x_selection_parser_add("_NETSCAPE_URL",
51 _ecore_x_selection_parser_files);
52 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
53 _ecore_x_selection_parser_targets);
57 _ecore_x_selection_shutdown(void)
59 Ecore_X_Selection_Converter *cnv;
60 Ecore_X_Selection_Parser *prs;
62 /* free the selection converters */
66 Ecore_X_Selection_Converter *tmp;
74 /* free the selection parsers */
78 Ecore_X_Selection_Parser *tmp;
88 Ecore_X_Selection_Intern *
89 _ecore_x_selection_get(Ecore_X_Atom selection)
91 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
92 return &selections[0];
93 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
94 return &selections[1];
95 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
96 return &selections[2];
97 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
98 return &selections[3];
104 _ecore_x_selection_set(Window w, const void *data, int size, Ecore_X_Atom selection)
107 unsigned char *buf = NULL;
109 XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
110 if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
113 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
115 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
117 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
119 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
126 selections[in].win = w;
127 selections[in].selection = selection;
128 selections[in].length = size;
129 selections[in].time = _ecore_x_event_last_time;
132 memcpy(buf, data, size);
133 selections[in].data = buf;
137 if (selections[in].data)
139 free(selections[in].data);
140 memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
148 * Claim ownership of the PRIMARY selection and set its data.
149 * @param w The window to which this selection belongs
150 * @param data The data associated with the selection
151 * @param size The size of the data buffer in bytes
152 * @return Returns 1 if the ownership of the selection was successfully
153 * claimed, or 0 if unsuccessful.
156 ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size)
158 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
162 * Release ownership of the primary selection
163 * @return Returns 1 if the selection was successfully cleared,
164 * or 0 if unsuccessful.
168 ecore_x_selection_primary_clear(void)
170 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
174 * Claim ownership of the SECONDARY selection and set its data.
175 * @param w The window to which this selection belongs
176 * @param data The data associated with the selection
177 * @param size The size of the data buffer in bytes
178 * @return Returns 1 if the ownership of the selection was successfully
179 * claimed, or 0 if unsuccessful.
182 ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size)
184 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_SECONDARY);
188 * Release ownership of the secondary selection
189 * @return Returns 1 if the selection was successfully cleared,
190 * or 0 if unsuccessful.
194 ecore_x_selection_secondary_clear(void)
196 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY);
200 * Claim ownership of the XDND selection and set its data.
201 * @param w The window to which this selection belongs
202 * @param data The data associated with the selection
203 * @param size The size of the data buffer in bytes
204 * @return Returns 1 if the ownership of the selection was successfully
205 * claimed, or 0 if unsuccessful.
208 ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size)
210 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
214 * Release ownership of the XDND selection
215 * @return Returns 1 if the selection was successfully cleared,
216 * or 0 if unsuccessful.
220 ecore_x_selection_xdnd_clear(void)
222 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
226 * Claim ownership of the CLIPBOARD selection and set its data.
227 * @param w The window to which this selection belongs
228 * @param data The data associated with the selection
229 * @param size The size of the data buffer in bytes
230 * @return Returns 1 if the ownership of the selection was successfully
231 * claimed, or 0 if unsuccessful.
233 * Get the converted data from a previous CLIPBOARD selection
234 * request. The buffer must be freed when done with.
237 ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size)
239 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD);
243 * Release ownership of the clipboard selection
244 * @return Returns 1 if the selection was successfully cleared,
245 * or 0 if unsuccessful.
249 ecore_x_selection_clipboard_clear(void)
251 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD);
255 _ecore_x_selection_target_atom_get(const char *target)
257 Ecore_X_Atom x_target;
259 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
260 x_target = ECORE_X_ATOM_TEXT;
261 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
262 x_target = ECORE_X_ATOM_COMPOUND_TEXT;
263 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
264 x_target = ECORE_X_ATOM_STRING;
265 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
266 x_target = ECORE_X_ATOM_UTF8_STRING;
267 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
268 x_target = ECORE_X_ATOM_FILE_NAME;
271 x_target = ecore_x_atom_get(target);
278 _ecore_x_selection_target_get(Ecore_X_Atom target)
280 /* FIXME: Should not return mem allocated with strdup or X mixed,
281 * one should use free to free, the other XFree */
282 if (target == ECORE_X_ATOM_FILE_NAME)
283 return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
284 else if (target == ECORE_X_ATOM_STRING)
285 return strdup(ECORE_X_SELECTION_TARGET_STRING);
286 else if (target == ECORE_X_ATOM_UTF8_STRING)
287 return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
288 else if (target == ECORE_X_ATOM_TEXT)
289 return strdup(ECORE_X_SELECTION_TARGET_TEXT);
291 return XGetAtomName(_ecore_x_disp, target);
295 _ecore_x_selection_request(Ecore_X_Window w, Ecore_X_Atom selection, const char *target_str)
297 Ecore_X_Atom target, prop;
299 target = _ecore_x_selection_target_atom_get(target_str);
301 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
302 prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
303 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
304 prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
305 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
306 prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
310 XConvertSelection(_ecore_x_disp, selection, target, prop,
315 ecore_x_selection_primary_request(Ecore_X_Window w, const char *target)
317 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
321 ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target)
323 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
327 ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target)
330 Ecore_X_DND_Target *_target;
332 _target = _ecore_x_dnd_target_get();
333 atom = _ecore_x_selection_target_atom_get(target);
334 XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
335 ECORE_X_ATOM_SELECTION_PROP_XDND, w,
340 ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target)
342 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
346 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
347 int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
349 Ecore_X_Selection_Converter *cnv;
356 if (cnv->target == target)
367 cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
372 converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
375 cnv->target = target;
380 ecore_x_selection_converter_add(char *target,
381 int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
383 Ecore_X_Atom x_target;
385 if (!func || !target)
388 x_target = _ecore_x_selection_target_atom_get(target);
390 ecore_x_selection_converter_atom_add(x_target, func);
394 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
396 Ecore_X_Selection_Converter *cnv, *prev_cnv;
403 if (cnv->target == target)
406 prev_cnv->next = cnv->next;
408 converters = cnv->next; /* This was the first converter */
419 ecore_x_selection_converter_del(char *target)
421 Ecore_X_Atom x_target;
426 x_target = _ecore_x_selection_target_atom_get(target);
427 ecore_x_selection_converter_atom_del(x_target);
431 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)
434 XSelectionEvent xnotify;
436 xnotify.type = SelectionNotify;
437 xnotify.display = _ecore_x_disp;
438 xnotify.requestor = requestor;
439 xnotify.selection = selection;
440 xnotify.target = target;
441 xnotify.property = property;
443 xnotify.send_event = True;
446 xev.xselection = xnotify;
447 return ((XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? 1 : 0);
450 /* Locate and run conversion callback for specified selection target */
452 ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret)
454 Ecore_X_Selection_Intern *sel;
455 Ecore_X_Selection_Converter *cnv;
460 sel = _ecore_x_selection_get(selection);
461 tgt_str = _ecore_x_selection_target_get(target);
463 for (cnv = converters; cnv; cnv = cnv->next)
465 if (cnv->target == target)
468 r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
480 /* 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." */
483 /* Default, just return the data
484 *data_ret = malloc(sel->length);
485 memcpy(*data_ret, sel->data, sel->length);
491 /* TODO: We need to work out a mechanism for automatic conversion to any requested
492 * locale using Ecore_Txt functions */
493 /* Converter for standard non-utf8 text targets */
495 _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret)
497 XTextProperty text_prop;
499 XICCEncodingStyle style;
504 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
506 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
507 style = XCompoundTextStyle;
508 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
509 style = XStringStyle;
510 #ifdef X_HAVE_UTF8_STRING
511 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
512 style = XUTF8StringStyle;
517 if (!(mystr = strdup(data)))
520 #ifdef X_HAVE_UTF8_STRING
521 if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
523 int bufsize = strlen((char *)text_prop.value) + 1;
524 *data_ret = malloc(bufsize);
525 memcpy(*data_ret, text_prop.value, bufsize);
527 XFree(text_prop.value);
532 if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
534 int bufsize = strlen(text_prop.value) + 1;
535 *data_ret = malloc(bufsize);
536 memcpy(*data_ret, text_prop.value, bufsize);
538 XFree(text_prop.value);
551 ecore_x_selection_parser_add(const char *target,
552 void *(*func)(const char *target, void *data, int size, int format))
554 Ecore_X_Selection_Parser *prs;
564 if (!strcmp(prs->target, target))
572 prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
577 parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
580 prs->target = strdup(target);
585 ecore_x_selection_parser_del(const char *target)
587 Ecore_X_Selection_Parser *prs, *prev_prs;
597 if (!strcmp(prs->target, target))
600 prev_prs->next = prs->next;
602 parsers = prs->next; /* This was the first parser */
613 /* Locate and run conversion callback for specified selection target */
615 _ecore_x_selection_parse(const char *target, void *data, int size, int format)
617 Ecore_X_Selection_Parser *prs;
618 Ecore_X_Selection_Data *sel;
620 for (prs = parsers; prs; prs = prs->next)
622 if (!strcmp(prs->target, target))
624 sel = prs->parse(target, data, size, format);
629 /* Default, just return the data */
630 sel = calloc(1, sizeof(Ecore_X_Selection_Data));
631 sel->free = _ecore_x_selection_data_default_free;
633 sel->format = format;
639 _ecore_x_selection_data_default_free(void *data)
641 Ecore_X_Selection_Data *sel;
650 _ecore_x_selection_parser_files(const char *target, void *_data, int size, int format __UNUSED__)
652 Ecore_X_Selection_Data_Files *sel;
657 if (strcmp(target, "text/uri-list") &&
658 strcmp(target, "_NETSCAPE_URL"))
661 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
662 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
666 /* Isn't nul terminated */
668 data = realloc(data, size);
675 while ((is < size) && (data[is]))
677 if ((i == 0) && (data[is] == '#'))
679 for (; ((data[is]) && (data[is] != '\n')); is++);
683 if ((data[is] != '\r') &&
686 tmp[i++] = data[is++];
690 while ((data[is] == '\r') || (data[is] == '\n')) is++;
693 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
694 sel->files[sel->num_files - 1] = strdup(tmp);
704 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
705 sel->files[sel->num_files - 1] = strdup(tmp);
710 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
711 ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
713 return ECORE_X_SELECTION_DATA(sel);
717 _ecore_x_selection_data_files_free(void *data)
719 Ecore_X_Selection_Data_Files *sel;
725 for (i = 0; i < sel->num_files; i++)
734 _ecore_x_selection_parser_text(const char *target __UNUSED__, void *_data, int size, int format __UNUSED__)
736 Ecore_X_Selection_Data_Text *sel;
739 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
743 /* Isn't nul terminated */
745 data = realloc(data, size);
749 sel->text = (char *)data;
750 ECORE_X_SELECTION_DATA(sel)->length = size;
751 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
752 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
757 _ecore_x_selection_data_text_free(void *data)
759 Ecore_X_Selection_Data_Text *sel;
768 _ecore_x_selection_parser_targets(const char *target __UNUSED__, void *data, int size, int format __UNUSED__)
770 Ecore_X_Selection_Data_Targets *sel;
771 unsigned long *targets;
774 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
775 targets = (unsigned long *)data;
777 sel->num_targets = size - 2;
778 sel->targets = malloc((size - 2) * sizeof(char *));
779 for (i = 2; i < size; i++)
780 sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
783 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
784 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
785 ECORE_X_SELECTION_DATA(sel)->length = size;
790 _ecore_x_selection_data_targets_free(void *data)
792 Ecore_X_Selection_Data_Targets *sel;
799 for (i = 0; i < sel->num_targets; i++)
800 XFree(sel->targets[i]);