]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkscreen-x11.c
Fixes from #98358, Havoc Pennington.
[~andy/gtk] / gdk / x11 / gdkscreen-x11.c
index 91b7d6858dd75b34efe2f107c2322870a10b738b..c8f819727b4e02573a75f0632fc9e2958466bc72 100644 (file)
@@ -21,6 +21,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
 #include <glib.h>
 #include "gdkscreen.h"
 #include "gdkscreen-x11.h"
 #include "gdkdisplay-x11.h"
 #include "gdkx.h"
 
+#ifdef HAVE_XFT
+#include <pango/pangoxft.h>
+#endif
+#include <pango/pangox.h>
+
 #ifdef HAVE_SOLARIS_XINERAMA
 #include <X11/extensions/xinerama.h>
 #endif
 #endif
 
 static void         gdk_screen_x11_class_init  (GdkScreenX11Class *klass);
+static void         gdk_screen_x11_dispose     (GObject                  *object);
 static void         gdk_screen_x11_finalize    (GObject                  *object);
 static void        init_xinerama_support      (GdkScreen         *screen);
+static void        init_randr_support         (GdkScreen         *screen);
 
+enum
+{
+  WINDOW_MANAGER_CHANGED,
+  LAST_SIGNAL
+};
 
 static gpointer parent_class = NULL;
+static guint signals[LAST_SIGNAL] = { 0 };
 
 GType
 _gdk_screen_x11_get_type ()
@@ -68,11 +82,25 @@ _gdk_screen_x11_get_type ()
   return object_type;
 }
 
-void
-gdk_screen_x11_class_init (GdkScreenX11Class * klass)
+static void
+gdk_screen_x11_class_init (GdkScreenX11Class *klass)
 {
-  G_OBJECT_CLASS (klass)->finalize = gdk_screen_x11_finalize;
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  object_class->dispose = gdk_screen_x11_dispose;
+  object_class->finalize = gdk_screen_x11_finalize;
+
   parent_class = g_type_class_peek_parent (klass);
+
+  signals[WINDOW_MANAGER_CHANGED] =
+    g_signal_new ("window_manager_changed",
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE,
+                  0);
 }
 
 /**
@@ -216,10 +244,38 @@ void
 gdk_screen_set_default_colormap (GdkScreen   *screen,
                                 GdkColormap *colormap)
 {
+  GdkColormap *old_colormap;
+  
   g_return_if_fail (GDK_IS_SCREEN (screen));
   g_return_if_fail (GDK_IS_COLORMAP (colormap));
+
+  old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
+
+  GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
   
-  GDK_SCREEN_X11 (screen)->default_colormap = colormap;
+  if (old_colormap)
+    g_object_unref (old_colormap);
+}
+
+static void
+gdk_screen_x11_dispose (GObject *object)
+{
+  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
+
+  _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
+
+  g_object_unref (screen_x11->default_colormap);
+  screen_x11->default_colormap = NULL;
+  
+  screen_x11->root_window = NULL;
+
+  screen_x11->xdisplay = NULL;
+  screen_x11->xscreen = NULL;
+  screen_x11->screen_num = -1;
+  screen_x11->xroot_window = None;
+  screen_x11->wmspec_check_window = None;
+  
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
@@ -227,16 +283,22 @@ gdk_screen_x11_finalize (GObject *object)
 {
   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
   /* int i; */
-  g_object_unref (G_OBJECT (screen_x11->root_window));
+  g_object_unref (screen_x11->root_window);
   
   /* Visual Part (Need to implement finalize for Visuals for a clean
    * finalize) */
   /* for (i=0;i<screen_x11->nvisuals;i++)
-    g_object_unref (G_OBJECT (screen_x11->visuals[i]));*/
+    g_object_unref (screen_x11->visuals[i]);*/
   g_free (screen_x11->visuals);
   g_hash_table_destroy (screen_x11->visual_hash);
+
+  g_free (screen_x11->window_manager_name);  
+
+  g_hash_table_destroy (screen_x11->colormap_hash);
   /* X settings */
   g_free (screen_x11->xsettings_client);
+  g_free (screen_x11->monitors);
+  
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -278,6 +340,7 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
 {
   g_return_if_fail (GDK_IS_SCREEN (screen));
   g_return_if_fail (monitor_num < GDK_SCREEN_X11 (screen)->num_monitors);
+  g_return_if_fail (monitor_num >= 0);
 
   *dest = GDK_SCREEN_X11 (screen)->monitors[monitor_num];
 }
@@ -327,12 +390,14 @@ _gdk_x11_screen_new (GdkDisplay *display,
   screen_x11->screen_num = screen_number;
   screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
   screen_x11->wmspec_check_window = None;
-
+  /* we want this to be always non-null */
+  screen_x11->window_manager_name = g_strdup ("unknown");
+  
   init_xinerama_support (screen);
+  init_randr_support (screen);
   
   _gdk_visual_init (screen);
   _gdk_windowing_window_init (screen);
-  _gdk_x11_events_init_screen (screen);
 
   return screen;
 }
@@ -390,6 +455,7 @@ check_xfree_xinerama (GdkScreen *screen)
 #ifdef HAVE_XFREE_XINERAMA
   if (XineramaIsActive (GDK_SCREEN_XDISPLAY (screen)))
     {
+      GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
       XineramaScreenInfo *monitors = XineramaQueryScreens (GDK_SCREEN_XDISPLAY (screen),
                                                           &screen_x11->num_monitors);
       if (screen_x11->num_monitors <= 0)
@@ -427,11 +493,14 @@ static void
 init_xinerama_support (GdkScreen * screen)
 {
   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
-  
 #ifdef HAVE_XINERAMA
   int opcode, firstevent, firsterror;
-  gint result;
+#endif
+
+  if (screen_x11->monitors)
+    g_free (screen_x11->monitors);
   
+#ifdef HAVE_XINERAMA  
   if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
                       &opcode, &firstevent, &firsterror))
     {
@@ -451,3 +520,104 @@ init_xinerama_support (GdkScreen * screen)
   screen_x11->monitors[0].height = HeightOfScreen (screen_x11->xscreen);
 }
 
+static void
+init_randr_support (GdkScreen * screen)
+{
+  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+  
+  XSelectInput (GDK_SCREEN_XDISPLAY (screen),
+               screen_x11->xroot_window,
+               StructureNotifyMask);
+}
+
+void
+_gdk_x11_screen_size_changed (GdkScreen *screen,
+                             XEvent    *event)
+{
+#ifdef HAVE_RANDR
+  if (!XRRUpdateConfiguration (event))
+    return;
+#else
+  if (event->type == ConfigureNotify)
+    {
+      XConfigureEvent *rcevent = (XConfigureEvent *) event;
+      Screen       *xscreen = gdk_x11_screen_get_xscreen (screen);
+      
+      xscreen->width   = rcevent->width;
+      xscreen->height  = rcevent->height;
+    }
+  else
+    return;
+#endif
+  
+  init_xinerama_support (screen);
+  g_signal_emit_by_name (G_OBJECT (screen), "size_changed");
+}
+
+void
+_gdk_x11_screen_window_manager_changed (GdkScreen *screen)
+{
+  g_signal_emit (G_OBJECT (screen),
+                 signals[WINDOW_MANAGER_CHANGED], 0);
+}
+
+/**
+ * _gdk_windowing_substitute_screen_number:
+ * @display_name : The name of a display, in the form used by 
+ *                 gdk_display_open (). If %NULL a default value
+ *                 will be used. On X11, this is derived from the DISPLAY
+ *                 environment variable.
+ * @screen_number : The number of a screen within the display
+ *                  referred to by @display_name.
+ *
+ * Modifies a @display_name to make @screen_number the default
+ * screen when the display is opened.
+ *
+ * Return value: a newly allocated string holding the resulting
+ *   display name. Free with g_free().
+ */
+gchar * 
+_gdk_windowing_substitute_screen_number (const gchar *display_name,
+                                        gint         screen_number)
+{
+  GString *str;
+  gchar   *p;
+
+  if (!display_name)
+    display_name = getenv ("DISPLAY");
+
+  if (!display_name)
+    return NULL;
+
+  str = g_string_new (display_name);
+
+  p = strrchr (str->str, '.');
+  if (p && p > strchr (str->str, ':'))
+    g_string_truncate (str, p - str->str);
+
+  g_string_append_printf (str, ".%d", screen_number);
+
+  return g_string_free (str, FALSE);
+}
+
+/**
+ * gdk_screen_make_display_name:
+ * @screen: a #GdkScreen
+ * 
+ * Determines the name to pass to gdk_display_open() to get
+ * a #GdkDisplay with this screen as the default screen.
+ * 
+ * Return value: a newly allocated string, free with g_free()
+ **/
+gchar *
+gdk_screen_make_display_name (GdkScreen *screen)
+{
+  const gchar *old_display;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  old_display = gdk_display_get_name (gdk_screen_get_display (screen));
+
+  return _gdk_windowing_substitute_screen_number (old_display, 
+                                                 gdk_screen_get_number (screen));
+}