00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #include <config.h>
00084 #include "xprops.h"
00085 #include "errors.h"
00086 #include "util.h"
00087 #include "async-getprop.h"
00088 #include "ui.h"
00089 #include "metacity-Xatomtype.h"
00090 #include <X11/Xatom.h>
00091 #include <string.h>
00092 #include "window-private.h"
00093
00094 typedef struct
00095 {
00096 MetaDisplay *display;
00097 Window xwindow;
00098 Atom xatom;
00099 Atom type;
00100 int format;
00101 unsigned long n_items;
00102 unsigned long bytes_after;
00103 unsigned char *prop;
00104 } GetPropertyResults;
00105
00106 static gboolean
00107 validate_or_free_results (GetPropertyResults *results,
00108 int expected_format,
00109 Atom expected_type,
00110 gboolean must_have_items)
00111 {
00112 char *type_name;
00113 char *expected_name;
00114 char *prop_name;
00115 const char *title;
00116 const char *res_class;
00117 const char *res_name;
00118 MetaWindow *w;
00119
00120 if (expected_format == results->format &&
00121 expected_type == results->type &&
00122 (!must_have_items || results->n_items > 0))
00123 return TRUE;
00124
00125 meta_error_trap_push (results->display);
00126 type_name = XGetAtomName (results->display->xdisplay, results->type);
00127 expected_name = XGetAtomName (results->display->xdisplay, expected_type);
00128 prop_name = XGetAtomName (results->display->xdisplay, results->xatom);
00129 meta_error_trap_pop (results->display, TRUE);
00130
00131 w = meta_display_lookup_x_window (results->display, results->xwindow);
00132
00133 if (w != NULL)
00134 {
00135 title = w->title;
00136 res_class = w->res_class;
00137 res_name = w->res_name;
00138 }
00139 else
00140 {
00141 title = NULL;
00142 res_class = NULL;
00143 res_name = NULL;
00144 }
00145
00146 if (title == NULL)
00147 title = "unknown";
00148
00149 if (res_class == NULL)
00150 res_class = "unknown";
00151
00152 if (res_name == NULL)
00153 res_name = "unknown";
00154
00155 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"),
00156 results->xwindow,
00157 prop_name ? prop_name : "(bad atom)",
00158 expected_name ? expected_name : "(bad atom)",
00159 expected_format,
00160 type_name ? type_name : "(bad atom)",
00161 results->format, (int) results->n_items,
00162 title, res_class, res_name);
00163
00164 if (type_name)
00165 XFree (type_name);
00166 if (expected_name)
00167 XFree (expected_name);
00168 if (prop_name)
00169 XFree (prop_name);
00170
00171 if (results->prop)
00172 {
00173 XFree (results->prop);
00174 results->prop = NULL;
00175 }
00176
00177 return FALSE;
00178 }
00179
00180 static gboolean
00181 get_property (MetaDisplay *display,
00182 Window xwindow,
00183 Atom xatom,
00184 Atom req_type,
00185 GetPropertyResults *results)
00186 {
00187 results->display = display;
00188 results->xwindow = xwindow;
00189 results->xatom = xatom;
00190 results->prop = NULL;
00191 results->n_items = 0;
00192 results->type = None;
00193 results->bytes_after = 0;
00194 results->format = 0;
00195
00196 meta_error_trap_push_with_return (display);
00197 if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
00198 0, G_MAXLONG,
00199 False, req_type, &results->type, &results->format,
00200 &results->n_items,
00201 &results->bytes_after,
00202 (guchar **)&results->prop) != Success ||
00203 results->type == None)
00204 {
00205 if (results->prop)
00206 XFree (results->prop);
00207 meta_error_trap_pop_with_return (display, TRUE);
00208 return FALSE;
00209 }
00210
00211 if (meta_error_trap_pop_with_return (display, TRUE) != Success)
00212 {
00213 if (results->prop)
00214 XFree (results->prop);
00215 return FALSE;
00216 }
00217
00218 return TRUE;
00219 }
00220
00221 static gboolean
00222 atom_list_from_results (GetPropertyResults *results,
00223 Atom **atoms_p,
00224 int *n_atoms_p)
00225 {
00226 if (!validate_or_free_results (results, 32, XA_ATOM, FALSE))
00227 return FALSE;
00228
00229 *atoms_p = (Atom*) results->prop;
00230 *n_atoms_p = results->n_items;
00231 results->prop = NULL;
00232
00233 return TRUE;
00234 }
00235
00236 gboolean
00237 meta_prop_get_atom_list (MetaDisplay *display,
00238 Window xwindow,
00239 Atom xatom,
00240 Atom **atoms_p,
00241 int *n_atoms_p)
00242 {
00243 GetPropertyResults results;
00244
00245 *atoms_p = NULL;
00246 *n_atoms_p = 0;
00247
00248 if (!get_property (display, xwindow, xatom, XA_ATOM,
00249 &results))
00250 return FALSE;
00251
00252 return atom_list_from_results (&results, atoms_p, n_atoms_p);
00253 }
00254
00255 static gboolean
00256 cardinal_list_from_results (GetPropertyResults *results,
00257 gulong **cardinals_p,
00258 int *n_cardinals_p)
00259 {
00260 if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE))
00261 return FALSE;
00262
00263 *cardinals_p = (gulong*) results->prop;
00264 *n_cardinals_p = results->n_items;
00265 results->prop = NULL;
00266
00267 return TRUE;
00268 }
00269
00270 gboolean
00271 meta_prop_get_cardinal_list (MetaDisplay *display,
00272 Window xwindow,
00273 Atom xatom,
00274 gulong **cardinals_p,
00275 int *n_cardinals_p)
00276 {
00277 GetPropertyResults results;
00278
00279 *cardinals_p = NULL;
00280 *n_cardinals_p = 0;
00281
00282 if (!get_property (display, xwindow, xatom, XA_CARDINAL,
00283 &results))
00284 return FALSE;
00285
00286 return cardinal_list_from_results (&results, cardinals_p, n_cardinals_p);
00287 }
00288
00289 static gboolean
00290 motif_hints_from_results (GetPropertyResults *results,
00291 MotifWmHints **hints_p)
00292 {
00293 int real_size, max_size;
00294 #define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong)
00295
00296 *hints_p = NULL;
00297
00298 if (results->type == None || results->n_items <= 0)
00299 {
00300 meta_verbose ("Motif hints had unexpected type or n_items\n");
00301 if (results->prop)
00302 {
00303 XFree (results->prop);
00304 results->prop = NULL;
00305 }
00306 return FALSE;
00307 }
00308
00309
00310
00311
00312
00313 *hints_p = ag_Xmalloc (sizeof (MotifWmHints));
00314 if (*hints_p == NULL)
00315 {
00316 if (results->prop)
00317 {
00318 XFree (results->prop);
00319 results->prop = NULL;
00320 }
00321 return FALSE;
00322 }
00323 real_size = results->n_items * sizeof (gulong);
00324 max_size = MAX_ITEMS * sizeof (gulong);
00325 memcpy (*hints_p, results->prop, MIN (real_size, max_size));
00326
00327 if (results->prop)
00328 {
00329 XFree (results->prop);
00330 results->prop = NULL;
00331 }
00332
00333 return TRUE;
00334 }
00335
00336 gboolean
00337 meta_prop_get_motif_hints (MetaDisplay *display,
00338 Window xwindow,
00339 Atom xatom,
00340 MotifWmHints **hints_p)
00341 {
00342 GetPropertyResults results;
00343
00344 *hints_p = NULL;
00345
00346 if (!get_property (display, xwindow, xatom, AnyPropertyType,
00347 &results))
00348 return FALSE;
00349
00350 return motif_hints_from_results (&results, hints_p);
00351 }
00352
00353 static gboolean
00354 latin1_string_from_results (GetPropertyResults *results,
00355 char **str_p)
00356 {
00357 *str_p = NULL;
00358
00359 if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
00360 return FALSE;
00361
00362 *str_p = (char*) results->prop;
00363 results->prop = NULL;
00364
00365 return TRUE;
00366 }
00367
00368 gboolean
00369 meta_prop_get_latin1_string (MetaDisplay *display,
00370 Window xwindow,
00371 Atom xatom,
00372 char **str_p)
00373 {
00374 GetPropertyResults results;
00375
00376 *str_p = NULL;
00377
00378 if (!get_property (display, xwindow, xatom, XA_STRING,
00379 &results))
00380 return FALSE;
00381
00382 return latin1_string_from_results (&results, str_p);
00383 }
00384
00385 static gboolean
00386 utf8_string_from_results (GetPropertyResults *results,
00387 char **str_p)
00388 {
00389 *str_p = NULL;
00390
00391 if (!validate_or_free_results (results, 8,
00392 results->display->atom_UTF8_STRING, FALSE))
00393 return FALSE;
00394
00395 if (results->n_items > 0 &&
00396 !g_utf8_validate ((gchar *)results->prop, results->n_items, NULL))
00397 {
00398 char *name;
00399
00400 name = XGetAtomName (results->display->xdisplay, results->xatom);
00401 meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"),
00402 name, results->xwindow);
00403 meta_XFree (name);
00404 XFree (results->prop);
00405 results->prop = NULL;
00406
00407 return FALSE;
00408 }
00409
00410 *str_p = (char*) results->prop;
00411 results->prop = NULL;
00412
00413 return TRUE;
00414 }
00415
00416 gboolean
00417 meta_prop_get_utf8_string (MetaDisplay *display,
00418 Window xwindow,
00419 Atom xatom,
00420 char **str_p)
00421 {
00422 GetPropertyResults results;
00423
00424 *str_p = NULL;
00425
00426 if (!get_property (display, xwindow, xatom,
00427 display->atom_UTF8_STRING,
00428 &results))
00429 return FALSE;
00430
00431 return utf8_string_from_results (&results, str_p);
00432 }
00433
00434
00435 static gboolean
00436 utf8_list_from_results (GetPropertyResults *results,
00437 char ***str_p,
00438 int *n_str_p)
00439 {
00440 int i;
00441 int n_strings;
00442 char **retval;
00443 const char *p;
00444
00445 *str_p = NULL;
00446 *n_str_p = 0;
00447
00448 if (!validate_or_free_results (results, 8,
00449 results->display->atom_UTF8_STRING, FALSE))
00450 return FALSE;
00451
00452
00453
00454
00455 i = 0;
00456 n_strings = 0;
00457 while (i < (int) results->n_items)
00458 {
00459 if (results->prop[i] == '\0')
00460 ++n_strings;
00461 ++i;
00462 }
00463
00464 if (results->prop[results->n_items - 1] != '\0')
00465 ++n_strings;
00466
00467
00468
00469
00470
00471 retval = g_new0 (char*, n_strings + 1);
00472
00473 p = (char *)results->prop;
00474 i = 0;
00475 while (i < n_strings)
00476 {
00477 if (!g_utf8_validate (p, -1, NULL))
00478 {
00479 char *name;
00480
00481 meta_error_trap_push (results->display);
00482 name = XGetAtomName (results->display->xdisplay, results->xatom);
00483 meta_error_trap_pop (results->display, TRUE);
00484 meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
00485 name, results->xwindow, i);
00486 meta_XFree (name);
00487 meta_XFree (results->prop);
00488 results->prop = NULL;
00489
00490 g_strfreev (retval);
00491 return FALSE;
00492 }
00493
00494 retval[i] = g_strdup (p);
00495
00496 p = p + strlen (p) + 1;
00497 ++i;
00498 }
00499
00500 *str_p = retval;
00501 *n_str_p = i;
00502
00503 meta_XFree (results->prop);
00504 results->prop = NULL;
00505
00506 return TRUE;
00507 }
00508
00509
00510 gboolean
00511 meta_prop_get_utf8_list (MetaDisplay *display,
00512 Window xwindow,
00513 Atom xatom,
00514 char ***str_p,
00515 int *n_str_p)
00516 {
00517 GetPropertyResults results;
00518
00519 *str_p = NULL;
00520
00521 if (!get_property (display, xwindow, xatom,
00522 display->atom_UTF8_STRING,
00523 &results))
00524 return FALSE;
00525
00526 return utf8_list_from_results (&results, str_p, n_str_p);
00527 }
00528
00529 void
00530 meta_prop_set_utf8_string_hint (MetaDisplay *display,
00531 Window xwindow,
00532 Atom atom,
00533 const char *val)
00534 {
00535 meta_error_trap_push (display);
00536 XChangeProperty (display->xdisplay,
00537 xwindow, atom,
00538 display->atom_UTF8_STRING,
00539 8, PropModeReplace, (guchar*) val, strlen (val));
00540 meta_error_trap_pop (display, FALSE);
00541 }
00542
00543 static gboolean
00544 window_from_results (GetPropertyResults *results,
00545 Window *window_p)
00546 {
00547 if (!validate_or_free_results (results, 32, XA_WINDOW, TRUE))
00548 return FALSE;
00549
00550 *window_p = *(Window*) results->prop;
00551 XFree (results->prop);
00552 results->prop = NULL;
00553
00554 return TRUE;
00555 }
00556
00557 #ifdef HAVE_XSYNC
00558 static gboolean
00559 counter_from_results (GetPropertyResults *results,
00560 XSyncCounter *counter_p)
00561 {
00562 if (!validate_or_free_results (results, 32,
00563 XA_CARDINAL,
00564 TRUE))
00565 return FALSE;
00566
00567 *counter_p = *(XSyncCounter*) results->prop;
00568 XFree (results->prop);
00569 results->prop = NULL;
00570
00571 return TRUE;
00572 }
00573 #endif
00574
00575 gboolean
00576 meta_prop_get_window (MetaDisplay *display,
00577 Window xwindow,
00578 Atom xatom,
00579 Window *window_p)
00580 {
00581 GetPropertyResults results;
00582
00583 *window_p = None;
00584
00585 if (!get_property (display, xwindow, xatom, XA_WINDOW,
00586 &results))
00587 return FALSE;
00588
00589 return window_from_results (&results, window_p);
00590 }
00591
00592 gboolean
00593 meta_prop_get_cardinal (MetaDisplay *display,
00594 Window xwindow,
00595 Atom xatom,
00596 gulong *cardinal_p)
00597 {
00598 return meta_prop_get_cardinal_with_atom_type (display, xwindow, xatom,
00599 XA_CARDINAL, cardinal_p);
00600 }
00601
00602 static gboolean
00603 cardinal_with_atom_type_from_results (GetPropertyResults *results,
00604 Atom prop_type,
00605 gulong *cardinal_p)
00606 {
00607 if (!validate_or_free_results (results, 32, prop_type, TRUE))
00608 return FALSE;
00609
00610 *cardinal_p = *(gulong*) results->prop;
00611 XFree (results->prop);
00612 results->prop = NULL;
00613
00614 return TRUE;
00615 }
00616
00617 gboolean
00618 meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
00619 Window xwindow,
00620 Atom xatom,
00621 Atom prop_type,
00622 gulong *cardinal_p)
00623 {
00624 GetPropertyResults results;
00625
00626 *cardinal_p = 0;
00627
00628 if (!get_property (display, xwindow, xatom, prop_type,
00629 &results))
00630 return FALSE;
00631
00632 return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p);
00633 }
00634
00635 static gboolean
00636 text_property_from_results (GetPropertyResults *results,
00637 char **utf8_str_p)
00638 {
00639 XTextProperty tp;
00640
00641 *utf8_str_p = NULL;
00642
00643 tp.value = results->prop;
00644 results->prop = NULL;
00645 tp.encoding = results->type;
00646 tp.format = results->format;
00647 tp.nitems = results->n_items;
00648
00649 *utf8_str_p = meta_text_property_to_utf8 (results->display->xdisplay,
00650 &tp);
00651
00652 if (tp.value != NULL)
00653 XFree (tp.value);
00654
00655 return *utf8_str_p != NULL;
00656 }
00657
00658 gboolean
00659 meta_prop_get_text_property (MetaDisplay *display,
00660 Window xwindow,
00661 Atom xatom,
00662 char **utf8_str_p)
00663 {
00664 GetPropertyResults results;
00665
00666 if (!get_property (display, xwindow, xatom, AnyPropertyType,
00667 &results))
00668 return FALSE;
00669
00670 return text_property_from_results (&results, utf8_str_p);
00671 }
00672
00673
00674 #ifndef cvtINT32toInt
00675 #if SIZEOF_VOID_P == 8
00676 #define cvtINT8toInt(val) (((val) & 0x00000080) ? ((val) | 0xffffffffffffff00) : (val))
00677 #define cvtINT16toInt(val) (((val) & 0x00008000) ? ((val) | 0xffffffffffff0000) : (val))
00678 #define cvtINT32toInt(val) (((val) & 0x80000000) ? ((val) | 0xffffffff00000000) : (val))
00679 #define cvtINT8toShort(val) cvtINT8toInt(val)
00680 #define cvtINT16toShort(val) cvtINT16toInt(val)
00681 #define cvtINT32toShort(val) cvtINT32toInt(val)
00682 #define cvtINT8toLong(val) cvtINT8toInt(val)
00683 #define cvtINT16toLong(val) cvtINT16toInt(val)
00684 #define cvtINT32toLong(val) cvtINT32toInt(val)
00685 #else
00686 #define cvtINT8toInt(val) (val)
00687 #define cvtINT16toInt(val) (val)
00688 #define cvtINT32toInt(val) (val)
00689 #define cvtINT8toShort(val) (val)
00690 #define cvtINT16toShort(val) (val)
00691 #define cvtINT32toShort(val) (val)
00692 #define cvtINT8toLong(val) (val)
00693 #define cvtINT16toLong(val) (val)
00694 #define cvtINT32toLong(val) (val)
00695 #endif
00696 #endif
00697
00698 static gboolean
00699 wm_hints_from_results (GetPropertyResults *results,
00700 XWMHints **hints_p)
00701 {
00702 XWMHints *hints;
00703 xPropWMHints *raw;
00704
00705 *hints_p = NULL;
00706
00707 if (!validate_or_free_results (results, 32, XA_WM_HINTS, TRUE))
00708 return FALSE;
00709
00710
00711 if (results->n_items < (NumPropWMHintsElements - 1))
00712 {
00713 meta_verbose ("WM_HINTS property too short: %d should be %d\n",
00714 (int) results->n_items, NumPropWMHintsElements - 1);
00715 if (results->prop)
00716 {
00717 XFree (results->prop);
00718 results->prop = NULL;
00719 }
00720 return FALSE;
00721 }
00722
00723 hints = ag_Xmalloc0 (sizeof (XWMHints));
00724
00725 raw = (xPropWMHints*) results->prop;
00726
00727 hints->flags = raw->flags;
00728 hints->input = (raw->input ? True : False);
00729 hints->initial_state = cvtINT32toInt (raw->initialState);
00730 hints->icon_pixmap = raw->iconPixmap;
00731 hints->icon_window = raw->iconWindow;
00732 hints->icon_x = cvtINT32toInt (raw->iconX);
00733 hints->icon_y = cvtINT32toInt (raw->iconY);
00734 hints->icon_mask = raw->iconMask;
00735 if (results->n_items >= NumPropWMHintsElements)
00736 hints->window_group = raw->windowGroup;
00737 else
00738 hints->window_group = 0;
00739
00740 if (results->prop)
00741 {
00742 XFree (results->prop);
00743 results->prop = NULL;
00744 }
00745
00746 *hints_p = hints;
00747
00748 return TRUE;
00749 }
00750
00751 gboolean
00752 meta_prop_get_wm_hints (MetaDisplay *display,
00753 Window xwindow,
00754 Atom xatom,
00755 XWMHints **hints_p)
00756 {
00757 GetPropertyResults results;
00758
00759 *hints_p = NULL;
00760
00761 if (!get_property (display, xwindow, xatom, XA_WM_HINTS,
00762 &results))
00763 return FALSE;
00764
00765 return wm_hints_from_results (&results, hints_p);
00766 }
00767
00768 static gboolean
00769 class_hint_from_results (GetPropertyResults *results,
00770 XClassHint *class_hint)
00771 {
00772 int len_name, len_class;
00773
00774 class_hint->res_class = NULL;
00775 class_hint->res_name = NULL;
00776
00777 if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
00778 return FALSE;
00779
00780 len_name = strlen ((char *) results->prop);
00781 if (! (class_hint->res_name = ag_Xmalloc (len_name+1)))
00782 {
00783 XFree (results->prop);
00784 results->prop = NULL;
00785 return FALSE;
00786 }
00787
00788 strcpy (class_hint->res_name, (char *)results->prop);
00789
00790 if (len_name == (int) results->n_items)
00791 len_name--;
00792
00793 len_class = strlen ((char *)results->prop + len_name + 1);
00794
00795 if (! (class_hint->res_class = ag_Xmalloc(len_class+1)))
00796 {
00797 XFree(class_hint->res_name);
00798 class_hint->res_name = NULL;
00799 XFree (results->prop);
00800 results->prop = NULL;
00801 return FALSE;
00802 }
00803
00804 strcpy (class_hint->res_class, (char *)results->prop + len_name + 1);
00805
00806 XFree (results->prop);
00807 results->prop = NULL;
00808
00809 return TRUE;
00810 }
00811
00812 gboolean
00813 meta_prop_get_class_hint (MetaDisplay *display,
00814 Window xwindow,
00815 Atom xatom,
00816 XClassHint *class_hint)
00817 {
00818 GetPropertyResults results;
00819
00820 class_hint->res_class = NULL;
00821 class_hint->res_name = NULL;
00822
00823 if (!get_property (display, xwindow, xatom, XA_STRING,
00824 &results))
00825 return FALSE;
00826
00827 return class_hint_from_results (&results, class_hint);
00828 }
00829
00830 static gboolean
00831 size_hints_from_results (GetPropertyResults *results,
00832 XSizeHints **hints_p,
00833 gulong *flags_p)
00834 {
00835 xPropSizeHints *raw;
00836 XSizeHints *hints;
00837
00838 *hints_p = NULL;
00839 *flags_p = 0;
00840
00841 if (!validate_or_free_results (results, 32, XA_WM_SIZE_HINTS, FALSE))
00842 return FALSE;
00843
00844 if (results->n_items < OldNumPropSizeElements)
00845 return FALSE;
00846
00847 raw = (xPropSizeHints*) results->prop;
00848
00849 hints = ag_Xmalloc (sizeof (XSizeHints));
00850
00851
00852 hints->flags = raw->flags;
00853 hints->x = cvtINT32toInt (raw->x);
00854 hints->y = cvtINT32toInt (raw->y);
00855 hints->width = cvtINT32toInt (raw->width);
00856 hints->height = cvtINT32toInt (raw->height);
00857 hints->min_width = cvtINT32toInt (raw->minWidth);
00858 hints->min_height = cvtINT32toInt (raw->minHeight);
00859 hints->max_width = cvtINT32toInt (raw->maxWidth);
00860 hints->max_height = cvtINT32toInt (raw->maxHeight);
00861 hints->width_inc = cvtINT32toInt (raw->widthInc);
00862 hints->height_inc = cvtINT32toInt (raw->heightInc);
00863 hints->min_aspect.x = cvtINT32toInt (raw->minAspectX);
00864 hints->min_aspect.y = cvtINT32toInt (raw->minAspectY);
00865 hints->max_aspect.x = cvtINT32toInt (raw->maxAspectX);
00866 hints->max_aspect.y = cvtINT32toInt (raw->maxAspectY);
00867
00868 *flags_p = (USPosition | USSize | PAllHints);
00869 if (results->n_items >= NumPropSizeElements)
00870 {
00871 hints->base_width= cvtINT32toInt (raw->baseWidth);
00872 hints->base_height= cvtINT32toInt (raw->baseHeight);
00873 hints->win_gravity= cvtINT32toInt (raw->winGravity);
00874 *flags_p |= (PBaseSize | PWinGravity);
00875 }
00876
00877 hints->flags &= (*flags_p);
00878
00879 XFree (results->prop);
00880 results->prop = NULL;
00881
00882 *hints_p = hints;
00883
00884 return TRUE;
00885 }
00886
00887 gboolean
00888 meta_prop_get_size_hints (MetaDisplay *display,
00889 Window xwindow,
00890 Atom xatom,
00891 XSizeHints **hints_p,
00892 gulong *flags_p)
00893 {
00894 GetPropertyResults results;
00895
00896 *hints_p = NULL;
00897 *flags_p = 0;
00898
00899 if (!get_property (display, xwindow, xatom, XA_WM_SIZE_HINTS,
00900 &results))
00901 return FALSE;
00902
00903 return size_hints_from_results (&results, hints_p, flags_p);
00904 }
00905
00906 static AgGetPropertyTask*
00907 get_task (MetaDisplay *display,
00908 Window xwindow,
00909 Atom xatom,
00910 Atom req_type)
00911 {
00912 return ag_task_create (display->xdisplay,
00913 xwindow,
00914 xatom, 0, G_MAXLONG,
00915 False, req_type);
00916 }
00917
00918 static char*
00919 latin1_to_utf8 (const char *text)
00920 {
00921 GString *str;
00922 const char *p;
00923
00924 str = g_string_new ("");
00925
00926 p = text;
00927 while (*p)
00928 {
00929 g_string_append_unichar (str, *p);
00930 ++p;
00931 }
00932
00933 return g_string_free (str, FALSE);
00934 }
00935
00936 void
00937 meta_prop_get_values (MetaDisplay *display,
00938 Window xwindow,
00939 MetaPropValue *values,
00940 int n_values)
00941 {
00942 int i;
00943 AgGetPropertyTask **tasks;
00944
00945 meta_verbose ("Requesting %d properties of 0x%lx at once\n",
00946 n_values, xwindow);
00947
00948 if (n_values == 0)
00949 return;
00950
00951 tasks = g_new0 (AgGetPropertyTask*, n_values);
00952
00953
00954
00955
00956 i = 0;
00957 while (i < n_values)
00958 {
00959 if (values[i].required_type == None)
00960 {
00961 switch (values[i].type)
00962 {
00963 case META_PROP_VALUE_INVALID:
00964
00965
00966
00967 if (values[i].atom != None)
00968 meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC);
00969 break;
00970 case META_PROP_VALUE_UTF8_LIST:
00971 case META_PROP_VALUE_UTF8:
00972 values[i].required_type = display->atom_UTF8_STRING;
00973 break;
00974 case META_PROP_VALUE_STRING:
00975 case META_PROP_VALUE_STRING_AS_UTF8:
00976 values[i].required_type = XA_STRING;
00977 break;
00978 case META_PROP_VALUE_MOTIF_HINTS:
00979 values[i].required_type = AnyPropertyType;
00980 break;
00981 case META_PROP_VALUE_CARDINAL_LIST:
00982 case META_PROP_VALUE_CARDINAL:
00983 values[i].required_type = XA_CARDINAL;
00984 break;
00985 case META_PROP_VALUE_WINDOW:
00986 values[i].required_type = XA_WINDOW;
00987 break;
00988 case META_PROP_VALUE_ATOM_LIST:
00989 values[i].required_type = XA_ATOM;
00990 break;
00991 case META_PROP_VALUE_TEXT_PROPERTY:
00992 values[i].required_type = AnyPropertyType;
00993 break;
00994 case META_PROP_VALUE_WM_HINTS:
00995 values[i].required_type = XA_WM_HINTS;
00996 break;
00997 case META_PROP_VALUE_CLASS_HINT:
00998 values[i].required_type = XA_STRING;
00999 break;
01000 case META_PROP_VALUE_SIZE_HINTS:
01001 values[i].required_type = XA_WM_SIZE_HINTS;
01002 break;
01003 case META_PROP_VALUE_SYNC_COUNTER:
01004 values[i].required_type = XA_CARDINAL;
01005 break;
01006 }
01007 }
01008
01009 if (values[i].atom != None)
01010 tasks[i] = get_task (display, xwindow,
01011 values[i].atom, values[i].required_type);
01012
01013 ++i;
01014 }
01015
01016
01017 meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n",
01018 n_values, G_STRFUNC);
01019 XSync (display->xdisplay, False);
01020
01021
01022 i = 0;
01023 while (i < n_values)
01024 {
01025 AgGetPropertyTask *task;
01026 GetPropertyResults results;
01027
01028 if (tasks[i] == NULL)
01029 {
01030
01031
01032
01033 values[i].type = META_PROP_VALUE_INVALID;
01034 goto next;
01035 }
01036
01037 task = ag_get_next_completed_task (display->xdisplay);
01038 g_assert (task != NULL);
01039 g_assert (ag_task_have_reply (task));
01040
01041 results.display = display;
01042 results.xwindow = xwindow;
01043 results.xatom = values[i].atom;
01044 results.prop = NULL;
01045 results.n_items = 0;
01046 results.type = None;
01047 results.bytes_after = 0;
01048 results.format = 0;
01049
01050 if (ag_task_get_reply_and_free (task,
01051 &results.type, &results.format,
01052 &results.n_items,
01053 &results.bytes_after,
01054 (unsigned char **)(&results.prop)) != Success ||
01055 results.type == None)
01056 {
01057 values[i].type = META_PROP_VALUE_INVALID;
01058 if (results.prop)
01059 {
01060 XFree (results.prop);
01061 results.prop = NULL;
01062 }
01063 goto next;
01064 }
01065
01066 switch (values[i].type)
01067 {
01068 case META_PROP_VALUE_INVALID:
01069 g_assert_not_reached ();
01070 break;
01071 case META_PROP_VALUE_UTF8_LIST:
01072 if (!utf8_list_from_results (&results,
01073 &values[i].v.string_list.strings,
01074 &values[i].v.string_list.n_strings))
01075 values[i].type = META_PROP_VALUE_INVALID;
01076 break;
01077 case META_PROP_VALUE_UTF8:
01078 if (!utf8_string_from_results (&results,
01079 &values[i].v.str))
01080 values[i].type = META_PROP_VALUE_INVALID;
01081 break;
01082 case META_PROP_VALUE_STRING:
01083 if (!latin1_string_from_results (&results,
01084 &values[i].v.str))
01085 values[i].type = META_PROP_VALUE_INVALID;
01086 break;
01087 case META_PROP_VALUE_STRING_AS_UTF8:
01088 if (!latin1_string_from_results (&results,
01089 &values[i].v.str))
01090 values[i].type = META_PROP_VALUE_INVALID;
01091 else
01092 {
01093 char *new_str;
01094 char *xmalloc_new_str;
01095
01096 new_str = latin1_to_utf8 (values[i].v.str);
01097 xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1);
01098 if (xmalloc_new_str != NULL)
01099 {
01100 strcpy (xmalloc_new_str, new_str);
01101 meta_XFree (values[i].v.str);
01102 values[i].v.str = xmalloc_new_str;
01103 }
01104
01105 g_free (new_str);
01106 }
01107 break;
01108 case META_PROP_VALUE_MOTIF_HINTS:
01109 if (!motif_hints_from_results (&results,
01110 &values[i].v.motif_hints))
01111 values[i].type = META_PROP_VALUE_INVALID;
01112 break;
01113 case META_PROP_VALUE_CARDINAL_LIST:
01114 if (!cardinal_list_from_results (&results,
01115 &values[i].v.cardinal_list.cardinals,
01116 &values[i].v.cardinal_list.n_cardinals))
01117 values[i].type = META_PROP_VALUE_INVALID;
01118 break;
01119 case META_PROP_VALUE_CARDINAL:
01120 if (!cardinal_with_atom_type_from_results (&results,
01121 values[i].required_type,
01122 &values[i].v.cardinal))
01123 values[i].type = META_PROP_VALUE_INVALID;
01124 break;
01125 case META_PROP_VALUE_WINDOW:
01126 if (!window_from_results (&results,
01127 &values[i].v.xwindow))
01128 values[i].type = META_PROP_VALUE_INVALID;
01129 break;
01130 case META_PROP_VALUE_ATOM_LIST:
01131 if (!atom_list_from_results (&results,
01132 &values[i].v.atom_list.atoms,
01133 &values[i].v.atom_list.n_atoms))
01134 values[i].type = META_PROP_VALUE_INVALID;
01135 break;
01136 case META_PROP_VALUE_TEXT_PROPERTY:
01137 if (!text_property_from_results (&results, &values[i].v.str))
01138 values[i].type = META_PROP_VALUE_INVALID;
01139 break;
01140 case META_PROP_VALUE_WM_HINTS:
01141 if (!wm_hints_from_results (&results, &values[i].v.wm_hints))
01142 values[i].type = META_PROP_VALUE_INVALID;
01143 break;
01144 case META_PROP_VALUE_CLASS_HINT:
01145 if (!class_hint_from_results (&results, &values[i].v.class_hint))
01146 values[i].type = META_PROP_VALUE_INVALID;
01147 break;
01148 case META_PROP_VALUE_SIZE_HINTS:
01149 if (!size_hints_from_results (&results,
01150 &values[i].v.size_hints.hints,
01151 &values[i].v.size_hints.flags))
01152 values[i].type = META_PROP_VALUE_INVALID;
01153 break;
01154 case META_PROP_VALUE_SYNC_COUNTER:
01155 #ifdef HAVE_XSYNC
01156 if (!counter_from_results (&results,
01157 &values[i].v.xcounter))
01158 values[i].type = META_PROP_VALUE_INVALID;
01159 #else
01160 values[i].type = META_PROP_VALUE_INVALID;
01161 if (results.prop)
01162 {
01163 XFree (results.prop);
01164 results.prop = NULL;
01165 }
01166 #endif
01167 break;
01168 }
01169
01170 next:
01171 ++i;
01172 }
01173
01174 g_free (tasks);
01175 }
01176
01177 static void
01178 free_value (MetaPropValue *value)
01179 {
01180 switch (value->type)
01181 {
01182 case META_PROP_VALUE_INVALID:
01183 break;
01184 case META_PROP_VALUE_UTF8:
01185 case META_PROP_VALUE_STRING:
01186 case META_PROP_VALUE_STRING_AS_UTF8:
01187 meta_XFree (value->v.str);
01188 break;
01189 case META_PROP_VALUE_MOTIF_HINTS:
01190 meta_XFree (value->v.motif_hints);
01191 break;
01192 case META_PROP_VALUE_CARDINAL:
01193 break;
01194 case META_PROP_VALUE_WINDOW:
01195 break;
01196 case META_PROP_VALUE_ATOM_LIST:
01197 meta_XFree (value->v.atom_list.atoms);
01198 break;
01199 case META_PROP_VALUE_TEXT_PROPERTY:
01200 meta_XFree (value->v.str);
01201 break;
01202 case META_PROP_VALUE_WM_HINTS:
01203 meta_XFree (value->v.wm_hints);
01204 break;
01205 case META_PROP_VALUE_CLASS_HINT:
01206 meta_XFree (value->v.class_hint.res_class);
01207 meta_XFree (value->v.class_hint.res_name);
01208 break;
01209 case META_PROP_VALUE_SIZE_HINTS:
01210 meta_XFree (value->v.size_hints.hints);
01211 break;
01212 case META_PROP_VALUE_UTF8_LIST:
01213 g_strfreev (value->v.string_list.strings);
01214 break;
01215 case META_PROP_VALUE_CARDINAL_LIST:
01216 meta_XFree (value->v.cardinal_list.cardinals);
01217 break;
01218 case META_PROP_VALUE_SYNC_COUNTER:
01219 break;
01220 }
01221 }
01222
01223 void
01224 meta_prop_free_values (MetaPropValue *values,
01225 int n_values)
01226 {
01227 int i;
01228
01229 i = 0;
01230 while (i < n_values)
01231 {
01232 free_value (&values[i]);
01233 ++i;
01234 }
01235
01236
01237 memset (values, '\0', sizeof (MetaPropValue) * n_values);
01238 }