gboolean
gdk_property_get (GdkWindow   *window,
		  GdkAtom      property,
		  GdkAtom      type,
		  gulong       offset,
		  gulong       length,
		  gint         pdelete,
		  GdkAtom     *actual_property_type,
		  gint        *actual_format_type,
		  gint        *actual_length,
		  guchar     **data)
{
  GdkDisplay *display;
  Atom ret_prop_type;
  gint ret_format;
  gulong ret_nitems;
  gulong ret_bytes_after;
  gulong get_length;
  gulong ret_length;
  guchar *ret_data;
  Atom xproperty;
  Atom xtype;
  int res;

  g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);

  if (!window)
    {
      GdkScreen *screen = gdk_screen_get_default ();
      window = gdk_screen_get_root_window (screen);
      
      GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
    }
  else if (!GDK_WINDOW_IS_X11 (window))
    return FALSE;

  if (GDK_WINDOW_DESTROYED (window))
    return FALSE;

  display = gdk_drawable_get_display (window);
  xproperty = gdk_x11_atom_to_xatom_for_display (display, property);
  if (type == GDK_NONE)
    xtype = AnyPropertyType;
  else
    xtype = gdk_x11_atom_to_xatom_for_display (display, type);

  ret_data = NULL;
  
  /* 
   * Round up length to next 4 byte value.  Some code is in the (bad?)
   * habit of passing G_MAXLONG as the length argument, causing an
   * overflow to negative on the add.  In this case, we clamp the
   * value to G_MAXLONG.
   */
  get_length = length + 3;
  if (get_length > G_MAXLONG)
    get_length = G_MAXLONG;

  /* To fail, either the user passed 0 or G_MAXULONG */
  get_length = get_length / 4;
  if (get_length == 0)
    {
      g_warning ("gdk_propery-get(): invalid length 0");
      return FALSE;
    }

  res = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
			    GDK_WINDOW_XWINDOW (window), xproperty,
			    offset, get_length, pdelete,
			    xtype, &ret_prop_type, &ret_format,
			    &ret_nitems, &ret_bytes_after,
			    &ret_data);

  if (res != Success || (ret_prop_type == None && ret_format == 0))
    {
      return FALSE;
    }

  if (actual_property_type)
    *actual_property_type = gdk_x11_xatom_to_atom_for_display (display, ret_prop_type);
  if (actual_format_type)
    *actual_format_type = ret_format;

  if ((xtype != AnyPropertyType) && (ret_prop_type != xtype))
    {
      XFree (ret_data);
      g_warning ("Couldn't match property type %s to %s\n", 
		 gdk_x11_get_xatom_name_for_display (display, ret_prop_type), 
		 gdk_x11_get_xatom_name_for_display (display, xtype));
      return FALSE;
    }

  /* FIXME: ignoring bytes_after could have very bad effects */

  if (data)
    {
      if (ret_prop_type == XA_ATOM ||
	  ret_prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
	{
	  /*
	   * data is an array of X atom, we need to convert it
	   * to an array of GDK Atoms
	   */
	  gint i;
	  GdkAtom *ret_atoms = g_new (GdkAtom, ret_nitems);
	  Atom *xatoms = (Atom *)ret_data;

	  *data = (guchar *)ret_atoms;

	  for (i = 0; i < ret_nitems; i++)
	    ret_atoms[i] = gdk_x11_xatom_to_atom_for_display (display, xatoms[i]);
	  
	  if (actual_length)
	    *actual_length = ret_nitems * sizeof (GdkAtom);
	}
      else
	{
	  switch (ret_format)
	    {
	    case 8:
	      ret_length = ret_nitems;
	      break;
	    case 16:
	      ret_length = sizeof(short) * ret_nitems;
	      break;
	    case 32:
	      ret_length = sizeof(long) * ret_nitems;
	      break;
	    default:
	      g_warning ("unknown property return format: %d", ret_format);
	      XFree (ret_data);
	      return FALSE;
	    }
	  
	  *data = g_new (guchar, ret_length);
	  memcpy (*data, ret_data, ret_length);
	  if (actual_length)
	    *actual_length = ret_length;
	}
    }

  XFree (ret_data);

  return TRUE;
}
Example #2
0
static void
read_settings (GdkX11Screen *x11_screen,
               gboolean      do_notify)
{
  GdkScreen *screen = GDK_SCREEN (x11_screen);

  Atom type;
  int format;
  unsigned long n_items;
  unsigned long bytes_after;
  unsigned char *data;
  int result;

  GHashTable *old_list = x11_screen->xsettings;
  GValue value = G_VALUE_INIT;
  GValue *setting, *copy;

  x11_screen->xsettings = NULL;

  if (x11_screen->xsettings_manager_window)
    {
      GdkDisplay *display = x11_screen->display;
      Atom xsettings_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XSETTINGS_SETTINGS");

      gdk_x11_display_error_trap_push (display);
      result = XGetWindowProperty (gdk_x11_display_get_xdisplay (display),
                                   gdk_x11_window_get_xid (x11_screen->xsettings_manager_window),
				   xsettings_atom, 0, LONG_MAX,
				   False, xsettings_atom,
				   &type, &format, &n_items, &bytes_after, &data);
      gdk_x11_display_error_trap_pop_ignored (display);
      
      if (result == Success && type != None)
	{
	  if (type != xsettings_atom)
	    {
	      g_warning ("Invalid type for XSETTINGS property: %s", gdk_x11_get_xatom_name_for_display (display, type));
	    }
	  else if (format != 8)
	    {
	      g_warning ("Invalid format for XSETTINGS property: %d", format);
	    }
	  else
	    x11_screen->xsettings = parse_settings (data, n_items);
	  
	  XFree (data);
	}
    }

  /* Since we support scaling we look at the specific Gdk/UnscaledDPI
     setting if it exists and use that instead of Xft/DPI if it is set */
  if (x11_screen->xsettings && !x11_screen->fixed_window_scale)
    {
      setting = g_hash_table_lookup (x11_screen->xsettings, "gdk-unscaled-dpi");
      if (setting)
	{
	  copy = g_new0 (GValue, 1);
	  g_value_init (copy, G_VALUE_TYPE (setting));
	  g_value_copy (setting, copy);
	  g_hash_table_insert (x11_screen->xsettings, 
			       "gtk-xft-dpi", copy);
	}
    }

  if (do_notify)
    notify_changes (x11_screen, old_list);
  if (old_list)
    g_hash_table_unref (old_list);

  g_value_init (&value, G_TYPE_INT);

  if (!screen->resolution_set)
    {
      /* This code is duplicated with gtksettings.c:settings_update_resolution().
       * The update of the screen resolution needs to happen immediately when
       * gdk_x11_display_set_window_scale() is called, and not wait for events
       * to be processed, so we can't always handling it in gtksettings.c.
       * But we can't always handle it here because the DPI can be set through
       * GtkSettings, which we don't have access to.
       */
      int dpi_int = 0;
      double dpi;
      const char *scale_env;
      double scale;

      if (gdk_screen_get_setting (GDK_SCREEN (x11_screen),
                                  "gtk-xft-dpi", &value))
        dpi_int = g_value_get_int (&value);

      if (dpi_int > 0)
        dpi = dpi_int / 1024.;
      else
        dpi = -1.;

      scale_env = g_getenv ("GDK_DPI_SCALE");
      if (scale_env)
        {
          scale = g_ascii_strtod (scale_env, NULL);
          if (scale != 0 && dpi > 0)
            dpi *= scale;
        }

      _gdk_screen_set_resolution (screen, dpi);
    }

  if (!x11_screen->fixed_window_scale &&
      gdk_screen_get_setting (GDK_SCREEN (x11_screen),
			      "gdk-window-scaling-factor", &value))
    _gdk_x11_screen_set_window_scale (x11_screen,
				      g_value_get_int (&value));
}