[gtk+] Create a proper subclass of GdkScreen: GdkScreenQuartz



commit d47772f002efdb1d88b61d8176ea432e7a8b5106
Author: Kristian Rietveld <kris gtk org>
Date:   Sat Oct 24 11:48:39 2009 +0200

    Create a proper subclass of GdkScreen: GdkScreenQuartz

 gdk/quartz/Makefile.am         |    1 +
 gdk/quartz/gdkdisplay-quartz.c |    8 +-
 gdk/quartz/gdkprivate-quartz.h |    3 -
 gdk/quartz/gdkscreen-quartz.c  |  302 ++++++++++++++++++++--------------------
 gdk/quartz/gdkscreen-quartz.h  |   62 ++++++++
 5 files changed, 222 insertions(+), 154 deletions(-)
---
diff --git a/gdk/quartz/Makefile.am b/gdk/quartz/Makefile.am
index 2c3e621..a5721b1 100644
--- a/gdk/quartz/Makefile.am
+++ b/gdk/quartz/Makefile.am
@@ -46,6 +46,7 @@ libgdk_quartz_la_SOURCES =    	\
 	gdkproperty-quartz.c	\
 	gdkquartz.h		\
 	gdkscreen-quartz.c	\
+	gdkscreen-quartz.h	\
 	gdkselection-quartz.c	\
 	gdkspawn-quartz.c	\
 	gdktestutils-quartz.c	\
diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c
index fd38da1..957bb43 100644
--- a/gdk/quartz/gdkdisplay-quartz.c
+++ b/gdk/quartz/gdkdisplay-quartz.c
@@ -22,6 +22,7 @@
 
 #include "gdk.h"
 #include "gdkprivate-quartz.h"
+#include "gdkscreen-quartz.h"
 
 GdkWindow *
 gdk_display_get_default_group (GdkDisplay *display)
@@ -51,13 +52,14 @@ gdk_display_open (const gchar *display_name)
   [NSApplication sharedApplication];
 
   _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
-  _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
+
+  _gdk_visual_init ();
+
+  _gdk_screen = _gdk_screen_quartz_new ();
 
   nsscreen = [[NSScreen screens] objectAtIndex:0];
   gdk_screen_set_resolution (_gdk_screen, 72.0 * [nsscreen userSpaceScaleFactor]);
 
-  _gdk_visual_init ();
-  _gdk_quartz_screen_init ();
   _gdk_windowing_window_init ();
 
   _gdk_events_init ();
diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h
index 86db886..52834b3 100644
--- a/gdk/quartz/gdkprivate-quartz.h
+++ b/gdk/quartz/gdkprivate-quartz.h
@@ -152,9 +152,6 @@ void       _gdk_quartz_window_debug_highlight       (GdkWindow *window,
 void       _gdk_quartz_window_set_needs_display_in_rect (GdkWindow    *window,
                                                          GdkRectangle *rect);
 
-/* Screen */
-void       _gdk_quartz_screen_init (void);
-
 /* Events */
 typedef enum {
   GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c
index 41d51c7..4c08109 100644
--- a/gdk/quartz/gdkscreen-quartz.c
+++ b/gdk/quartz/gdkscreen-quartz.c
@@ -20,20 +20,89 @@
 
 #include "config.h"
 #include "gdk.h"
+#include "gdkscreen-quartz.h"
 #include "gdkprivate-quartz.h"
  
-/* FIXME: If we want to do it properly, this should be stored
- * in a proper GdkScreen subclass.
- */
-static GdkColormap *default_colormap = NULL;
-static int n_screens = 0;
-static GdkRectangle *screen_rects = NULL;
 
-static guint screen_changed_id = 0;
+static void  gdk_screen_quartz_dispose          (GObject         *object);
+static void  gdk_screen_quartz_finalize         (GObject         *object);
+static void  gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen);
+
+static void display_reconfiguration_callback (CGDirectDisplayID            display,
+                                              CGDisplayChangeSummaryFlags  flags,
+                                              void                        *userInfo);
+
+G_DEFINE_TYPE (GdkScreenQuartz, _gdk_screen_quartz, GDK_TYPE_SCREEN);
+
+static void
+_gdk_screen_quartz_class_init (GdkScreenQuartzClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gdk_screen_quartz_dispose;
+  object_class->finalize = gdk_screen_quartz_finalize;
+}
+
+static void
+_gdk_screen_quartz_init (GdkScreenQuartz *screen_quartz)
+{
+  GdkScreen *screen = GDK_SCREEN (screen_quartz);
+
+  gdk_screen_set_default_colormap (screen,
+                                   gdk_screen_get_system_colormap (screen));
+
+  gdk_screen_quartz_calculate_layout (screen_quartz);
+
+  CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback,
+                                            screen);
+}
+
+static void
+gdk_screen_quartz_dispose (GObject *object)
+{
+  GdkScreenQuartz *screen = GDK_SCREEN_QUARTZ (object);
+
+  if (screen->default_colormap)
+    {
+      g_object_unref (screen->default_colormap);
+      screen->default_colormap = NULL;
+    }
 
+  if (screen->screen_changed_id)
+    {
+      g_source_remove (screen->screen_changed_id);
+      screen->screen_changed_id = 0;
+    }
+
+  CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback,
+                                          screen);
+
+  G_OBJECT_CLASS (_gdk_screen_quartz_parent_class)->dispose (object);
+}
 
 static void
-screen_rects_init (void)
+gdk_screen_quartz_screen_rects_free (GdkScreenQuartz *screen)
+{
+  screen->n_screens = 0;
+
+  if (screen->screen_rects)
+    {
+      g_free (screen->screen_rects);
+      screen->screen_rects = NULL;
+    }
+}
+
+static void
+gdk_screen_quartz_finalize (GObject *object)
+{
+  GdkScreenQuartz *screen = GDK_SCREEN_QUARTZ (object);
+
+  gdk_screen_quartz_screen_rects_free (screen);
+}
+
+
+static void
+gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen)
 {
   NSArray *array;
   NSRect largest_rect;
@@ -41,14 +110,29 @@ screen_rects_init (void)
 
   GDK_QUARTZ_ALLOC_POOL;
 
-  array = [NSScreen screens];
+  gdk_screen_quartz_screen_rects_free (screen);
 
-  n_screens = [array count];
-  screen_rects = g_new0 (GdkRectangle, n_screens);
+  array = [NSScreen screens];
 
-  /* FIXME: as stated above the get_width() and get_height() functions
-   * in this file, we only support horizontal screen layouts for now.
+  /* FIXME: For now we only support screen layouts where the screens are laid
+   * out horizontally.  Mac OS X also supports laying out the screens vertically
+   * and the screens having "non-standard" offsets from eachother.  In the
+   * future we need a much more sophiscated algorithm to translate these
+   * layouts to GDK coordinate space and GDK screen layout.
    */
+  screen->width = 0;
+  screen->height = 0;
+
+  for (i = 0; i < [array count]; i++)
+    {
+      NSRect rect = [[array objectAtIndex:i] frame];
+
+      screen->width += rect.size.width;
+      screen->height = MAX (screen->height, rect.size.height);
+    }
+
+  screen->n_screens = [array count];
+  screen->screen_rects = g_new0 (GdkRectangle, screen->n_screens);
 
   /* Find the monitor with the largest height.  All monitors should be
    * offset to this one in the GDK screen space instead of offset to
@@ -63,7 +147,7 @@ screen_rects_init (void)
         largest_rect = [[array objectAtIndex:i] frame];
     }
 
-  for (i = 0; i < n_screens; i++)
+  for (i = 0; i < screen->n_screens; i++)
     {
       NSScreen *nsscreen;
       NSRect rect;
@@ -71,57 +155,54 @@ screen_rects_init (void)
       nsscreen = [array objectAtIndex:i];
       rect = [nsscreen frame];
 
-      screen_rects[i].x = rect.origin.x;
-      screen_rects[i].width = rect.size.width;
-      screen_rects[i].height = rect.size.height;
+      screen->screen_rects[i].x = rect.origin.x;
+      screen->screen_rects[i].width = rect.size.width;
+      screen->screen_rects[i].height = rect.size.height;
 
       if (largest_rect.size.height - rect.size.height == 0)
-        screen_rects[i].y = 0;
+        screen->screen_rects[i].y = 0;
       else
-        screen_rects[i].y = largest_rect.size.height - rect.size.height + largest_rect.origin.y;
+        screen->screen_rects[i].y = largest_rect.size.height - rect.size.height + largest_rect.origin.y;
     }
 
   GDK_QUARTZ_RELEASE_POOL;
 }
 
+
 static void
-screen_rects_free (void)
+process_display_reconfiguration (GdkScreenQuartz *screen)
 {
-  n_screens = 0;
+  int width, height;
 
-  g_free (screen_rects);
-  screen_rects = NULL;
-}
+  width = gdk_screen_get_width (GDK_SCREEN (screen));
+  height = gdk_screen_get_height (GDK_SCREEN (screen));
 
+  gdk_screen_quartz_calculate_layout (GDK_SCREEN_QUARTZ (screen));
 
-static void
-process_display_reconfiguration (void)
-{
-  screen_rects_free ();
-  screen_rects_init ();
-
-  /* FIXME: We should only emit this when the size of screen really
-   * has changed.  We need to start bookkeeping width, height once
-   * we have a proper GdkScreen subclass.
-   */
-  g_signal_emit_by_name (_gdk_screen, "size-changed");
+  if (width != gdk_screen_get_width (GDK_SCREEN (screen))
+      || height != gdk_screen_get_height (GDK_SCREEN (screen)))
+    g_signal_emit_by_name (_gdk_screen, "size-changed");
 }
 
 static gboolean
 screen_changed_idle (gpointer data)
 {
-  process_display_reconfiguration ();
+  GdkScreenQuartz *screen = data;
+
+  process_display_reconfiguration (data);
 
-  screen_changed_id = 0;
+  screen->screen_changed_id = 0;
 
   return FALSE;
 }
 
 static void
-screen_changed (CGDirectDisplayID            display,
-                CGDisplayChangeSummaryFlags  flags,
-                void                        *userInfo)
+display_reconfiguration_callback (CGDirectDisplayID            display,
+                                  CGDisplayChangeSummaryFlags  flags,
+                                  void                        *userInfo)
 {
+  GdkScreenQuartz *screen = userInfo;
+
   if (flags & kCGDisplayBeginConfigurationFlag)
     {
       /* Ignore the begin configuration signal. */
@@ -137,21 +218,16 @@ screen_changed (CGDirectDisplayID            display,
        * yet, so we delay our refresh into an idle handler.
        */
 
-      if (!screen_changed_id)
-        screen_changed_id = gdk_threads_add_idle (screen_changed_idle, NULL);
+      if (!screen->screen_changed_id)
+        screen->screen_changed_id = gdk_threads_add_idle (screen_changed_idle,
+                                                          screen);
     }
 }
 
-void
-_gdk_quartz_screen_init (void)
+GdkScreen *
+_gdk_screen_quartz_new (void)
 {
-  gdk_screen_set_default_colormap (_gdk_screen,
-                                   gdk_screen_get_system_colormap (_gdk_screen));
-
-  screen_rects_init ();
-
-  CGDisplayRegisterReconfigurationCallback (screen_changed,
-                                            _gdk_screen);
+  return g_object_new (GDK_TYPE_SCREEN_QUARTZ, NULL);
 }
 
 GdkDisplay *
@@ -192,7 +268,9 @@ _gdk_windowing_substitute_screen_number (const gchar *display_name,
 GdkColormap*
 gdk_screen_get_default_colormap (GdkScreen *screen)
 {
-  return default_colormap;
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return GDK_SCREEN_QUARTZ (screen)->default_colormap;
 }
 
 void
@@ -204,67 +282,28 @@ gdk_screen_set_default_colormap (GdkScreen   *screen,
   g_return_if_fail (GDK_IS_SCREEN (screen));
   g_return_if_fail (GDK_IS_COLORMAP (colormap));
 
-  old_colormap = default_colormap;
+  old_colormap = GDK_SCREEN_QUARTZ (screen)->default_colormap;
 
-  default_colormap = g_object_ref (colormap);
+  GDK_SCREEN_QUARTZ (screen)->default_colormap = g_object_ref (colormap);
   
   if (old_colormap)
     g_object_unref (old_colormap);
 }
 
-/* FIXME: note on the get_width() and the get_height() methods.  For
- * now we only support screen layouts where the screens are laid out
- * horizontally.  Mac OS X also supports laying out the screens vertically
- * and the screens having "non-standard" offsets from eachother.  In the
- * future we need a much more sophiscated algorithm to translate these
- * layouts to GDK coordinate space and GDK screen layout.
- */
 gint
 gdk_screen_get_width (GdkScreen *screen)
 {
-  int i;
-  int width;
-  NSArray *array;
-
   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
 
-  GDK_QUARTZ_ALLOC_POOL;
-  array = [NSScreen screens];
-
-  width = 0;
-  for (i = 0; i < [array count]; i++) 
-    {
-      NSRect rect = [[array objectAtIndex:i] frame];
-      width += rect.size.width;
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return width;
+  return GDK_SCREEN_QUARTZ (screen)->width;
 }
 
 gint
 gdk_screen_get_height (GdkScreen *screen)
 {
-  int i;
-  int height;
-  NSArray *array;
-
   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
 
-  GDK_QUARTZ_ALLOC_POOL;
-  array = [NSScreen screens];
-
-  height = 0;
-  for (i = 0; i < [array count]; i++) 
-    {
-      NSRect rect = [[array objectAtIndex:i] frame];
-      height = MAX (height, rect.size.height);
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return height;
+  return GDK_SCREEN_QUARTZ (screen)->height;
 }
 
 static gint
@@ -283,79 +322,46 @@ get_mm_from_pixels (NSScreen *screen, int pixels)
   return (pixels / dpi) * 25.4;
 }
 
-gint
-gdk_screen_get_width_mm (GdkScreen *screen)
+static NSScreen *
+get_nsscreen_for_monitor (gint monitor_num)
 {
-  int i;
-  gint width;
   NSArray *array;
-
-  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+  NSScreen *screen;
 
   GDK_QUARTZ_ALLOC_POOL;
-  array = [NSScreen screens];
 
-  width = 0;
-  for (i = 0; i < [array count]; i++)
-    {
-      NSScreen *screen = [array objectAtIndex:i];
-      NSRect rect = [screen frame];
-      width += get_mm_from_pixels (screen, rect.size.width);
-    }
+  array = [NSScreen screens];
+  screen = [array objectAtIndex:monitor_num];
 
   GDK_QUARTZ_RELEASE_POOL;
 
-  return width;
+  return screen;
 }
 
 gint
-gdk_screen_get_height_mm (GdkScreen *screen)
+gdk_screen_get_width_mm (GdkScreen *screen)
 {
-  int i;
-  gint height;
-  NSArray *array;
-
   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
 
-  GDK_QUARTZ_ALLOC_POOL;
-  array = [NSScreen screens];
-
-  height = 0;
-  for (i = 0; i < [array count]; i++)
-    {
-      NSScreen *screen = [array objectAtIndex:i];
-      NSRect rect = [screen frame];
-      gint h = get_mm_from_pixels (screen, rect.size.height);
-      height = MAX (height, h);
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return height;
+  return get_mm_from_pixels (get_nsscreen_for_monitor (0),
+                             GDK_SCREEN_QUARTZ (screen)->width);
 }
 
-int
-gdk_screen_get_n_monitors (GdkScreen *screen)
+gint
+gdk_screen_get_height_mm (GdkScreen *screen)
 {
   g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
 
-  return n_screens;
+  return get_mm_from_pixels (get_nsscreen_for_monitor (0),
+                             GDK_SCREEN_QUARTZ (screen)->height);
 }
 
-static NSScreen *
-get_nsscreen_for_monitor (gint monitor_num)
+int
+gdk_screen_get_n_monitors (GdkScreen *screen)
 {
-  NSArray *array;
-  NSScreen *screen;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  array = [NSScreen screens];
-  screen = [array objectAtIndex:monitor_num];
-
-  GDK_QUARTZ_RELEASE_POOL;
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
 
-  return screen;
+  return GDK_SCREEN_QUARTZ (screen)->n_screens;
 }
 
 gint
@@ -367,7 +373,7 @@ gdk_screen_get_monitor_width_mm	(GdkScreen *screen,
   g_return_val_if_fail (monitor_num >= 0, 0);
 
   return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num),
-                             screen_rects[monitor_num].width);
+                             GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num].width);
 }
 
 gint
@@ -379,7 +385,7 @@ gdk_screen_get_monitor_height_mm (GdkScreen *screen,
   g_return_val_if_fail (monitor_num >= 0, 0);
 
   return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num),
-                             screen_rects[monitor_num].height);
+                             GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num].height);
 }
 
 gchar *
@@ -399,7 +405,7 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
   g_return_if_fail (monitor_num < gdk_screen_get_n_monitors (screen));
   g_return_if_fail (monitor_num >= 0);
 
-  *dest = screen_rects[monitor_num];
+  *dest = GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num];
 }
 
 gchar *
diff --git a/gdk/quartz/gdkscreen-quartz.h b/gdk/quartz/gdkscreen-quartz.h
new file mode 100644
index 0000000..a67401d
--- /dev/null
+++ b/gdk/quartz/gdkscreen-quartz.h
@@ -0,0 +1,62 @@
+/* gdkscreen-quartz.h
+ *
+ * Copyright (C) 2009  Kristian Rietveld  <kris gtk org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDK_SCREEN_QUARTZ_H__
+#define __GDK_SCREEN_QUARTZ_H__
+
+G_BEGIN_DECLS
+
+typedef struct _GdkScreenQuartz GdkScreenQuartz;
+typedef struct _GdkScreenQuartzClass GdkScreenQuartzClass;
+
+#define GDK_TYPE_SCREEN_QUARTZ              (_gdk_screen_quartz_get_type ())
+#define GDK_SCREEN_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartz))
+#define GDK_SCREEN_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartzClass))
+#define GDK_IS_SCREEN_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SCREEN_QUARTZ))
+#define GDK_IS_SCREEN_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SCREEN_QUARTZ))
+#define GDK_SCREEN_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartzClass))
+
+struct _GdkScreenQuartz
+{
+  GdkScreen parent_instance;
+
+  GdkDisplay *display;
+  GdkColormap *default_colormap;
+
+  gint width;
+  gint height;
+
+  int n_screens;
+  GdkRectangle *screen_rects;
+
+  guint screen_changed_id;
+};
+
+struct _GdkScreenQuartzClass
+{
+  GdkScreenClass parent_class;
+};
+
+GType      _gdk_screen_quartz_get_type (void);
+GdkScreen *_gdk_screen_quartz_new      (void);
+
+G_END_DECLS
+
+#endif /* _GDK_SCREEN_QUARTZ_H_ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]