1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25#include "config.h"
26
27#include "gdkselection.h"
28
29#include "gdkproperty.h"
30#include "gdkdisplayprivate.h"
31
32
33/**
34 * SECTION:selections
35 * @Short_description: Functions for transfering data via the X selection mechanism
36 * @Title: Selections
37 *
38 * The X selection mechanism provides a way to transfer arbitrary chunks of
39 * data between programs. A “selection” is a essentially
40 * a named clipboard, identified by a string interned as a #GdkAtom. By
41 * claiming ownership of a selection, an application indicates that it will
42 * be responsible for supplying its contents. The most common selections are
43 * `PRIMARY` and `CLIPBOARD`.
44 *
45 * The contents of a selection can be represented in a number of formats,
46 * called “targets”. Each target is identified by an atom.
47 * A list of all possible targets supported by the selection owner can be
48 * retrieved by requesting the special target `TARGETS`. When
49 * a selection is retrieved, the data is accompanied by a type (an atom), and
50 * a format (an integer, representing the number of bits per item).
51 * See [Properties and Atoms][gdk3-Properties-and-Atoms]
52 * for more information.
53 *
54 * The functions in this section only contain the lowlevel parts of the
55 * selection protocol. A considerably more complicated implementation is needed
56 * on top of this. GTK+ contains such an implementation in the functions in
57 * `gtkselection.h` and programmers should use those functions
58 * instead of the ones presented here. If you plan to implement selection
59 * handling directly on top of the functions here, you should refer to the
60 * X Inter-client Communication Conventions Manual (ICCCM).
61 */
62
63/**
64 * gdk_selection_owner_set:
65 * @owner: (allow-none): a #GdkWindow or %NULL to indicate that the
66 * the owner for the given should be unset.
67 * @selection: an atom identifying a selection.
68 * @time_: timestamp to use when setting the selection.
69 * If this is older than the timestamp given last
70 * time the owner was set for the given selection, the
71 * request will be ignored.
72 * @send_event: if %TRUE, and the new owner is different
73 * from the current owner, the current owner
74 * will be sent a SelectionClear event.
75 *
76 * Sets the owner of the given selection.
77 *
78 * Returns: %TRUE if the selection owner was successfully
79 * changed to @owner, otherwise %FALSE.
80 */
81gboolean
82gdk_selection_owner_set (GdkWindow *owner,
83 GdkAtom selection,
84 guint32 time,
85 gboolean send_event)
86{
87 return gdk_selection_owner_set_for_display (gdk_display_get_default (),
88 owner, selection,
89 time, send_event);
90}
91
92/**
93 * gdk_selection_owner_get:
94 * @selection: an atom indentifying a selection.
95 *
96 * Determines the owner of the given selection.
97 *
98 * Returns: (nullable) (transfer none): if there is a selection owner
99 * for this window, and it is a window known to the current process,
100 * the #GdkWindow that owns the selection, otherwise %NULL. Note
101 * that the return value may be owned by a different process if a
102 * foreign window was previously created for that window, but a new
103 * foreign window will never be created by this call.
104 */
105GdkWindow*
106gdk_selection_owner_get (GdkAtom selection)
107{
108 return gdk_selection_owner_get_for_display (gdk_display_get_default (),
109 selection);
110}
111
112/**
113 * gdk_selection_send_notify:
114 * @requestor: window to which to deliver response.
115 * @selection: selection that was requested.
116 * @target: target that was selected.
117 * @property: property in which the selection owner stored the
118 * data, or %GDK_NONE to indicate that the request
119 * was rejected.
120 * @time_: timestamp.
121 *
122 * Sends a response to SelectionRequest event.
123 */
124void
125gdk_selection_send_notify (GdkWindow *requestor,
126 GdkAtom selection,
127 GdkAtom target,
128 GdkAtom property,
129 guint32 time)
130{
131 gdk_selection_send_notify_for_display (gdk_window_get_display (requestor),
132 requestor, selection,
133 target, property, time);
134}
135
136/**
137 * gdk_selection_owner_set_for_display:
138 * @display: the #GdkDisplay
139 * @owner: (nullable): a #GdkWindow or %NULL to indicate that the owner for
140 * the given should be unset
141 * @selection: an atom identifying a selection
142 * @time_: timestamp to use when setting the selection
143 * If this is older than the timestamp given last time the owner was
144 * set for the given selection, the request will be ignored
145 * @send_event: if %TRUE, and the new owner is different from the current
146 * owner, the current owner will be sent a SelectionClear event
147 *
148 * Sets the #GdkWindow @owner as the current owner of the selection @selection.
149 *
150 * Returns: %TRUE if the selection owner was successfully changed to owner,
151 * otherwise %FALSE.
152 *
153 * Since: 2.2
154 */
155gboolean
156gdk_selection_owner_set_for_display (GdkDisplay *display,
157 GdkWindow *owner,
158 GdkAtom selection,
159 guint32 time,
160 gboolean send_event)
161{
162 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
163 g_return_val_if_fail (selection != GDK_NONE, FALSE);
164
165 return GDK_DISPLAY_GET_CLASS (display)
166 ->set_selection_owner (display, owner, selection, time, send_event);
167}
168
169/**
170 * gdk_selection_owner_get_for_display:
171 * @display: a #GdkDisplay
172 * @selection: an atom indentifying a selection
173 *
174 * Determine the owner of the given selection.
175 *
176 * Note that the return value may be owned by a different
177 * process if a foreign window was previously created for that
178 * window, but a new foreign window will never be created by this call.
179 *
180 * Returns: (nullable) (transfer none): if there is a selection owner
181 * for this window, and it is a window known to the current
182 * process, the #GdkWindow that owns the selection, otherwise
183 * %NULL.
184 *
185 * Since: 2.2
186 */
187GdkWindow *
188gdk_selection_owner_get_for_display (GdkDisplay *display,
189 GdkAtom selection)
190{
191 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
192 g_return_val_if_fail (selection != GDK_NONE, NULL);
193
194 return GDK_DISPLAY_GET_CLASS (display)->get_selection_owner (display, selection);
195}
196
197/**
198 * gdk_selection_send_notify_for_display:
199 * @display: the #GdkDisplay where @requestor is realized
200 * @requestor: window to which to deliver response
201 * @selection: selection that was requested
202 * @target: target that was selected
203 * @property: property in which the selection owner stored the data,
204 * or %GDK_NONE to indicate that the request was rejected
205 * @time_: timestamp
206 *
207 * Send a response to SelectionRequest event.
208 *
209 * Since: 2.2
210 */
211void
212gdk_selection_send_notify_for_display (GdkDisplay *display,
213 GdkWindow *requestor,
214 GdkAtom selection,
215 GdkAtom target,
216 GdkAtom property,
217 guint32 time_)
218{
219 g_return_if_fail (GDK_IS_DISPLAY (display));
220
221 GDK_DISPLAY_GET_CLASS (display)
222 ->send_selection_notify (display, requestor, selection,target, property, time_);
223}
224
225/**
226 * gdk_selection_property_get: (skip)
227 * @requestor: the window on which the data is stored
228 * @data: location to store a pointer to the retrieved data.
229 If the retrieval failed, %NULL we be stored here, otherwise, it
230 will be non-%NULL and the returned data should be freed with g_free()
231 when you are finished using it. The length of the
232 allocated memory is one more than the length
233 of the returned data, and the final byte will always
234 be zero, to ensure nul-termination of strings
235 * @prop_type: location to store the type of the property
236 * @prop_format: location to store the format of the property
237 *
238 * Retrieves selection data that was stored by the selection
239 * data in response to a call to gdk_selection_convert(). This function
240 * will not be used by applications, who should use the #GtkClipboard
241 * API instead.
242 *
243 * Returns: the length of the retrieved data.
244 */
245gint
246gdk_selection_property_get (GdkWindow *requestor,
247 guchar **data,
248 GdkAtom *ret_type,
249 gint *ret_format)
250{
251 GdkDisplay *display;
252
253 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
254
255 display = gdk_window_get_display (requestor);
256
257 return GDK_DISPLAY_GET_CLASS (display)
258 ->get_selection_property (display, requestor, data, ret_type, ret_format);
259}
260
261void
262gdk_selection_convert (GdkWindow *requestor,
263 GdkAtom selection,
264 GdkAtom target,
265 guint32 time)
266{
267 GdkDisplay *display;
268
269 g_return_if_fail (selection != GDK_NONE);
270
271 display = gdk_window_get_display (requestor);
272
273 GDK_DISPLAY_GET_CLASS (display)
274 ->convert_selection (display, requestor, selection, target, time);
275}
276
277/**
278 * gdk_text_property_to_utf8_list_for_display:
279 * @display: a #GdkDisplay
280 * @encoding: an atom representing the encoding of the text
281 * @format: the format of the property
282 * @text: (array length=length): the text to convert
283 * @length: the length of @text, in bytes
284 * @list: (out) (array zero-terminated=1): location to store the list
285 * of strings or %NULL. The list should be freed with
286 * g_strfreev().
287 *
288 * Converts a text property in the given encoding to
289 * a list of UTF-8 strings.
290 *
291 * Returns: the number of strings in the resulting list
292 *
293 * Since: 2.2
294 */
295gint
296gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
297 GdkAtom encoding,
298 gint format,
299 const guchar *text,
300 gint length,
301 gchar ***list)
302{
303 g_return_val_if_fail (text != NULL, 0);
304 g_return_val_if_fail (length >= 0, 0);
305 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
306
307 return GDK_DISPLAY_GET_CLASS (display)
308 ->text_property_to_utf8_list (display, encoding, format, text, length, list);
309}
310
311/**
312 * gdk_utf8_to_string_target:
313 * @str: a UTF-8 string
314 *
315 * Converts an UTF-8 string into the best possible representation
316 * as a STRING. The representation of characters not in STRING
317 * is not specified; it may be as pseudo-escape sequences
318 * \x{ABCD}, or it may be in some other form of approximation.
319 *
320 * Returns: (nullable): the newly-allocated string, or %NULL if the
321 * conversion failed. (It should not fail for any properly
322 * formed UTF-8 string unless system limits like memory or
323 * file descriptors are exceeded.)
324 **/
325gchar *
326gdk_utf8_to_string_target (const gchar *str)
327{
328 GdkDisplay *display = gdk_display_get_default ();
329
330 return GDK_DISPLAY_GET_CLASS (display)->utf8_to_string_target (display, str);
331}
332