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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team.
23 */
24
25 /*
26 * GTK+ DirectFB backend
27 * Copyright (C) 2001-2002 convergence integrated media GmbH
28 * Copyright (C) 2002-2004 convergence GmbH
29 * Written by Denis Oliver Kropp <dok@convergence.de> and
30 * Sven Neumann <sven@convergence.de>
31 */
32
33 #include "config.h"
34 #include "gdk.h"
35
36 #include <string.h>
37
38 #include "gdkproperty.h"
39
40 #include "gdkdirectfb.h"
41 #include "gdkprivate-directfb.h"
42
43 #include "gdkinternals.h"
44
45 #include "gdkalias.h"
46
47 static GHashTable *names_to_atoms;
48 static GPtrArray *atoms_to_names;
49
50 static const gchar xatoms_string[] =
51 /* These are all the standard predefined X atoms */
52 "NONE\0"
53 "PRIMARY\0"
54 "SECONDARY\0"
55 "ARC\0"
56 "ATOM\0"
57 "BITMAP\0"
58 "CARDINAL\0"
59 "COLORMAP\0"
60 "CURSOR\0"
61 "CUT_BUFFER0\0"
62 "CUT_BUFFER1\0"
63 "CUT_BUFFER2\0"
64 "CUT_BUFFER3\0"
65 "CUT_BUFFER4\0"
66 "CUT_BUFFER5\0"
67 "CUT_BUFFER6\0"
68 "CUT_BUFFER7\0"
69 "DRAWABLE\0"
70 "FONT\0"
71 "INTEGER\0"
72 "PIXMAP\0"
73 "POINT\0"
74 "RECTANGLE\0"
75 "RESOURCE_MANAGER\0"
76 "RGB_COLOR_MAP\0"
77 "RGB_BEST_MAP\0"
78 "RGB_BLUE_MAP\0"
79 "RGB_DEFAULT_MAP\0"
80 "RGB_GRAY_MAP\0"
81 "RGB_GREEN_MAP\0"
82 "RGB_RED_MAP\0"
83 "STRING\0"
84 "VISUALID\0"
85 "WINDOW\0"
86 "WM_COMMAND\0"
87 "WM_HINTS\0"
88 "WM_CLIENT_MACHINE\0"
89 "WM_ICON_NAME\0"
90 "WM_ICON_SIZE\0"
91 "WM_NAME\0"
92 "WM_NORMAL_HINTS\0"
93 "WM_SIZE_HINTS\0"
94 "WM_ZOOM_HINTS\0"
95 "MIN_SPACE\0"
96 "NORM_SPACE\0"
97 "MAX_SPACE\0"
98 "END_SPACE\0"
99 "SUPERSCRIPT_X\0"
100 "SUPERSCRIPT_Y\0"
101 "SUBSCRIPT_X\0"
102 "SUBSCRIPT_Y\0"
103 "UNDERLINE_POSITION\0"
104 "UNDERLINE_THICKNESS\0"
105 "STRIKEOUT_ASCENT\0"
106 "STRIKEOUT_DESCENT\0"
107 "ITALIC_ANGLE\0"
108 "X_HEIGHT\0"
109 "QUAD_WIDTH\0"
110 "WEIGHT\0"
111 "POINT_SIZE\0"
112 "RESOLUTION\0"
113 "COPYRIGHT\0"
114 "NOTICE\0"
115 "FONT_NAME\0"
116 "FAMILY_NAME\0"
117 "FULL_NAME\0"
118 "CAP_HEIGHT\0"
119 "WM_CLASS\0"
120 "WM_TRANSIENT_FOR\0"
121 ;
122
123 static const gint xatoms_offset[] = {
124 0, 5, 13, 23, 27, 32, 39, 48, 57, 64, 76, 88,
125 100, 112, 124, 136, 148, 160, 169, 174, 182, 189, 195, 205,
126 222, 236, 249, 262, 278, 291, 305, 317, 324, 333, 340, 351,
127 360, 378, 391, 404, 412, 428, 442, 456, 466, 477, 487, 497,
128 511, 525, 537, 549, 568, 588, 605, 623, 636, 645, 656, 663,
129 674, 685, 695, 702, 712, 724, 734, 745, 754
130 };
131
132 #define N_CUSTOM_PREDEFINED 1
133
134 static void
ensure_atom_tables(void)135 ensure_atom_tables (void)
136 {
137 int i;
138
139 if (names_to_atoms)
140 return;
141
142 names_to_atoms = g_hash_table_new (g_str_hash, g_str_equal);
143 atoms_to_names = g_ptr_array_sized_new (G_N_ELEMENTS (xatoms_offset));
144
145 for (i = 0; i < G_N_ELEMENTS (xatoms_offset); i++)
146 {
147 g_hash_table_insert (names_to_atoms,
148 (gchar *)xatoms_string + xatoms_offset[i],
149 GINT_TO_POINTER (i));
150 g_ptr_array_add (atoms_to_names,
151 (gchar *)xatoms_string + xatoms_offset[i]);
152 }
153 }
154
155 static GdkAtom
intern_atom_internal(const gchar * atom_name,gboolean allocate)156 intern_atom_internal (const gchar *atom_name, gboolean allocate)
157 {
158 gpointer result;
159 gchar *name;
160
161 g_return_val_if_fail (atom_name != NULL, GDK_NONE);
162
163 ensure_atom_tables ();
164
165 if (g_hash_table_lookup_extended (names_to_atoms, atom_name, NULL, &result))
166 return result;
167
168 result = GINT_TO_POINTER (atoms_to_names->len);
169 name = allocate ? g_strdup (atom_name) : (gchar *)atom_name;
170 g_hash_table_insert (names_to_atoms, name, result);
171 g_ptr_array_add (atoms_to_names, name);
172
173 return result;
174 }
175
176 GdkAtom
gdk_atom_intern(const gchar * atom_name,gboolean only_if_exists)177 gdk_atom_intern (const gchar *atom_name,
178 gboolean only_if_exists)
179 {
180 return intern_atom_internal (atom_name, TRUE);
181 }
182
183 GdkAtom
gdk_atom_intern_static_string(const gchar * atom_name)184 gdk_atom_intern_static_string (const gchar *atom_name)
185 {
186 return intern_atom_internal (atom_name, FALSE);
187 }
188
189
190 gchar *
gdk_atom_name(GdkAtom atom)191 gdk_atom_name (GdkAtom atom)
192 {
193 if (!atoms_to_names)
194 return NULL;
195
196 if (GPOINTER_TO_INT (atom) >= atoms_to_names->len)
197 return NULL;
198
199 return g_strdup (g_ptr_array_index (atoms_to_names, GPOINTER_TO_INT (atom)));
200 }
201
202
203 static void
gdk_property_delete_2(GdkWindow * window,GdkAtom property,GdkWindowProperty * prop)204 gdk_property_delete_2 (GdkWindow *window,
205 GdkAtom property,
206 GdkWindowProperty *prop)
207 {
208 GdkWindowImplDirectFB *impl;
209 GdkEvent *event;
210 GdkWindow *event_window;
211
212 impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
213
214 g_hash_table_remove (impl->properties, GUINT_TO_POINTER (property));
215 g_free (prop);
216
217 event_window = gdk_directfb_other_event_window (window, GDK_PROPERTY_NOTIFY);
218
219 if (event_window)
220 {
221 event = gdk_directfb_event_make (event_window, GDK_PROPERTY_NOTIFY);
222 event->property.atom = property;
223 event->property.state = GDK_PROPERTY_DELETE;
224 }
225 }
226
227 void
gdk_property_delete(GdkWindow * window,GdkAtom property)228 gdk_property_delete (GdkWindow *window,
229 GdkAtom property)
230 {
231 GdkWindowImplDirectFB *impl;
232 GdkWindowProperty *prop;
233
234 g_return_if_fail (GDK_IS_WINDOW (window));
235
236 impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
237
238 if (!impl->properties)
239 return;
240
241 prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
242 if (!prop)
243 return;
244
245 gdk_property_delete_2 (window, property, prop);
246 }
247
248 gboolean
gdk_property_get(GdkWindow * window,GdkAtom property,GdkAtom type,gulong offset,gulong length,gint pdelete,GdkAtom * actual_property_type,gint * actual_format_type,gint * actual_length,guchar ** data)249 gdk_property_get (GdkWindow *window,
250 GdkAtom property,
251 GdkAtom type,
252 gulong offset,
253 gulong length,
254 gint pdelete,
255 GdkAtom *actual_property_type,
256 gint *actual_format_type,
257 gint *actual_length,
258 guchar **data)
259 {
260 GdkWindowImplDirectFB *impl;
261 GdkWindowProperty *prop;
262 gint nbytes = 0;
263
264 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
265 g_return_val_if_fail (data != NULL, FALSE);
266
267 if (!window)
268 window = _gdk_parent_root;
269
270 if (GDK_WINDOW_DESTROYED (window))
271 return FALSE;
272
273 impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
274
275 if (!impl->properties)
276 return FALSE;
277
278 prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
279 if (!prop)
280 {
281 if (actual_property_type)
282 *actual_property_type = GDK_NONE;
283 return FALSE;
284 }
285
286 nbytes = CLAMP (length, 0, prop->length - offset * 4);
287
288 if (nbytes > 0 &&
289 (prop->type == 0 /* AnyPropertyType */ || prop->type == type))
290 {
291 *data = g_malloc (nbytes + 1);
292 memcpy (*data, prop->data + offset, nbytes);
293 (*data)[nbytes] = 0;
294 }
295 else
296 {
297 *data = NULL;
298 }
299
300 if (actual_length)
301 *actual_length = nbytes;
302 if (actual_property_type)
303 *actual_property_type = prop->type;
304 if (actual_format_type)
305 *actual_format_type = prop->format;
306
307 /* only delete the property if it was completely retrieved */
308 if (pdelete && length >= *actual_length && *data != NULL)
309 {
310 gdk_property_delete_2 (window, property, prop);
311 }
312
313 return TRUE;
314 }
315
316 void
gdk_property_change(GdkWindow * window,GdkAtom property,GdkAtom type,gint format,GdkPropMode mode,const guchar * data,gint nelements)317 gdk_property_change (GdkWindow *window,
318 GdkAtom property,
319 GdkAtom type,
320 gint format,
321 GdkPropMode mode,
322 const guchar *data,
323 gint nelements)
324 {
325 GdkWindowImplDirectFB *impl;
326 GdkWindowProperty *prop;
327 GdkWindowProperty *new_prop;
328 gint new_size = 0;
329 GdkEvent *event;
330 GdkWindow *event_window;
331
332 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
333
334 if (!window)
335 window = _gdk_parent_root;
336
337 if (GDK_WINDOW_DESTROYED (window))
338 return;
339
340 impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
341
342 if (!impl->properties)
343 impl->properties = g_hash_table_new (NULL, NULL);
344
345 prop = g_hash_table_lookup (impl->properties, GUINT_TO_POINTER (property));
346
347 switch (mode)
348 {
349 case GDK_PROP_MODE_REPLACE:
350 new_size = nelements * (format >> 3);
351 break;
352
353 case GDK_PROP_MODE_PREPEND:
354 case GDK_PROP_MODE_APPEND:
355 new_size = nelements * (format >> 3);
356 if (prop)
357 {
358 if (type != prop->type || format != prop->format)
359 return;
360 new_size += prop->length;
361 }
362 break;
363 }
364
365 new_prop = g_malloc (G_STRUCT_OFFSET (GdkWindowProperty, data) + new_size);
366 new_prop->length = new_size;
367 new_prop->type = type;
368 new_prop->format = format;
369
370 switch (mode)
371 {
372 case GDK_PROP_MODE_REPLACE:
373 memcpy (new_prop->data, data, new_size);
374 break;
375
376 case GDK_PROP_MODE_APPEND:
377 if (prop)
378 memcpy (new_prop->data, prop->data, prop->length);
379 memcpy (new_prop->data + new_prop->length,
380 data, (nelements * (format >> 3)));
381 break;
382
383 case GDK_PROP_MODE_PREPEND:
384 memcpy (new_prop->data, data, (nelements * (format >> 3)));
385 if (prop)
386 memcpy (new_prop->data + (nelements * (format >> 3)),
387 prop->data, prop->length);
388 break;
389 }
390
391 g_hash_table_insert (impl->properties,
392 GUINT_TO_POINTER (property), new_prop);
393 g_free (prop);
394
395 event_window = gdk_directfb_other_event_window (window, GDK_PROPERTY_NOTIFY);
396
397 if (event_window)
398 {
399 event = gdk_directfb_event_make (event_window, GDK_PROPERTY_NOTIFY);
400 event->property.atom = property;
401 event->property.state = GDK_PROPERTY_NEW_VALUE;
402 }
403 }
404
405 #define __GDK_PROPERTY_X11_C__
406 #include "gdkaliasdef.c"
407