xprops.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* Metacity X property convenience routines */
00004 
00005 /* 
00006  * Copyright (C) 2001 Havoc Pennington
00007  * Copyright (C) 2002 Red Hat Inc.
00008  *
00009  * Some trivial property-unpacking code from Xlib:
00010  *   Copyright 1987, 1988, 1998  The Open Group
00011  *   Copyright 1988 by Wyse Technology, Inc., San Jose, Ca,
00012  *   Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
00013  * 
00014  * This program is free software; you can redistribute it and/or
00015  * modify it under the terms of the GNU General Public License as
00016  * published by the Free Software Foundation; either version 2 of the
00017  * License, or (at your option) any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful, but
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00022  * General Public License for more details.
00023  * 
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00027  * 02111-1307, USA.
00028  */
00029 
00030 /***********************************************************
00031 Copyright 1988 by Wyse Technology, Inc., San Jose, Ca,
00032 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
00033 
00034                         All Rights Reserved
00035 
00036 Permission to use, copy, modify, and distribute this software and its 
00037 documentation for any purpose and without fee is hereby granted, 
00038 provided that the above copyright notice appear in all copies and that
00039 both that copyright notice and this permission notice appear in 
00040 supporting documentation, and that the name Digital not be
00041 used in advertising or publicity pertaining to distribution of the
00042 software without specific, written prior permission.  
00043 
00044 DIGITAL AND WYSE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
00045 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 
00046 EVENT SHALL DIGITAL OR WYSE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
00047 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 
00048 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 
00049 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
00050 PERFORMANCE OF THIS SOFTWARE.
00051 
00052 ******************************************************************/
00053 
00054 /*
00055 
00056 Copyright 1987, 1988, 1998  The Open Group
00057 
00058 Permission to use, copy, modify, distribute, and sell this software and its
00059 documentation for any purpose is hereby granted without fee, provided that
00060 the above copyright notice appear in all copies and that both that
00061 copyright notice and this permission notice appear in supporting
00062 documentation.
00063 
00064 The above copyright notice and this permission notice shall be included
00065 in all copies or substantial portions of the Software.
00066 
00067 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00068 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00069 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00070 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
00071 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00072 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00073 OTHER DEALINGS IN THE SOFTWARE.
00074 
00075 Except as contained in this notice, the name of The Open Group shall
00076 not be used in advertising or otherwise to promote the sale, use or
00077 other dealings in this Software without prior written authorization
00078 from The Open Group.
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   /* The issue here is that some old crufty code will set a smaller
00310    * MotifWmHints than the one we expect, apparently.  I'm not sure of
00311    * the history behind it. See bug #89841 for example.
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 /* this one freakishly returns g_malloc memory */
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   /* I'm not sure this is right, but I'm guessing the
00453    * property is nul-separated
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   /* we're guaranteed that results->prop has a nul on the end
00468    * by XGetWindowProperty
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 /* returns g_malloc not Xmalloc memory */
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 /* From Xmd.h */
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 /* SIZEOF_VOID_P == 8 */
00696 #endif /* cvtINT32toInt() */
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   /* pre-R3 bogusly truncated window_group, don't fail on them */  
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   /* XSizeHints misdeclares these as int instead of long */
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);   /* get rid of unwanted bits */
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   /* Start up tasks. The "values" array can have values
00954    * with atom == None, which means to ignore that element.
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               /* This means we don't really want a value, e.g. got
00965                * property notify on an atom we don't care about.
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   /* Get replies for all our tasks */
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   /* Collect results, should arrive in order requested */
01022   i = 0;
01023   while (i < n_values)
01024     {
01025       AgGetPropertyTask *task;
01026       GetPropertyResults results;
01027       
01028       if (tasks[i] == NULL)
01029         {
01030           /* Probably values[i].type was None, or ag_task_create()
01031            * returned NULL.
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   /* Zero the whole thing to quickly detect breakage */
01237   memset (values, '\0', sizeof (MetaPropValue) * n_values);
01238 }

Generated on Sat Aug 23 22:04:18 2008 for metacity by  doxygen 1.5.5