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_converter_text(char *target,
25 static int _ecore_x_selection_data_default_free(void *data);
26 static void * _ecore_x_selection_parser_files(const char *target,
30 static int _ecore_x_selection_data_files_free(void *data);
31 static void * _ecore_x_selection_parser_text(const char *target,
35 static int _ecore_x_selection_data_text_free(void *data);
36 static void * _ecore_x_selection_parser_targets(const char *target,
40 static int _ecore_x_selection_data_targets_free(void *data);
42 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
45 _ecore_x_selection_data_init(void)
47 /* Initialize global data */
48 memset(selections, 0, sizeof(selections));
50 /* Initialize converters */
51 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
52 _ecore_x_selection_converter_text);
53 #ifdef X_HAVE_UTF8_STRING
54 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
55 _ecore_x_selection_converter_text);
56 #endif /* ifdef X_HAVE_UTF8_STRING */
57 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
58 _ecore_x_selection_converter_text);
59 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
60 _ecore_x_selection_converter_text);
62 /* Initialize parsers */
63 ecore_x_selection_parser_add("text/plain",
64 _ecore_x_selection_parser_text);
65 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
66 _ecore_x_selection_parser_text);
67 ecore_x_selection_parser_add("text/uri-list",
68 _ecore_x_selection_parser_files);
69 ecore_x_selection_parser_add("_NETSCAPE_URL",
70 _ecore_x_selection_parser_files);
71 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
72 _ecore_x_selection_parser_targets);
73 } /* _ecore_x_selection_data_init */
76 _ecore_x_selection_shutdown(void)
78 Ecore_X_Selection_Converter *cnv;
79 Ecore_X_Selection_Parser *prs;
81 /* free the selection converters */
85 Ecore_X_Selection_Converter *tmp;
93 /* free the selection parsers */
97 Ecore_X_Selection_Parser *tmp;
105 } /* _ecore_x_selection_shutdown */
107 Ecore_X_Selection_Intern *
108 _ecore_x_selection_get(Ecore_X_Atom selection)
110 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
111 return &selections[0];
112 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
113 return &selections[1];
114 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
115 return &selections[2];
116 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
117 return &selections[3];
120 } /* _ecore_x_selection_get */
123 _ecore_x_selection_set(Window w,
126 Ecore_X_Atom selection)
129 unsigned char *buf = NULL;
131 XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
132 if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
135 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
137 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
139 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
141 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
148 selections[in].win = w;
149 selections[in].selection = selection;
150 selections[in].length = size;
151 selections[in].time = _ecore_x_event_last_time;
154 memcpy(buf, data, size);
155 selections[in].data = buf;
157 else if (selections[in].data)
159 free(selections[in].data);
160 memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
164 } /* _ecore_x_selection_set */
167 * Claim ownership of the PRIMARY selection and set its data.
168 * @param w The window to which this selection belongs
169 * @param data The data associated with the selection
170 * @param size The size of the data buffer in bytes
171 * @return Returns 1 if the ownership of the selection was successfully
172 * claimed, or 0 if unsuccessful.
175 ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size)
177 LOGFN(__FILE__, __LINE__, __FUNCTION__);
178 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
179 } /* ecore_x_selection_primary_set */
182 * Release ownership of the primary selection
183 * @return Returns 1 if the selection was successfully cleared,
184 * or 0 if unsuccessful.
188 ecore_x_selection_primary_clear(void)
190 LOGFN(__FILE__, __LINE__, __FUNCTION__);
191 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
192 } /* ecore_x_selection_primary_clear */
195 * Claim ownership of the SECONDARY selection and set its data.
196 * @param w The window to which this selection belongs
197 * @param data The data associated with the selection
198 * @param size The size of the data buffer in bytes
199 * @return Returns 1 if the ownership of the selection was successfully
200 * claimed, or 0 if unsuccessful.
203 ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size)
205 LOGFN(__FILE__, __LINE__, __FUNCTION__);
206 return _ecore_x_selection_set(w,
209 ECORE_X_ATOM_SELECTION_SECONDARY);
210 } /* ecore_x_selection_secondary_set */
213 * Release ownership of the secondary selection
214 * @return Returns 1 if the selection was successfully cleared,
215 * or 0 if unsuccessful.
219 ecore_x_selection_secondary_clear(void)
221 LOGFN(__FILE__, __LINE__, __FUNCTION__);
222 return _ecore_x_selection_set(None,
225 ECORE_X_ATOM_SELECTION_SECONDARY);
226 } /* ecore_x_selection_secondary_clear */
229 * Claim ownership of the XDND selection and set its data.
230 * @param w The window to which this selection belongs
231 * @param data The data associated with the selection
232 * @param size The size of the data buffer in bytes
233 * @return Returns 1 if the ownership of the selection was successfully
234 * claimed, or 0 if unsuccessful.
237 ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size)
239 LOGFN(__FILE__, __LINE__, __FUNCTION__);
240 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
241 } /* ecore_x_selection_xdnd_set */
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);
254 } /* ecore_x_selection_xdnd_clear */
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, const void *data, int size)
270 LOGFN(__FILE__, __LINE__, __FUNCTION__);
271 return _ecore_x_selection_set(w,
274 ECORE_X_ATOM_SELECTION_CLIPBOARD);
275 } /* ecore_x_selection_clipboard_set */
278 * Release ownership of the clipboard selection
279 * @return Returns 1 if the selection was successfully cleared,
280 * or 0 if unsuccessful.
284 ecore_x_selection_clipboard_clear(void)
286 LOGFN(__FILE__, __LINE__, __FUNCTION__);
287 return _ecore_x_selection_set(None,
290 ECORE_X_ATOM_SELECTION_CLIPBOARD);
291 } /* ecore_x_selection_clipboard_clear */
294 _ecore_x_selection_target_atom_get(const char *target)
296 Ecore_X_Atom x_target;
298 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
299 x_target = ECORE_X_ATOM_TEXT;
300 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
301 x_target = ECORE_X_ATOM_COMPOUND_TEXT;
302 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
303 x_target = ECORE_X_ATOM_STRING;
304 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
305 x_target = ECORE_X_ATOM_UTF8_STRING;
306 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
307 x_target = ECORE_X_ATOM_FILE_NAME;
309 x_target = ecore_x_atom_get(target);
312 } /* _ecore_x_selection_target_atom_get */
315 _ecore_x_selection_target_get(Ecore_X_Atom target)
317 /* FIXME: Should not return mem allocated with strdup or X mixed,
318 * one should use free to free, the other XFree */
319 if (target == ECORE_X_ATOM_FILE_NAME)
320 return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
321 else if (target == ECORE_X_ATOM_STRING)
322 return strdup(ECORE_X_SELECTION_TARGET_STRING);
323 else if (target == ECORE_X_ATOM_UTF8_STRING)
324 return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
325 else if (target == ECORE_X_ATOM_TEXT)
326 return strdup(ECORE_X_SELECTION_TARGET_TEXT);
328 return XGetAtomName(_ecore_x_disp, target);
329 } /* _ecore_x_selection_target_get */
332 _ecore_x_selection_request(Ecore_X_Window w,
333 Ecore_X_Atom selection,
334 const char *target_str)
336 Ecore_X_Atom target, prop;
338 target = _ecore_x_selection_target_atom_get(target_str);
340 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
341 prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
342 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
343 prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
344 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
345 prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
349 XConvertSelection(_ecore_x_disp, selection, target, prop,
351 } /* _ecore_x_selection_request */
354 ecore_x_selection_primary_request(Ecore_X_Window w, const char *target)
356 LOGFN(__FILE__, __LINE__, __FUNCTION__);
357 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
358 } /* ecore_x_selection_primary_request */
361 ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target)
363 LOGFN(__FILE__, __LINE__, __FUNCTION__);
364 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
365 } /* ecore_x_selection_secondary_request */
368 ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target)
371 Ecore_X_DND_Target *_target;
373 LOGFN(__FILE__, __LINE__, __FUNCTION__);
374 _target = _ecore_x_dnd_target_get();
375 atom = _ecore_x_selection_target_atom_get(target);
376 XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
377 ECORE_X_ATOM_SELECTION_PROP_XDND, w,
379 } /* ecore_x_selection_xdnd_request */
382 ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target)
384 LOGFN(__FILE__, __LINE__, __FUNCTION__);
385 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
386 } /* ecore_x_selection_clipboard_request */
389 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
390 int (*func)(char *target,
398 Ecore_X_Selection_Converter *cnv;
400 LOGFN(__FILE__, __LINE__, __FUNCTION__);
406 if (cnv->target == target)
418 cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
423 converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
427 cnv->target = target;
429 } /* ecore_x_selection_converter_atom_add */
432 ecore_x_selection_converter_add(char *target,
433 int (*func)(char *target,
441 Ecore_X_Atom x_target;
443 if (!func || !target)
446 LOGFN(__FILE__, __LINE__, __FUNCTION__);
447 x_target = _ecore_x_selection_target_atom_get(target);
449 ecore_x_selection_converter_atom_add(x_target, func);
450 } /* ecore_x_selection_converter_add */
453 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
455 Ecore_X_Selection_Converter *cnv, *prev_cnv;
457 LOGFN(__FILE__, __LINE__, __FUNCTION__);
463 if (cnv->target == target)
466 prev_cnv->next = cnv->next;
469 converters = cnv->next; /* This was the first converter */
480 } /* ecore_x_selection_converter_atom_del */
483 ecore_x_selection_converter_del(char *target)
485 Ecore_X_Atom x_target;
490 LOGFN(__FILE__, __LINE__, __FUNCTION__);
491 x_target = _ecore_x_selection_target_atom_get(target);
492 ecore_x_selection_converter_atom_del(x_target);
493 } /* ecore_x_selection_converter_del */
496 ecore_x_selection_notify_send(Ecore_X_Window requestor,
497 Ecore_X_Atom selection,
499 Ecore_X_Atom property,
503 XSelectionEvent xnotify;
505 LOGFN(__FILE__, __LINE__, __FUNCTION__);
506 xnotify.type = SelectionNotify;
507 xnotify.display = _ecore_x_disp;
508 xnotify.requestor = requestor;
509 xnotify.selection = selection;
510 xnotify.target = target;
511 xnotify.property = property;
513 xnotify.send_event = True;
516 xev.xselection = xnotify;
517 return ((XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? 1 : 0);
518 } /* ecore_x_selection_notify_send */
520 /* Locate and run conversion callback for specified selection target */
522 ecore_x_selection_convert(Ecore_X_Atom selection,
526 Ecore_X_Atom *targtype,
529 Ecore_X_Selection_Intern *sel;
530 Ecore_X_Selection_Converter *cnv;
534 LOGFN(__FILE__, __LINE__, __FUNCTION__);
535 sel = _ecore_x_selection_get(selection);
536 tgt_str = _ecore_x_selection_target_get(target);
538 for (cnv = converters; cnv; cnv = cnv->next)
540 if (cnv->target == target)
543 r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
556 /* 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." */
559 /* Default, just return the data
560 *data_ret = malloc(sel->length);
561 memcpy(*data_ret, sel->data, sel->length);
565 } /* ecore_x_selection_convert */
567 /* TODO: We need to work out a mechanism for automatic conversion to any requested
568 * locale using Ecore_Txt functions */
569 /* Converter for standard non-utf8 text targets */
571 _ecore_x_selection_converter_text(char *target,
576 Ecore_X_Atom *targprop __UNUSED__,
579 XTextProperty text_prop;
581 XICCEncodingStyle style;
586 LOGFN(__FILE__, __LINE__, __FUNCTION__);
587 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
589 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
590 style = XCompoundTextStyle;
591 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
592 style = XStringStyle;
594 #ifdef X_HAVE_UTF8_STRING
595 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
596 style = XUTF8StringStyle;
597 #endif /* ifdef X_HAVE_UTF8_STRING */
601 if (!(mystr = strdup(data)))
604 #ifdef X_HAVE_UTF8_STRING
605 if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
606 &text_prop) == Success)
608 int bufsize = strlen((char *)text_prop.value) + 1;
609 *data_ret = malloc(bufsize);
610 memcpy(*data_ret, text_prop.value, bufsize);
612 XFree(text_prop.value);
617 #else /* ifdef X_HAVE_UTF8_STRING */
618 if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
619 &text_prop) == Success)
621 int bufsize = strlen(text_prop.value) + 1;
622 *data_ret = malloc(bufsize);
623 memcpy(*data_ret, text_prop.value, bufsize);
625 XFree(text_prop.value);
630 #endif /* ifdef X_HAVE_UTF8_STRING */
638 } /* _ecore_x_selection_converter_text */
641 ecore_x_selection_parser_add(const char *target,
642 void *(*func)(const char *target, void *data,
646 Ecore_X_Selection_Parser *prs;
651 LOGFN(__FILE__, __LINE__, __FUNCTION__);
657 if (!strcmp(prs->target, target))
666 prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
671 parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
675 prs->target = strdup(target);
677 } /* ecore_x_selection_parser_add */
680 ecore_x_selection_parser_del(const char *target)
682 Ecore_X_Selection_Parser *prs, *prev_prs;
687 LOGFN(__FILE__, __LINE__, __FUNCTION__);
693 if (!strcmp(prs->target, target))
696 prev_prs->next = prs->next;
699 parsers = prs->next; /* This was the first parser */
711 } /* ecore_x_selection_parser_del */
713 /* Locate and run conversion callback for specified selection target */
715 _ecore_x_selection_parse(const char *target, void *data, int size, int format)
717 Ecore_X_Selection_Parser *prs;
718 Ecore_X_Selection_Data *sel;
720 for (prs = parsers; prs; prs = prs->next)
722 if (!strcmp(prs->target, target))
724 sel = prs->parse(target, data, size, format);
729 /* Default, just return the data */
730 sel = calloc(1, sizeof(Ecore_X_Selection_Data));
731 sel->free = _ecore_x_selection_data_default_free;
733 sel->format = format;
736 } /* _ecore_x_selection_parse */
739 _ecore_x_selection_data_default_free(void *data)
741 Ecore_X_Selection_Data *sel;
747 } /* _ecore_x_selection_data_default_free */
750 _ecore_x_selection_parser_files(const char *target,
753 int format __UNUSED__)
755 Ecore_X_Selection_Data_Files *sel;
760 if (strcmp(target, "text/uri-list") &&
761 strcmp(target, "_NETSCAPE_URL"))
764 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
765 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
769 /* Isn't nul terminated */
771 data = realloc(data, size);
778 while ((is < size) && (data[is]))
780 if ((i == 0) && (data[is] == '#'))
781 for (; ((data[is]) && (data[is] != '\n')); is++) ;
784 if ((data[is] != '\r') &&
786 tmp[i++] = data[is++];
789 while ((data[is] == '\r') || (data[is] == '\n')) is++;
793 realloc(sel->files, sel->num_files * sizeof(char *));
794 sel->files[sel->num_files - 1] = strdup(tmp);
804 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
805 sel->files[sel->num_files - 1] = strdup(tmp);
811 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
812 ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
814 return ECORE_X_SELECTION_DATA(sel);
815 } /* _ecore_x_selection_parser_files */
818 _ecore_x_selection_data_files_free(void *data)
820 Ecore_X_Selection_Data_Files *sel;
826 for (i = 0; i < sel->num_files; i++)
833 } /* _ecore_x_selection_data_files_free */
836 _ecore_x_selection_parser_text(const char *target __UNUSED__,
839 int format __UNUSED__)
841 Ecore_X_Selection_Data_Text *sel;
842 unsigned char *data = _data;
844 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
848 /* Isn't nul terminated */
850 data = realloc(data, size);
854 sel->text = (char *)data;
855 ECORE_X_SELECTION_DATA(sel)->length = size;
856 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
857 ECORE_X_SELECTION_DATA(sel)->data = data;
858 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
860 } /* _ecore_x_selection_parser_text */
863 _ecore_x_selection_data_text_free(void *data)
865 Ecore_X_Selection_Data_Text *sel;
871 } /* _ecore_x_selection_data_text_free */
874 _ecore_x_selection_parser_targets(const char *target __UNUSED__,
877 int format __UNUSED__)
879 Ecore_X_Selection_Data_Targets *sel;
880 unsigned long *targets;
883 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
884 targets = (unsigned long *)data;
886 sel->num_targets = size - 2;
887 sel->targets = malloc((size - 2) * sizeof(char *));
888 for (i = 2; i < size; i++)
889 sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
891 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
892 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
893 ECORE_X_SELECTION_DATA(sel)->length = size;
894 ECORE_X_SELECTION_DATA(sel)->data = data;
896 } /* _ecore_x_selection_parser_targets */
899 _ecore_x_selection_data_targets_free(void *data)
901 Ecore_X_Selection_Data_Targets *sel;
908 for (i = 0; i < sel->num_targets; i++)
909 XFree(sel->targets[i]);
913 free(ECORE_X_SELECTION_DATA(sel)->data);
916 } /* _ecore_x_selection_data_targets_free */