File: | core/xprops.c |
Warning: | line 474, column 7 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | |||
2 | ||||
3 | /* Croma X property convenience routines */ | |||
4 | ||||
5 | /* | |||
6 | * Copyright (C) 2001 Havoc Pennington | |||
7 | * Copyright (C) 2002 Red Hat Inc. | |||
8 | * | |||
9 | * Some trivial property-unpacking code from Xlib: | |||
10 | * Copyright 1987, 1988, 1998 The Open Group | |||
11 | * Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, | |||
12 | * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, | |||
13 | * | |||
14 | * This program is free software; you can redistribute it and/or | |||
15 | * modify it under the terms of the GNU General Public License as | |||
16 | * published by the Free Software Foundation; either version 2 of the | |||
17 | * License, or (at your option) any later version. | |||
18 | * | |||
19 | * This program is distributed in the hope that it will be useful, but | |||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
22 | * General Public License for more details. | |||
23 | * | |||
24 | * You should have received a copy of the GNU General Public License | |||
25 | * along with this program; if not, write to the Free Software | |||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |||
27 | * 02110-1301, USA. | |||
28 | */ | |||
29 | ||||
30 | /*********************************************************** | |||
31 | Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, | |||
32 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, | |||
33 | ||||
34 | All Rights Reserved | |||
35 | ||||
36 | Permission to use, copy, modify, and distribute this software and its | |||
37 | documentation for any purpose and without fee is hereby granted, | |||
38 | provided that the above copyright notice appear in all copies and that | |||
39 | both that copyright notice and this permission notice appear in | |||
40 | supporting documentation, and that the name Digital not be | |||
41 | used in advertising or publicity pertaining to distribution of the | |||
42 | software without specific, written prior permission. | |||
43 | ||||
44 | DIGITAL AND WYSE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
45 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
46 | EVENT SHALL DIGITAL OR WYSE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
47 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
48 | USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |||
49 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
50 | PERFORMANCE OF THIS SOFTWARE. | |||
51 | ||||
52 | ******************************************************************/ | |||
53 | ||||
54 | /* | |||
55 | ||||
56 | Copyright 1987, 1988, 1998 The Open Group | |||
57 | ||||
58 | Permission to use, copy, modify, distribute, and sell this software and its | |||
59 | documentation for any purpose is hereby granted without fee, provided that | |||
60 | the above copyright notice appear in all copies and that both that | |||
61 | copyright notice and this permission notice appear in supporting | |||
62 | documentation. | |||
63 | ||||
64 | The above copyright notice and this permission notice shall be included | |||
65 | in all copies or substantial portions of the Software. | |||
66 | ||||
67 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
68 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
69 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
70 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
71 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
72 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
73 | OTHER DEALINGS IN THE SOFTWARE. | |||
74 | ||||
75 | Except as contained in this notice, the name of The Open Group shall | |||
76 | not be used in advertising or otherwise to promote the sale, use or | |||
77 | other dealings in this Software without prior written authorization | |||
78 | from The Open Group. | |||
79 | ||||
80 | */ | |||
81 | ||||
82 | ||||
83 | #include <config.h> | |||
84 | #include "xprops.h" | |||
85 | #include "errors.h" | |||
86 | #include "util.h" | |||
87 | #include "async-getprop.h" | |||
88 | #include "ui.h" | |||
89 | #include "croma-Xatomtype.h" | |||
90 | #include <X11/Xatom.h> | |||
91 | #include <string.h> | |||
92 | #include "window-private.h" | |||
93 | ||||
94 | typedef struct | |||
95 | { | |||
96 | MetaDisplay *display; | |||
97 | Window xwindow; | |||
98 | Atom xatom; | |||
99 | Atom type; | |||
100 | int format; | |||
101 | unsigned long n_items; | |||
102 | unsigned long bytes_after; | |||
103 | unsigned char *prop; | |||
104 | } GetPropertyResults; | |||
105 | ||||
106 | static gboolean | |||
107 | validate_or_free_results (GetPropertyResults *results, | |||
108 | int expected_format, | |||
109 | Atom expected_type, | |||
110 | gboolean must_have_items) | |||
111 | { | |||
112 | char *type_name; | |||
113 | char *expected_name; | |||
114 | char *prop_name; | |||
115 | const char *title; | |||
116 | const char *res_class; | |||
117 | const char *res_name; | |||
118 | MetaWindow *w; | |||
119 | ||||
120 | if (expected_format == results->format && | |||
121 | expected_type == results->type && | |||
122 | (!must_have_items || results->n_items > 0)) | |||
123 | return TRUE(!(0)); | |||
124 | ||||
125 | meta_error_trap_push (results->display); | |||
126 | type_name = XGetAtomName (results->display->xdisplay, results->type); | |||
127 | expected_name = XGetAtomName (results->display->xdisplay, expected_type); | |||
128 | prop_name = XGetAtomName (results->display->xdisplay, results->xatom); | |||
129 | meta_error_trap_pop (results->display, TRUE(!(0))); | |||
130 | ||||
131 | w = meta_display_lookup_x_window (results->display, results->xwindow); | |||
132 | ||||
133 | if (w != NULL((void*)0)) | |||
134 | { | |||
135 | title = w->title; | |||
136 | res_class = w->res_class; | |||
137 | res_name = w->res_name; | |||
138 | } | |||
139 | else | |||
140 | { | |||
141 | title = NULL((void*)0); | |||
142 | res_class = NULL((void*)0); | |||
143 | res_name = NULL((void*)0); | |||
144 | } | |||
145 | ||||
146 | if (title == NULL((void*)0)) | |||
147 | title = "unknown"; | |||
148 | ||||
149 | if (res_class == NULL((void*)0)) | |||
150 | res_class = "unknown"; | |||
151 | ||||
152 | if (res_name == NULL((void*)0)) | |||
153 | res_name = "unknown"; | |||
154 | ||||
155 | meta_warning (_("Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n")dgettext ("croma", "Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n" ), | |||
156 | results->xwindow, | |||
157 | prop_name ? prop_name : "(bad atom)", | |||
158 | expected_name ? expected_name : "(bad atom)", | |||
159 | expected_format, | |||
160 | type_name ? type_name : "(bad atom)", | |||
161 | results->format, (int) results->n_items, | |||
162 | title, res_class, res_name); | |||
163 | ||||
164 | if (type_name) | |||
165 | XFree (type_name); | |||
166 | if (expected_name) | |||
167 | XFree (expected_name); | |||
168 | if (prop_name) | |||
169 | XFree (prop_name); | |||
170 | ||||
171 | if (results->prop) | |||
172 | { | |||
173 | XFree (results->prop); | |||
174 | results->prop = NULL((void*)0); | |||
175 | } | |||
176 | ||||
177 | return FALSE(0); | |||
178 | } | |||
179 | ||||
180 | static gboolean | |||
181 | get_property (MetaDisplay *display, | |||
182 | Window xwindow, | |||
183 | Atom xatom, | |||
184 | Atom req_type, | |||
185 | GetPropertyResults *results) | |||
186 | { | |||
187 | results->display = display; | |||
188 | results->xwindow = xwindow; | |||
189 | results->xatom = xatom; | |||
190 | results->prop = NULL((void*)0); | |||
191 | results->n_items = 0; | |||
192 | results->type = None0L; | |||
193 | results->bytes_after = 0; | |||
194 | results->format = 0; | |||
195 | ||||
196 | meta_error_trap_push (display); | |||
197 | if (XGetWindowProperty (display->xdisplay, xwindow, xatom, | |||
198 | 0, G_MAXLONG9223372036854775807L, | |||
199 | False0, req_type, &results->type, &results->format, | |||
200 | &results->n_items, | |||
201 | &results->bytes_after, | |||
202 | &results->prop) != Success0 || | |||
203 | results->type == None0L) | |||
204 | { | |||
205 | if (results->prop) | |||
206 | XFree (results->prop); | |||
207 | meta_error_trap_pop_with_return (display, TRUE(!(0))); | |||
208 | return FALSE(0); | |||
209 | } | |||
210 | ||||
211 | if (meta_error_trap_pop_with_return (display, TRUE(!(0))) != Success0) | |||
212 | { | |||
213 | if (results->prop) | |||
214 | XFree (results->prop); | |||
215 | return FALSE(0); | |||
216 | } | |||
217 | ||||
218 | return TRUE(!(0)); | |||
219 | } | |||
220 | ||||
221 | static gboolean | |||
222 | atom_list_from_results (GetPropertyResults *results, | |||
223 | Atom **atoms_p, | |||
224 | int *n_atoms_p) | |||
225 | { | |||
226 | if (!validate_or_free_results (results, 32, XA_ATOM((Atom) 4), FALSE(0))) | |||
227 | return FALSE(0); | |||
228 | ||||
229 | *atoms_p = (Atom*) results->prop; | |||
230 | *n_atoms_p = results->n_items; | |||
231 | results->prop = NULL((void*)0); | |||
232 | ||||
233 | return TRUE(!(0)); | |||
234 | } | |||
235 | ||||
236 | gboolean | |||
237 | meta_prop_get_atom_list (MetaDisplay *display, | |||
238 | Window xwindow, | |||
239 | Atom xatom, | |||
240 | Atom **atoms_p, | |||
241 | int *n_atoms_p) | |||
242 | { | |||
243 | GetPropertyResults results; | |||
244 | ||||
245 | *atoms_p = NULL((void*)0); | |||
246 | *n_atoms_p = 0; | |||
247 | ||||
248 | if (!get_property (display, xwindow, xatom, XA_ATOM((Atom) 4), | |||
249 | &results)) | |||
250 | return FALSE(0); | |||
251 | ||||
252 | return atom_list_from_results (&results, atoms_p, n_atoms_p); | |||
253 | } | |||
254 | ||||
255 | static gboolean | |||
256 | cardinal_list_from_results (GetPropertyResults *results, | |||
257 | gulong **cardinals_p, | |||
258 | int *n_cardinals_p) | |||
259 | { | |||
260 | if (!validate_or_free_results (results, 32, XA_CARDINAL((Atom) 6), FALSE(0))) | |||
261 | return FALSE(0); | |||
262 | ||||
263 | *cardinals_p = (gulong*) results->prop; | |||
264 | *n_cardinals_p = results->n_items; | |||
265 | results->prop = NULL((void*)0); | |||
266 | ||||
267 | #if GLIB_SIZEOF_LONG8 == 8 | |||
268 | /* Xlib sign-extends format=32 items, but we want them unsigned */ | |||
269 | { | |||
270 | int i; | |||
271 | ||||
272 | for (i = 0; i < *n_cardinals_p; i++) | |||
273 | (*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff; | |||
274 | } | |||
275 | #endif | |||
276 | ||||
277 | return TRUE(!(0)); | |||
278 | } | |||
279 | ||||
280 | gboolean | |||
281 | meta_prop_get_cardinal_list (MetaDisplay *display, | |||
282 | Window xwindow, | |||
283 | Atom xatom, | |||
284 | gulong **cardinals_p, | |||
285 | int *n_cardinals_p) | |||
286 | { | |||
287 | GetPropertyResults results; | |||
288 | ||||
289 | *cardinals_p = NULL((void*)0); | |||
290 | *n_cardinals_p = 0; | |||
291 | ||||
292 | if (!get_property (display, xwindow, xatom, XA_CARDINAL((Atom) 6), | |||
293 | &results)) | |||
294 | return FALSE(0); | |||
295 | ||||
296 | return cardinal_list_from_results (&results, cardinals_p, n_cardinals_p); | |||
297 | } | |||
298 | ||||
299 | static gboolean | |||
300 | motif_hints_from_results (GetPropertyResults *results, | |||
301 | Motif_ctkWmHints **hints_p) | |||
302 | { | |||
303 | int real_size, max_size; | |||
304 | #define MAX_ITEMSsizeof (Motif_ctkWmHints)/sizeof (gulong) sizeof (Motif_ctkWmHints)/sizeof (gulong) | |||
305 | ||||
306 | *hints_p = NULL((void*)0); | |||
307 | ||||
308 | if (results->type == None0L || results->n_items <= 0) | |||
309 | { | |||
310 | meta_verbosemeta_verbose_real ("Motif_ctk hints had unexpected type or n_items\n"); | |||
311 | if (results->prop) | |||
312 | { | |||
313 | XFree (results->prop); | |||
314 | results->prop = NULL((void*)0); | |||
315 | } | |||
316 | return FALSE(0); | |||
317 | } | |||
318 | ||||
319 | /* The issue here is that some old crufty code will set a smaller | |||
320 | * Motif_ctkWmHints than the one we expect, apparently. I'm not sure of | |||
321 | * the history behind it. See bug #89841 for example. | |||
322 | */ | |||
323 | *hints_p = ag_Xmalloc (sizeof (Motif_ctkWmHints)); | |||
324 | if (*hints_p == NULL((void*)0)) | |||
325 | { | |||
326 | if (results->prop) | |||
327 | { | |||
328 | XFree (results->prop); | |||
329 | results->prop = NULL((void*)0); | |||
330 | } | |||
331 | return FALSE(0); | |||
332 | } | |||
333 | real_size = results->n_items * sizeof (gulong); | |||
334 | max_size = MAX_ITEMSsizeof (Motif_ctkWmHints)/sizeof (gulong) * sizeof (gulong); | |||
335 | memcpy (*hints_p, results->prop, MIN (real_size, max_size)(((real_size) < (max_size)) ? (real_size) : (max_size))); | |||
336 | ||||
337 | if (results->prop) | |||
338 | { | |||
339 | XFree (results->prop); | |||
340 | results->prop = NULL((void*)0); | |||
341 | } | |||
342 | ||||
343 | return TRUE(!(0)); | |||
344 | } | |||
345 | ||||
346 | gboolean | |||
347 | meta_prop_get_motif_hints (MetaDisplay *display, | |||
348 | Window xwindow, | |||
349 | Atom xatom, | |||
350 | Motif_ctkWmHints **hints_p) | |||
351 | { | |||
352 | GetPropertyResults results; | |||
353 | ||||
354 | *hints_p = NULL((void*)0); | |||
355 | ||||
356 | if (!get_property (display, xwindow, xatom, AnyPropertyType0L, | |||
357 | &results)) | |||
358 | return FALSE(0); | |||
359 | ||||
360 | return motif_hints_from_results (&results, hints_p); | |||
361 | } | |||
362 | ||||
363 | static gboolean | |||
364 | latin1_string_from_results (GetPropertyResults *results, | |||
365 | char **str_p) | |||
366 | { | |||
367 | *str_p = NULL((void*)0); | |||
368 | ||||
369 | if (!validate_or_free_results (results, 8, XA_STRING((Atom) 31), FALSE(0))) | |||
370 | return FALSE(0); | |||
371 | ||||
372 | *str_p = (char*) results->prop; | |||
373 | results->prop = NULL((void*)0); | |||
374 | ||||
375 | return TRUE(!(0)); | |||
376 | } | |||
377 | ||||
378 | gboolean | |||
379 | meta_prop_get_latin1_string (MetaDisplay *display, | |||
380 | Window xwindow, | |||
381 | Atom xatom, | |||
382 | char **str_p) | |||
383 | { | |||
384 | GetPropertyResults results; | |||
385 | ||||
386 | *str_p = NULL((void*)0); | |||
387 | ||||
388 | if (!get_property (display, xwindow, xatom, XA_STRING((Atom) 31), | |||
389 | &results)) | |||
390 | return FALSE(0); | |||
391 | ||||
392 | return latin1_string_from_results (&results, str_p); | |||
393 | } | |||
394 | ||||
395 | static gboolean | |||
396 | utf8_string_from_results (GetPropertyResults *results, | |||
397 | char **str_p) | |||
398 | { | |||
399 | *str_p = NULL((void*)0); | |||
400 | ||||
401 | if (!validate_or_free_results (results, 8, | |||
402 | results->display->atom_UTF8_STRING, FALSE(0))) | |||
403 | return FALSE(0); | |||
404 | ||||
405 | if (results->n_items > 0 && | |||
406 | !g_utf8_validate ((gchar *)results->prop, results->n_items, NULL((void*)0))) | |||
407 | { | |||
408 | char *name; | |||
409 | ||||
410 | name = XGetAtomName (results->display->xdisplay, results->xatom); | |||
411 | meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n")dgettext ("croma", "Property %s on window 0x%lx contained invalid UTF-8\n" ), | |||
412 | name, results->xwindow); | |||
413 | meta_XFree (name)do { if ((name)) XFree ((name)); } while (0); | |||
414 | XFree (results->prop); | |||
415 | results->prop = NULL((void*)0); | |||
416 | ||||
417 | return FALSE(0); | |||
418 | } | |||
419 | ||||
420 | *str_p = (char*) results->prop; | |||
421 | results->prop = NULL((void*)0); | |||
422 | ||||
423 | return TRUE(!(0)); | |||
424 | } | |||
425 | ||||
426 | gboolean | |||
427 | meta_prop_get_utf8_string (MetaDisplay *display, | |||
428 | Window xwindow, | |||
429 | Atom xatom, | |||
430 | char **str_p) | |||
431 | { | |||
432 | GetPropertyResults results; | |||
433 | ||||
434 | *str_p = NULL((void*)0); | |||
435 | ||||
436 | if (!get_property (display, xwindow, xatom, | |||
437 | display->atom_UTF8_STRING, | |||
438 | &results)) | |||
439 | return FALSE(0); | |||
440 | ||||
441 | return utf8_string_from_results (&results, str_p); | |||
442 | } | |||
443 | ||||
444 | /* this one freakishly returns g_malloc memory */ | |||
445 | static gboolean | |||
446 | utf8_list_from_results (GetPropertyResults *results, | |||
447 | char ***str_p, | |||
448 | int *n_str_p) | |||
449 | { | |||
450 | int i; | |||
451 | int n_strings; | |||
452 | char **retval; | |||
453 | const char *p; | |||
454 | ||||
455 | *str_p = NULL((void*)0); | |||
456 | *n_str_p = 0; | |||
457 | ||||
458 | if (!validate_or_free_results (results, 8, | |||
459 | results->display->atom_UTF8_STRING, FALSE(0))) | |||
460 | return FALSE(0); | |||
461 | ||||
462 | /* I'm not sure this is right, but I'm guessing the | |||
463 | * property is nul-separated | |||
464 | */ | |||
465 | i = 0; | |||
466 | n_strings = 0; | |||
467 | while (i < (int) results->n_items) | |||
468 | { | |||
469 | if (results->prop[i] == '\0') | |||
470 | ++n_strings; | |||
471 | ++i; | |||
472 | } | |||
473 | ||||
474 | if (results->prop[results->n_items - 1] != '\0') | |||
| ||||
475 | ++n_strings; | |||
476 | ||||
477 | /* we're guaranteed that results->prop has a nul on the end | |||
478 | * by XGetWindowProperty | |||
479 | */ | |||
480 | ||||
481 | retval = g_new0 (char*, n_strings + 1)((char* *) g_malloc0_n ((n_strings + 1), sizeof (char*))); | |||
482 | ||||
483 | p = (char *)results->prop; | |||
484 | i = 0; | |||
485 | while (i < n_strings) | |||
486 | { | |||
487 | if (!g_utf8_validate (p, -1, NULL((void*)0))) | |||
488 | { | |||
489 | char *name; | |||
490 | ||||
491 | meta_error_trap_push (results->display); | |||
492 | name = XGetAtomName (results->display->xdisplay, results->xatom); | |||
493 | meta_error_trap_pop (results->display, TRUE(!(0))); | |||
494 | meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n")dgettext ("croma", "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" ), | |||
495 | name, results->xwindow, i); | |||
496 | meta_XFree (name)do { if ((name)) XFree ((name)); } while (0); | |||
497 | meta_XFree (results->prop)do { if ((results->prop)) XFree ((results->prop)); } while (0); | |||
498 | results->prop = NULL((void*)0); | |||
499 | ||||
500 | g_strfreev (retval); | |||
501 | return FALSE(0); | |||
502 | } | |||
503 | ||||
504 | retval[i] = g_strdup (p); | |||
505 | ||||
506 | p = p + strlen (p) + 1; | |||
507 | ++i; | |||
508 | } | |||
509 | ||||
510 | *str_p = retval; | |||
511 | *n_str_p = i; | |||
512 | ||||
513 | meta_XFree (results->prop)do { if ((results->prop)) XFree ((results->prop)); } while (0); | |||
514 | results->prop = NULL((void*)0); | |||
515 | ||||
516 | return TRUE(!(0)); | |||
517 | } | |||
518 | ||||
519 | /* returns g_malloc not Xmalloc memory */ | |||
520 | gboolean | |||
521 | meta_prop_get_utf8_list (MetaDisplay *display, | |||
522 | Window xwindow, | |||
523 | Atom xatom, | |||
524 | char ***str_p, | |||
525 | int *n_str_p) | |||
526 | { | |||
527 | GetPropertyResults results; | |||
528 | ||||
529 | *str_p = NULL((void*)0); | |||
530 | ||||
531 | if (!get_property (display, xwindow, xatom, | |||
532 | display->atom_UTF8_STRING, | |||
533 | &results)) | |||
534 | return FALSE(0); | |||
535 | ||||
536 | return utf8_list_from_results (&results, str_p, n_str_p); | |||
537 | } | |||
538 | ||||
539 | void | |||
540 | meta_prop_set_utf8_string_hint (MetaDisplay *display, | |||
541 | Window xwindow, | |||
542 | Atom atom, | |||
543 | const char *val) | |||
544 | { | |||
545 | meta_error_trap_push (display); | |||
546 | XChangeProperty (display->xdisplay, | |||
547 | xwindow, atom, | |||
548 | display->atom_UTF8_STRING, | |||
549 | 8, PropModeReplace0, (guchar*) val, strlen (val)); | |||
550 | meta_error_trap_pop (display, FALSE(0)); | |||
551 | } | |||
552 | ||||
553 | static gboolean | |||
554 | window_from_results (GetPropertyResults *results, | |||
555 | Window *window_p) | |||
556 | { | |||
557 | if (!validate_or_free_results (results, 32, XA_WINDOW((Atom) 33), TRUE(!(0)))) | |||
558 | return FALSE(0); | |||
559 | ||||
560 | *window_p = *(Window*) results->prop; | |||
561 | XFree (results->prop); | |||
562 | results->prop = NULL((void*)0); | |||
563 | ||||
564 | return TRUE(!(0)); | |||
565 | } | |||
566 | ||||
567 | #ifdef HAVE_XSYNC | |||
568 | static gboolean | |||
569 | counter_from_results (GetPropertyResults *results, | |||
570 | XSyncCounter *counter_p) | |||
571 | { | |||
572 | if (!validate_or_free_results (results, 32, | |||
573 | XA_CARDINAL((Atom) 6), | |||
574 | TRUE(!(0)))) | |||
575 | return FALSE(0); | |||
576 | ||||
577 | *counter_p = *(XSyncCounter*) results->prop; | |||
578 | XFree (results->prop); | |||
579 | results->prop = NULL((void*)0); | |||
580 | ||||
581 | return TRUE(!(0)); | |||
582 | } | |||
583 | #endif | |||
584 | ||||
585 | gboolean | |||
586 | meta_prop_get_window (MetaDisplay *display, | |||
587 | Window xwindow, | |||
588 | Atom xatom, | |||
589 | Window *window_p) | |||
590 | { | |||
591 | GetPropertyResults results; | |||
592 | ||||
593 | *window_p = None0L; | |||
594 | ||||
595 | if (!get_property (display, xwindow, xatom, XA_WINDOW((Atom) 33), | |||
596 | &results)) | |||
597 | return FALSE(0); | |||
598 | ||||
599 | return window_from_results (&results, window_p); | |||
600 | } | |||
601 | ||||
602 | gboolean | |||
603 | meta_prop_get_cardinal (MetaDisplay *display, | |||
604 | Window xwindow, | |||
605 | Atom xatom, | |||
606 | gulong *cardinal_p) | |||
607 | { | |||
608 | return meta_prop_get_cardinal_with_atom_type (display, xwindow, xatom, | |||
609 | XA_CARDINAL((Atom) 6), cardinal_p); | |||
610 | } | |||
611 | ||||
612 | static gboolean | |||
613 | cardinal_with_atom_type_from_results (GetPropertyResults *results, | |||
614 | Atom prop_type, | |||
615 | gulong *cardinal_p) | |||
616 | { | |||
617 | if (!validate_or_free_results (results, 32, prop_type, TRUE(!(0)))) | |||
618 | return FALSE(0); | |||
619 | ||||
620 | *cardinal_p = *(gulong*) results->prop; | |||
621 | #if GLIB_SIZEOF_LONG8 == 8 | |||
622 | /* Xlib sign-extends format=32 items, but we want them unsigned */ | |||
623 | *cardinal_p &= 0xffffffff; | |||
624 | #endif | |||
625 | XFree (results->prop); | |||
626 | results->prop = NULL((void*)0); | |||
627 | ||||
628 | return TRUE(!(0)); | |||
629 | } | |||
630 | ||||
631 | gboolean | |||
632 | meta_prop_get_cardinal_with_atom_type (MetaDisplay *display, | |||
633 | Window xwindow, | |||
634 | Atom xatom, | |||
635 | Atom prop_type, | |||
636 | gulong *cardinal_p) | |||
637 | { | |||
638 | GetPropertyResults results; | |||
639 | ||||
640 | *cardinal_p = 0; | |||
641 | ||||
642 | if (!get_property (display, xwindow, xatom, prop_type, | |||
643 | &results)) | |||
644 | return FALSE(0); | |||
645 | ||||
646 | return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p); | |||
647 | } | |||
648 | ||||
649 | static char * | |||
650 | text_property_to_utf8 (Display *xdisplay, | |||
651 | const XTextProperty *prop) | |||
652 | { | |||
653 | char *ret = NULL((void*)0); | |||
654 | char **local_list = NULL((void*)0); | |||
655 | const char *charset = NULL((void*)0); | |||
656 | int count = 0; | |||
657 | int res; | |||
658 | ||||
659 | res = XmbTextPropertyToTextList (xdisplay, prop, &local_list, &count); | |||
660 | if (res == XNoMemory-1 || res == XLocaleNotSupported-2 || res == XConverterNotFound-3) | |||
661 | return NULL((void*)0); | |||
662 | ||||
663 | if (count == 0) | |||
664 | { | |||
665 | XFreeStringList (local_list); | |||
666 | return NULL((void*)0); | |||
667 | } | |||
668 | ||||
669 | if (g_get_charset (&charset)) | |||
670 | ret = g_strdup (local_list[0]); | |||
671 | else | |||
672 | ret = g_convert (local_list[0], -1, "UTF-8", charset, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
673 | ||||
674 | XFreeStringList (local_list); | |||
675 | return ret; | |||
676 | } | |||
677 | ||||
678 | static gboolean | |||
679 | text_property_from_results (GetPropertyResults *results, | |||
680 | char **utf8_str_p) | |||
681 | { | |||
682 | XTextProperty tp; | |||
683 | ||||
684 | *utf8_str_p = NULL((void*)0); | |||
685 | ||||
686 | tp.value = results->prop; | |||
687 | results->prop = NULL((void*)0); | |||
688 | tp.encoding = results->type; | |||
689 | tp.format = results->format; | |||
690 | tp.nitems = results->n_items; | |||
691 | ||||
692 | *utf8_str_p = text_property_to_utf8 (results->display->xdisplay, &tp); | |||
693 | ||||
694 | if (tp.value != NULL((void*)0)) | |||
695 | XFree (tp.value); | |||
696 | ||||
697 | return *utf8_str_p != NULL((void*)0); | |||
698 | } | |||
699 | ||||
700 | gboolean | |||
701 | meta_prop_get_text_property (MetaDisplay *display, | |||
702 | Window xwindow, | |||
703 | Atom xatom, | |||
704 | char **utf8_str_p) | |||
705 | { | |||
706 | GetPropertyResults results; | |||
707 | ||||
708 | if (!get_property (display, xwindow, xatom, AnyPropertyType0L, | |||
709 | &results)) | |||
710 | return FALSE(0); | |||
711 | ||||
712 | return text_property_from_results (&results, utf8_str_p); | |||
713 | } | |||
714 | ||||
715 | /* From Xmd.h */ | |||
716 | #ifndef cvtINT32toInt | |||
717 | #if SIZEOF_VOID_P8 == 8 | |||
718 | #define cvtINT8toInt(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) ((((unsigned int)val) & 0x00000080) ? (((unsigned int)val) | 0xffffffffffffff00) : ((unsigned int)val)) | |||
719 | #define cvtINT16toInt(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) ((((unsigned int)val) & 0x00008000) ? (((unsigned int)val) | 0xffffffffffff0000) : ((unsigned int)val)) | |||
720 | #define cvtINT32toInt(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) ((((unsigned int)val) & 0x80000000) ? (((unsigned int)val) | 0xffffffff00000000) : ((unsigned int)val)) | |||
721 | #define cvtINT8toShort(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) cvtINT8toInt(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) | |||
722 | #define cvtINT16toShort(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) cvtINT16toInt(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) | |||
723 | #define cvtINT32toShort(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) cvtINT32toInt(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) | |||
724 | #define cvtINT8toLong(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) cvtINT8toInt(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) | |||
725 | #define cvtINT16toLong(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) cvtINT16toInt(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) | |||
726 | #define cvtINT32toLong(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) cvtINT32toInt(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) | |||
727 | #else | |||
728 | #define cvtINT8toInt(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) (val) | |||
729 | #define cvtINT16toInt(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) (val) | |||
730 | #define cvtINT32toInt(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) (val) | |||
731 | #define cvtINT8toShort(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) (val) | |||
732 | #define cvtINT16toShort(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) (val) | |||
733 | #define cvtINT32toShort(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) (val) | |||
734 | #define cvtINT8toLong(val)((((unsigned int)val) & 0x00000080) ? (((unsigned int)val ) | 0xffffffffffffff00) : ((unsigned int)val)) (val) | |||
735 | #define cvtINT16toLong(val)((((unsigned int)val) & 0x00008000) ? (((unsigned int)val ) | 0xffffffffffff0000) : ((unsigned int)val)) (val) | |||
736 | #define cvtINT32toLong(val)((((unsigned int)val) & 0x80000000) ? (((unsigned int)val ) | 0xffffffff00000000) : ((unsigned int)val)) (val) | |||
737 | #endif /* SIZEOF_VOID_P == 8 */ | |||
738 | #endif /* cvtINT32toInt() */ | |||
739 | ||||
740 | static gboolean | |||
741 | wm_hints_from_results (GetPropertyResults *results, | |||
742 | XWMHints **hints_p) | |||
743 | { | |||
744 | XWMHints *hints; | |||
745 | xPropWMHints *raw; | |||
746 | ||||
747 | *hints_p = NULL((void*)0); | |||
748 | ||||
749 | if (!validate_or_free_results (results, 32, XA_WM_HINTS((Atom) 35), TRUE(!(0)))) | |||
750 | return FALSE(0); | |||
751 | ||||
752 | /* pre-R3 bogusly truncated window_group, don't fail on them */ | |||
753 | if (results->n_items < (NumPropWMHintsElements9 - 1)) | |||
754 | { | |||
755 | meta_verbosemeta_verbose_real ("WM_HINTS property too short: %d should be %d\n", | |||
756 | (int) results->n_items, NumPropWMHintsElements9 - 1); | |||
757 | if (results->prop) | |||
758 | { | |||
759 | XFree (results->prop); | |||
760 | results->prop = NULL((void*)0); | |||
761 | } | |||
762 | return FALSE(0); | |||
763 | } | |||
764 | ||||
765 | hints = ag_Xmalloc0 (sizeof (XWMHints)); | |||
766 | ||||
767 | raw = (xPropWMHints*) (gpointer) results->prop; | |||
768 | ||||
769 | hints->flags = raw->flags; | |||
770 | hints->input = (raw->input ? True1 : False0); | |||
771 | hints->initial_state = cvtINT32toInt (raw->initialState)((((unsigned int)raw->initialState) & 0x80000000) ? (( (unsigned int)raw->initialState) | 0xffffffff00000000) : ( (unsigned int)raw->initialState)); | |||
772 | hints->icon_pixmap = raw->iconPixmap; | |||
773 | hints->icon_window = raw->iconWindow; | |||
774 | hints->icon_x = cvtINT32toInt (raw->iconX)((((unsigned int)raw->iconX) & 0x80000000) ? (((unsigned int)raw->iconX) | 0xffffffff00000000) : ((unsigned int)raw ->iconX)); | |||
775 | hints->icon_y = cvtINT32toInt (raw->iconY)((((unsigned int)raw->iconY) & 0x80000000) ? (((unsigned int)raw->iconY) | 0xffffffff00000000) : ((unsigned int)raw ->iconY)); | |||
776 | hints->icon_mask = raw->iconMask; | |||
777 | if (results->n_items >= NumPropWMHintsElements9) | |||
778 | hints->window_group = raw->windowGroup; | |||
779 | else | |||
780 | hints->window_group = 0; | |||
781 | ||||
782 | if (results->prop) | |||
783 | { | |||
784 | XFree (results->prop); | |||
785 | results->prop = NULL((void*)0); | |||
786 | } | |||
787 | ||||
788 | *hints_p = hints; | |||
789 | ||||
790 | return TRUE(!(0)); | |||
791 | } | |||
792 | ||||
793 | gboolean | |||
794 | meta_prop_get_wm_hints (MetaDisplay *display, | |||
795 | Window xwindow, | |||
796 | Atom xatom, | |||
797 | XWMHints **hints_p) | |||
798 | { | |||
799 | GetPropertyResults results; | |||
800 | ||||
801 | *hints_p = NULL((void*)0); | |||
802 | ||||
803 | if (!get_property (display, xwindow, xatom, XA_WM_HINTS((Atom) 35), | |||
804 | &results)) | |||
805 | return FALSE(0); | |||
806 | ||||
807 | return wm_hints_from_results (&results, hints_p); | |||
808 | } | |||
809 | ||||
810 | static gboolean | |||
811 | class_hint_from_results (GetPropertyResults *results, | |||
812 | XClassHint *class_hint) | |||
813 | { | |||
814 | int len_name, len_class; | |||
815 | ||||
816 | class_hint->res_class = NULL((void*)0); | |||
817 | class_hint->res_name = NULL((void*)0); | |||
818 | ||||
819 | if (!validate_or_free_results (results, 8, XA_STRING((Atom) 31), FALSE(0))) | |||
820 | return FALSE(0); | |||
821 | ||||
822 | len_name = strlen ((char *) results->prop); | |||
823 | if (! (class_hint->res_name = ag_Xmalloc (len_name+1))) | |||
824 | { | |||
825 | XFree (results->prop); | |||
826 | results->prop = NULL((void*)0); | |||
827 | return FALSE(0); | |||
828 | } | |||
829 | ||||
830 | g_strlcpy (class_hint->res_name, (char *)results->prop, (len_name + 1)); | |||
831 | ||||
832 | if (len_name == (int) results->n_items) | |||
833 | len_name--; | |||
834 | ||||
835 | len_class = strlen ((char *)results->prop + len_name + 1); | |||
836 | ||||
837 | if (! (class_hint->res_class = ag_Xmalloc(len_class+1))) | |||
838 | { | |||
839 | XFree(class_hint->res_name); | |||
840 | class_hint->res_name = NULL((void*)0); | |||
841 | XFree (results->prop); | |||
842 | results->prop = NULL((void*)0); | |||
843 | return FALSE(0); | |||
844 | } | |||
845 | ||||
846 | g_strlcpy (class_hint->res_class, (char *)results->prop + len_name + 1, (len_class + 1)); | |||
847 | ||||
848 | XFree (results->prop); | |||
849 | results->prop = NULL((void*)0); | |||
850 | ||||
851 | return TRUE(!(0)); | |||
852 | } | |||
853 | ||||
854 | gboolean | |||
855 | meta_prop_get_class_hint (MetaDisplay *display, | |||
856 | Window xwindow, | |||
857 | Atom xatom, | |||
858 | XClassHint *class_hint) | |||
859 | { | |||
860 | GetPropertyResults results; | |||
861 | ||||
862 | class_hint->res_class = NULL((void*)0); | |||
863 | class_hint->res_name = NULL((void*)0); | |||
864 | ||||
865 | if (!get_property (display, xwindow, xatom, XA_STRING((Atom) 31), | |||
866 | &results)) | |||
867 | return FALSE(0); | |||
868 | ||||
869 | return class_hint_from_results (&results, class_hint); | |||
870 | } | |||
871 | ||||
872 | static gboolean | |||
873 | size_hints_from_results (GetPropertyResults *results, | |||
874 | XSizeHints **hints_p, | |||
875 | gulong *flags_p) | |||
876 | { | |||
877 | xPropSizeHints *raw; | |||
878 | XSizeHints *hints; | |||
879 | ||||
880 | *hints_p = NULL((void*)0); | |||
881 | *flags_p = 0; | |||
882 | ||||
883 | if (!validate_or_free_results (results, 32, XA_WM_SIZE_HINTS((Atom) 41), FALSE(0))) | |||
884 | return FALSE(0); | |||
885 | ||||
886 | if (results->n_items < OldNumPropSizeElements15) | |||
887 | return FALSE(0); | |||
888 | ||||
889 | raw = (xPropSizeHints*) (gpointer) results->prop; | |||
890 | ||||
891 | hints = ag_Xmalloc (sizeof (XSizeHints)); | |||
892 | ||||
893 | /* XSizeHints misdeclares these as int instead of long */ | |||
894 | hints->flags = raw->flags; | |||
895 | hints->x = cvtINT32toInt (raw->x)((((unsigned int)raw->x) & 0x80000000) ? (((unsigned int )raw->x) | 0xffffffff00000000) : ((unsigned int)raw->x) ); | |||
896 | hints->y = cvtINT32toInt (raw->y)((((unsigned int)raw->y) & 0x80000000) ? (((unsigned int )raw->y) | 0xffffffff00000000) : ((unsigned int)raw->y) ); | |||
897 | hints->width = cvtINT32toInt (raw->width)((((unsigned int)raw->width) & 0x80000000) ? (((unsigned int)raw->width) | 0xffffffff00000000) : ((unsigned int)raw ->width)); | |||
898 | hints->height = cvtINT32toInt (raw->height)((((unsigned int)raw->height) & 0x80000000) ? (((unsigned int)raw->height) | 0xffffffff00000000) : ((unsigned int)raw ->height)); | |||
899 | hints->min_width = cvtINT32toInt (raw->minWidth)((((unsigned int)raw->minWidth) & 0x80000000) ? (((unsigned int)raw->minWidth) | 0xffffffff00000000) : ((unsigned int )raw->minWidth)); | |||
900 | hints->min_height = cvtINT32toInt (raw->minHeight)((((unsigned int)raw->minHeight) & 0x80000000) ? (((unsigned int)raw->minHeight) | 0xffffffff00000000) : ((unsigned int )raw->minHeight)); | |||
901 | hints->max_width = cvtINT32toInt (raw->maxWidth)((((unsigned int)raw->maxWidth) & 0x80000000) ? (((unsigned int)raw->maxWidth) | 0xffffffff00000000) : ((unsigned int )raw->maxWidth)); | |||
902 | hints->max_height = cvtINT32toInt (raw->maxHeight)((((unsigned int)raw->maxHeight) & 0x80000000) ? (((unsigned int)raw->maxHeight) | 0xffffffff00000000) : ((unsigned int )raw->maxHeight)); | |||
903 | hints->width_inc = cvtINT32toInt (raw->widthInc)((((unsigned int)raw->widthInc) & 0x80000000) ? (((unsigned int)raw->widthInc) | 0xffffffff00000000) : ((unsigned int )raw->widthInc)); | |||
904 | hints->height_inc = cvtINT32toInt (raw->heightInc)((((unsigned int)raw->heightInc) & 0x80000000) ? (((unsigned int)raw->heightInc) | 0xffffffff00000000) : ((unsigned int )raw->heightInc)); | |||
905 | hints->min_aspect.x = cvtINT32toInt (raw->minAspectX)((((unsigned int)raw->minAspectX) & 0x80000000) ? (((unsigned int)raw->minAspectX) | 0xffffffff00000000) : ((unsigned int )raw->minAspectX)); | |||
906 | hints->min_aspect.y = cvtINT32toInt (raw->minAspectY)((((unsigned int)raw->minAspectY) & 0x80000000) ? (((unsigned int)raw->minAspectY) | 0xffffffff00000000) : ((unsigned int )raw->minAspectY)); | |||
907 | hints->max_aspect.x = cvtINT32toInt (raw->maxAspectX)((((unsigned int)raw->maxAspectX) & 0x80000000) ? (((unsigned int)raw->maxAspectX) | 0xffffffff00000000) : ((unsigned int )raw->maxAspectX)); | |||
908 | hints->max_aspect.y = cvtINT32toInt (raw->maxAspectY)((((unsigned int)raw->maxAspectY) & 0x80000000) ? (((unsigned int)raw->maxAspectY) | 0xffffffff00000000) : ((unsigned int )raw->maxAspectY)); | |||
909 | ||||
910 | *flags_p = (USPosition(1L << 0) | USSize(1L << 1) | PAllHints((1L << 2)|(1L << 3)|(1L << 4)|(1L << 5)|(1L << 6)|(1L << 7))); | |||
911 | if (results->n_items >= NumPropSizeElements18) | |||
912 | { | |||
913 | hints->base_width= cvtINT32toInt (raw->baseWidth)((((unsigned int)raw->baseWidth) & 0x80000000) ? (((unsigned int)raw->baseWidth) | 0xffffffff00000000) : ((unsigned int )raw->baseWidth)); | |||
914 | hints->base_height= cvtINT32toInt (raw->baseHeight)((((unsigned int)raw->baseHeight) & 0x80000000) ? (((unsigned int)raw->baseHeight) | 0xffffffff00000000) : ((unsigned int )raw->baseHeight)); | |||
915 | hints->win_gravity= cvtINT32toInt (raw->winGravity)((((unsigned int)raw->winGravity) & 0x80000000) ? (((unsigned int)raw->winGravity) | 0xffffffff00000000) : ((unsigned int )raw->winGravity)); | |||
916 | *flags_p |= (PBaseSize(1L << 8) | PWinGravity(1L << 9)); | |||
917 | } | |||
918 | ||||
919 | hints->flags &= (*flags_p); /* get rid of unwanted bits */ | |||
920 | ||||
921 | XFree (results->prop); | |||
922 | results->prop = NULL((void*)0); | |||
923 | ||||
924 | *hints_p = hints; | |||
925 | ||||
926 | return TRUE(!(0)); | |||
927 | } | |||
928 | ||||
929 | gboolean | |||
930 | meta_prop_get_size_hints (MetaDisplay *display, | |||
931 | Window xwindow, | |||
932 | Atom xatom, | |||
933 | XSizeHints **hints_p, | |||
934 | gulong *flags_p) | |||
935 | { | |||
936 | GetPropertyResults results; | |||
937 | ||||
938 | *hints_p = NULL((void*)0); | |||
939 | *flags_p = 0; | |||
940 | ||||
941 | if (!get_property (display, xwindow, xatom, XA_WM_SIZE_HINTS((Atom) 41), | |||
942 | &results)) | |||
943 | return FALSE(0); | |||
944 | ||||
945 | return size_hints_from_results (&results, hints_p, flags_p); | |||
946 | } | |||
947 | ||||
948 | static AgGetPropertyTask* | |||
949 | get_task (MetaDisplay *display, | |||
950 | Window xwindow, | |||
951 | Atom xatom, | |||
952 | Atom req_type) | |||
953 | { | |||
954 | return ag_task_create (display->xdisplay, | |||
955 | xwindow, | |||
956 | xatom, 0, G_MAXLONG9223372036854775807L, | |||
957 | False0, req_type); | |||
958 | } | |||
959 | ||||
960 | static char* | |||
961 | latin1_to_utf8 (const char *text) | |||
962 | { | |||
963 | GString *str; | |||
964 | const char *p; | |||
965 | ||||
966 | str = g_string_new (""); | |||
967 | ||||
968 | p = text; | |||
969 | while (*p) | |||
970 | { | |||
971 | g_string_append_unichar (str, *p); | |||
972 | ++p; | |||
973 | } | |||
974 | ||||
975 | return g_string_free (str, FALSE(0)); | |||
976 | } | |||
977 | ||||
978 | void | |||
979 | meta_prop_get_values (MetaDisplay *display, | |||
980 | Window xwindow, | |||
981 | MetaPropValue *values, | |||
982 | int n_values) | |||
983 | { | |||
984 | int i; | |||
985 | AgGetPropertyTask **tasks; | |||
986 | ||||
987 | meta_verbosemeta_verbose_real ("Requesting %d properties of 0x%lx at once\n", | |||
988 | n_values, xwindow); | |||
989 | ||||
990 | if (n_values == 0) | |||
| ||||
991 | return; | |||
992 | ||||
993 | tasks = g_new0 (AgGetPropertyTask*, n_values)((AgGetPropertyTask* *) g_malloc0_n ((n_values), sizeof (AgGetPropertyTask *))); | |||
994 | ||||
995 | /* Start up tasks. The "values" array can have values | |||
996 | * with atom == None, which means to ignore that element. | |||
997 | */ | |||
998 | i = 0; | |||
999 | while (i < n_values) | |||
1000 | { | |||
1001 | if (values[i].required_type == None0L) | |||
1002 | { | |||
1003 | switch (values[i].type) | |||
1004 | { | |||
1005 | case META_PROP_VALUE_INVALID: | |||
1006 | /* This means we don't really want a value, e.g. got | |||
1007 | * property notify on an atom we don't care about. | |||
1008 | */ | |||
1009 | if (values[i].atom != None0L) | |||
1010 | meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC((const char*) (__func__))); | |||
1011 | break; | |||
1012 | case META_PROP_VALUE_UTF8_LIST: | |||
1013 | case META_PROP_VALUE_UTF8: | |||
1014 | values[i].required_type = display->atom_UTF8_STRING; | |||
1015 | break; | |||
1016 | case META_PROP_VALUE_STRING: | |||
1017 | case META_PROP_VALUE_STRING_AS_UTF8: | |||
1018 | values[i].required_type = XA_STRING((Atom) 31); | |||
1019 | break; | |||
1020 | case META_PROP_VALUE_MOTIF_HINTS: | |||
1021 | values[i].required_type = AnyPropertyType0L; | |||
1022 | break; | |||
1023 | case META_PROP_VALUE_CARDINAL_LIST: | |||
1024 | case META_PROP_VALUE_CARDINAL: | |||
1025 | values[i].required_type = XA_CARDINAL((Atom) 6); | |||
1026 | break; | |||
1027 | case META_PROP_VALUE_WINDOW: | |||
1028 | values[i].required_type = XA_WINDOW((Atom) 33); | |||
1029 | break; | |||
1030 | case META_PROP_VALUE_ATOM_LIST: | |||
1031 | values[i].required_type = XA_ATOM((Atom) 4); | |||
1032 | break; | |||
1033 | case META_PROP_VALUE_TEXT_PROPERTY: | |||
1034 | values[i].required_type = AnyPropertyType0L; | |||
1035 | break; | |||
1036 | case META_PROP_VALUE_WM_HINTS: | |||
1037 | values[i].required_type = XA_WM_HINTS((Atom) 35); | |||
1038 | break; | |||
1039 | case META_PROP_VALUE_CLASS_HINT: | |||
1040 | values[i].required_type = XA_STRING((Atom) 31); | |||
1041 | break; | |||
1042 | case META_PROP_VALUE_SIZE_HINTS: | |||
1043 | values[i].required_type = XA_WM_SIZE_HINTS((Atom) 41); | |||
1044 | break; | |||
1045 | case META_PROP_VALUE_SYNC_COUNTER: | |||
1046 | values[i].required_type = XA_CARDINAL((Atom) 6); | |||
1047 | break; | |||
1048 | } | |||
1049 | } | |||
1050 | ||||
1051 | if (values[i].atom != None0L) | |||
1052 | tasks[i] = get_task (display, xwindow, | |||
1053 | values[i].atom, values[i].required_type); | |||
1054 | ||||
1055 | ++i; | |||
1056 | } | |||
1057 | ||||
1058 | /* Get replies for all our tasks */ | |||
1059 | meta_topicmeta_topic_real (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n", | |||
1060 | n_values, G_STRFUNC((const char*) (__func__))); | |||
1061 | XSync (display->xdisplay, False0); | |||
1062 | ||||
1063 | /* Collect results, should arrive in order requested */ | |||
1064 | i = 0; | |||
1065 | while (i < n_values) | |||
1066 | { | |||
1067 | AgGetPropertyTask *task; | |||
1068 | GetPropertyResults results; | |||
1069 | ||||
1070 | if (tasks[i] == NULL((void*)0)) | |||
1071 | { | |||
1072 | /* Probably values[i].type was None, or ag_task_create() | |||
1073 | * returned NULL. | |||
1074 | */ | |||
1075 | values[i].type = META_PROP_VALUE_INVALID; | |||
1076 | goto next; | |||
1077 | } | |||
1078 | ||||
1079 | task = ag_get_next_completed_task (display->xdisplay); | |||
1080 | g_assert (task != NULL)do { if (task != ((void*)0)) ; else g_assertion_message_expr ( "croma", "core/xprops.c", 1080, ((const char*) (__func__)), "task != NULL" ); } while (0); | |||
1081 | g_assert (ag_task_have_reply (task))do { if (ag_task_have_reply (task)) ; else g_assertion_message_expr ("croma", "core/xprops.c", 1081, ((const char*) (__func__)), "ag_task_have_reply (task)"); } while (0); | |||
1082 | ||||
1083 | results.display = display; | |||
1084 | results.xwindow = xwindow; | |||
1085 | results.xatom = values[i].atom; | |||
1086 | results.prop = NULL((void*)0); | |||
1087 | results.n_items = 0; | |||
1088 | results.type = None0L; | |||
1089 | results.bytes_after = 0; | |||
1090 | results.format = 0; | |||
1091 | ||||
1092 | if (ag_task_get_reply_and_free (task, | |||
1093 | &results.type, &results.format, | |||
1094 | &results.n_items, | |||
1095 | &results.bytes_after, | |||
1096 | &results.prop) != Success0 || | |||
1097 | results.type == None0L) | |||
1098 | { | |||
1099 | values[i].type = META_PROP_VALUE_INVALID; | |||
1100 | if (results.prop) | |||
1101 | { | |||
1102 | XFree (results.prop); | |||
1103 | results.prop = NULL((void*)0); | |||
1104 | } | |||
1105 | goto next; | |||
1106 | } | |||
1107 | ||||
1108 | switch (values[i].type) | |||
1109 | { | |||
1110 | case META_PROP_VALUE_INVALID: | |||
1111 | g_assert_not_reached ()do { g_assertion_message_expr ("croma", "core/xprops.c", 1111 , ((const char*) (__func__)), ((void*)0)); } while (0); | |||
1112 | break; | |||
1113 | case META_PROP_VALUE_UTF8_LIST: | |||
1114 | if (!utf8_list_from_results (&results, | |||
1115 | &values[i].v.string_list.strings, | |||
1116 | &values[i].v.string_list.n_strings)) | |||
1117 | values[i].type = META_PROP_VALUE_INVALID; | |||
1118 | break; | |||
1119 | case META_PROP_VALUE_UTF8: | |||
1120 | if (!utf8_string_from_results (&results, | |||
1121 | &values[i].v.str)) | |||
1122 | values[i].type = META_PROP_VALUE_INVALID; | |||
1123 | break; | |||
1124 | case META_PROP_VALUE_STRING: | |||
1125 | if (!latin1_string_from_results (&results, | |||
1126 | &values[i].v.str)) | |||
1127 | values[i].type = META_PROP_VALUE_INVALID; | |||
1128 | break; | |||
1129 | case META_PROP_VALUE_STRING_AS_UTF8: | |||
1130 | if (!latin1_string_from_results (&results, | |||
1131 | &values[i].v.str)) | |||
1132 | values[i].type = META_PROP_VALUE_INVALID; | |||
1133 | else | |||
1134 | { | |||
1135 | char *new_str; | |||
1136 | char *xmalloc_new_str; | |||
1137 | ||||
1138 | new_str = latin1_to_utf8 (values[i].v.str); | |||
1139 | xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1); | |||
1140 | if (xmalloc_new_str != NULL((void*)0)) | |||
1141 | { | |||
1142 | g_strlcpy (xmalloc_new_str, new_str, (strlen (new_str) + 1)); | |||
1143 | meta_XFree (values[i].v.str)do { if ((values[i].v.str)) XFree ((values[i].v.str)); } while (0); | |||
1144 | values[i].v.str = xmalloc_new_str; | |||
1145 | } | |||
1146 | ||||
1147 | g_free (new_str); | |||
1148 | } | |||
1149 | break; | |||
1150 | case META_PROP_VALUE_MOTIF_HINTS: | |||
1151 | if (!motif_hints_from_results (&results, | |||
1152 | &values[i].v.motif_hints)) | |||
1153 | values[i].type = META_PROP_VALUE_INVALID; | |||
1154 | break; | |||
1155 | case META_PROP_VALUE_CARDINAL_LIST: | |||
1156 | if (!cardinal_list_from_results (&results, | |||
1157 | &values[i].v.cardinal_list.cardinals, | |||
1158 | &values[i].v.cardinal_list.n_cardinals)) | |||
1159 | values[i].type = META_PROP_VALUE_INVALID; | |||
1160 | break; | |||
1161 | case META_PROP_VALUE_CARDINAL: | |||
1162 | if (!cardinal_with_atom_type_from_results (&results, | |||
1163 | values[i].required_type, | |||
1164 | &values[i].v.cardinal)) | |||
1165 | values[i].type = META_PROP_VALUE_INVALID; | |||
1166 | break; | |||
1167 | case META_PROP_VALUE_WINDOW: | |||
1168 | if (!window_from_results (&results, | |||
1169 | &values[i].v.xwindow)) | |||
1170 | values[i].type = META_PROP_VALUE_INVALID; | |||
1171 | break; | |||
1172 | case META_PROP_VALUE_ATOM_LIST: | |||
1173 | if (!atom_list_from_results (&results, | |||
1174 | &values[i].v.atom_list.atoms, | |||
1175 | &values[i].v.atom_list.n_atoms)) | |||
1176 | values[i].type = META_PROP_VALUE_INVALID; | |||
1177 | break; | |||
1178 | case META_PROP_VALUE_TEXT_PROPERTY: | |||
1179 | if (!text_property_from_results (&results, &values[i].v.str)) | |||
1180 | values[i].type = META_PROP_VALUE_INVALID; | |||
1181 | break; | |||
1182 | case META_PROP_VALUE_WM_HINTS: | |||
1183 | if (!wm_hints_from_results (&results, &values[i].v.wm_hints)) | |||
1184 | values[i].type = META_PROP_VALUE_INVALID; | |||
1185 | break; | |||
1186 | case META_PROP_VALUE_CLASS_HINT: | |||
1187 | if (!class_hint_from_results (&results, &values[i].v.class_hint)) | |||
1188 | values[i].type = META_PROP_VALUE_INVALID; | |||
1189 | break; | |||
1190 | case META_PROP_VALUE_SIZE_HINTS: | |||
1191 | if (!size_hints_from_results (&results, | |||
1192 | &values[i].v.size_hints.hints, | |||
1193 | &values[i].v.size_hints.flags)) | |||
1194 | values[i].type = META_PROP_VALUE_INVALID; | |||
1195 | break; | |||
1196 | case META_PROP_VALUE_SYNC_COUNTER: | |||
1197 | #ifdef HAVE_XSYNC | |||
1198 | if (!counter_from_results (&results, | |||
1199 | &values[i].v.xcounter)) | |||
1200 | values[i].type = META_PROP_VALUE_INVALID; | |||
1201 | #else | |||
1202 | values[i].type = META_PROP_VALUE_INVALID; | |||
1203 | if (results.prop) | |||
1204 | { | |||
1205 | XFree (results.prop); | |||
1206 | results.prop = NULL((void*)0); | |||
1207 | } | |||
1208 | #endif | |||
1209 | break; | |||
1210 | } | |||
1211 | ||||
1212 | next: | |||
1213 | ++i; | |||
1214 | } | |||
1215 | ||||
1216 | g_free (tasks); | |||
1217 | } | |||
1218 | ||||
1219 | static void | |||
1220 | free_value (MetaPropValue *value) | |||
1221 | { | |||
1222 | switch (value->type) | |||
1223 | { | |||
1224 | case META_PROP_VALUE_INVALID: | |||
1225 | break; | |||
1226 | case META_PROP_VALUE_UTF8: | |||
1227 | case META_PROP_VALUE_STRING: | |||
1228 | case META_PROP_VALUE_STRING_AS_UTF8: | |||
1229 | meta_XFree (value->v.str)do { if ((value->v.str)) XFree ((value->v.str)); } while (0); | |||
1230 | break; | |||
1231 | case META_PROP_VALUE_MOTIF_HINTS: | |||
1232 | meta_XFree (value->v.motif_hints)do { if ((value->v.motif_hints)) XFree ((value->v.motif_hints )); } while (0); | |||
1233 | break; | |||
1234 | case META_PROP_VALUE_CARDINAL: | |||
1235 | break; | |||
1236 | case META_PROP_VALUE_WINDOW: | |||
1237 | break; | |||
1238 | case META_PROP_VALUE_ATOM_LIST: | |||
1239 | meta_XFree (value->v.atom_list.atoms)do { if ((value->v.atom_list.atoms)) XFree ((value->v.atom_list .atoms)); } while (0); | |||
1240 | break; | |||
1241 | case META_PROP_VALUE_TEXT_PROPERTY: | |||
1242 | meta_XFree (value->v.str)do { if ((value->v.str)) XFree ((value->v.str)); } while (0); | |||
1243 | break; | |||
1244 | case META_PROP_VALUE_WM_HINTS: | |||
1245 | meta_XFree (value->v.wm_hints)do { if ((value->v.wm_hints)) XFree ((value->v.wm_hints )); } while (0); | |||
1246 | break; | |||
1247 | case META_PROP_VALUE_CLASS_HINT: | |||
1248 | meta_XFree (value->v.class_hint.res_class)do { if ((value->v.class_hint.res_class)) XFree ((value-> v.class_hint.res_class)); } while (0); | |||
1249 | meta_XFree (value->v.class_hint.res_name)do { if ((value->v.class_hint.res_name)) XFree ((value-> v.class_hint.res_name)); } while (0); | |||
1250 | break; | |||
1251 | case META_PROP_VALUE_SIZE_HINTS: | |||
1252 | meta_XFree (value->v.size_hints.hints)do { if ((value->v.size_hints.hints)) XFree ((value->v. size_hints.hints)); } while (0); | |||
1253 | break; | |||
1254 | case META_PROP_VALUE_UTF8_LIST: | |||
1255 | g_strfreev (value->v.string_list.strings); | |||
1256 | break; | |||
1257 | case META_PROP_VALUE_CARDINAL_LIST: | |||
1258 | meta_XFree (value->v.cardinal_list.cardinals)do { if ((value->v.cardinal_list.cardinals)) XFree ((value ->v.cardinal_list.cardinals)); } while (0); | |||
1259 | break; | |||
1260 | case META_PROP_VALUE_SYNC_COUNTER: | |||
1261 | break; | |||
1262 | } | |||
1263 | } | |||
1264 | ||||
1265 | void | |||
1266 | meta_prop_free_values (MetaPropValue *values, | |||
1267 | int n_values) | |||
1268 | { | |||
1269 | int i; | |||
1270 | ||||
1271 | i = 0; | |||
1272 | while (i < n_values) | |||
1273 | { | |||
1274 | free_value (&values[i]); | |||
1275 | ++i; | |||
1276 | } | |||
1277 | ||||
1278 | /* Zero the whole thing to quickly detect breakage */ | |||
1279 | memset (values, '\0', sizeof (MetaPropValue) * n_values); | |||
1280 | } |