[gtk+/native-layout] Implement extended layout for plug/socket



commit 56edab35539fa81b8061dc7e963905b625bc2583
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 19 01:23:58 2009 -0500

    Implement extended layout for plug/socket

 gtk/gtkplug-x11.c      |   27 ++++++++++++++++++
 gtk/gtkplug.c          |    8 +++++
 gtk/gtkplugprivate.h   |    3 ++
 gtk/gtksocket-x11.c    |   62 +++++++++++++++++++++++++++++++++++++++++
 gtk/gtksocket.c        |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtksocketprivate.h |    4 ++
 6 files changed, 175 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkplug-x11.c b/gtk/gtkplug-x11.c
index 95dcf1a..fa81b61 100644
--- a/gtk/gtkplug-x11.c
+++ b/gtk/gtkplug-x11.c
@@ -32,6 +32,7 @@
 #include "gtkplugprivate.h"
 
 #include "x11/gdkx.h"
+#include <X11/Xatom.h>
 
 #include "gtkxembed.h"
 #include "gtkalias.h"
@@ -330,3 +331,29 @@ _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent,
 
   return return_val;
 }
+
+void
+_gtk_plug_windowing_publish_natural_size (GtkPlug        *plug,
+					  GtkRequisition *requisition)
+{
+  GtkWidget *widget = GTK_WIDGET (plug);
+  GdkDisplay *display;
+  GdkWindow *window;
+  gint32 data[2];
+  Atom property;
+
+  gtk_widget_realize (widget);
+
+  window = GTK_WIDGET (plug)->window;
+  display = gdk_drawable_get_display (window);
+  property = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE");
+
+  data[0] = requisition->width;
+  data[1] = requisition->height;
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+		   GDK_WINDOW_XWINDOW (window), property,
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (unsigned char*)data, 2);
+}
+
diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c
index 4c31ea7..593df8c 100644
--- a/gtk/gtkplug.c
+++ b/gtk/gtkplug.c
@@ -30,6 +30,7 @@
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkplug.h"
+#include "gtkextendedlayout.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkplugprivate.h"
@@ -721,6 +722,9 @@ static void
 gtk_plug_size_allocate (GtkWidget     *widget,
 			GtkAllocation *allocation)
 {
+  GtkBin *bin = GTK_BIN (widget);
+  GtkRequisition natural_size;
+
   if (GTK_WIDGET_TOPLEVEL (widget))
     GTK_WIDGET_CLASS (gtk_plug_parent_class)->size_allocate (widget, allocation);
   else
@@ -748,6 +752,10 @@ gtk_plug_size_allocate (GtkWidget     *widget,
 	}
       
     }
+
+   gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (bin->child),
+                                         NULL, &natural_size);
+   _gtk_plug_windowing_publish_natural_size (GTK_PLUG (widget), &natural_size);
 }
 
 static gboolean
diff --git a/gtk/gtkplugprivate.h b/gtk/gtkplugprivate.h
index 74f0374..83dcaaf 100644
--- a/gtk/gtkplugprivate.h
+++ b/gtk/gtkplugprivate.h
@@ -138,4 +138,7 @@ GdkFilterReturn _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent,
 						 GdkEvent  *event,
 						 gpointer   data);
 
+void _gtk_plug_windowing_publish_natural_size (GtkPlug        *plug,
+                                               GtkRequisition *requisition);
+
 #endif /* __GTK_PLUG_PRIVATE_H__ */
diff --git a/gtk/gtksocket-x11.c b/gtk/gtksocket-x11.c
index 5dbde45..c076f9d 100644
--- a/gtk/gtksocket-x11.c
+++ b/gtk/gtksocket-x11.c
@@ -39,6 +39,7 @@
 #include "gtkdnd.h"
 
 #include "x11/gdkx.h"
+#include <X11/Xatom.h>
 
 #ifdef HAVE_XFIXES
 #include <X11/extensions/Xfixes.h>
@@ -123,6 +124,63 @@ _gtk_socket_windowing_size_request (GtkSocket *socket)
 }
 
 void
+_gtk_socket_windowing_get_natural_size (GtkSocket *socket)
+{
+  GtkSocketPrivate *priv;
+  GdkDisplay *display;
+
+  Atom property, type;
+  int format, status;
+
+  unsigned long nitems, bytes_after;
+  unsigned char *data;
+  gint32 *data_long;
+
+  priv = _gtk_socket_get_private (socket);
+
+  priv->natural_width = 1;
+  priv->natural_height = 1;
+
+  if (GTK_WIDGET_MAPPED (socket))
+    {
+      display = gdk_drawable_get_display (socket->plug_window);
+      property = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE");
+
+      gdk_error_trap_push ();
+      status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+                                   GDK_WINDOW_XWINDOW (socket->plug_window),
+                                   property, 0, 2, False, XA_CARDINAL,
+                                   &type, &format, &nitems, &bytes_after,
+                                   &data);
+      gdk_error_trap_pop ();
+
+      priv->have_natural_size = TRUE;
+
+      if (Success != status || !type)
+        return;
+
+      if (type != XA_CARDINAL)
+        {
+          g_warning ("_GTK_NATURAL_SIZE property has wrong type: %d\n", (int)type);
+          return;
+        }
+
+      if (nitems < 2)
+        {
+          g_warning ("_GTK_NATURAL_SIZE too short\n");
+          XFree (data);
+          return;
+        }
+
+      data_long = (gint32*) data;
+      priv->natural_width = MAX (1, data_long[0]);
+      priv->natural_height = MAX (1, data_long[1]);
+
+      XFree (data);
+    }
+}
+
+void
 _gtk_socket_windowing_send_key_event (GtkSocket *socket,
 				      GdkEvent  *gdk_event,
 				      gboolean   mask_key_presses)
@@ -602,6 +660,10 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
 		}
 	      return_val = GDK_FILTER_REMOVE;
 	    }
+          else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE"))
+            {
+              _gtk_socket_windowing_get_natural_size (socket);
+            }
 	}
       break;
     case ReparentNotify:
diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c
index f059f8d..c109348 100644
--- a/gtk/gtksocket.c
+++ b/gtk/gtksocket.c
@@ -37,6 +37,7 @@
 #include "gtksocket.h"
 #include "gtksocketprivate.h"
 #include "gtkdnd.h"
+#include "gtkextendedlayout.h"
 #include "gtkintl.h"
 
 #include "gtkalias.h"
@@ -67,6 +68,7 @@ static void     gtk_socket_forall               (GtkContainer     *container,
 						 GtkCallback       callback,
 						 gpointer          callback_data);
 
+static void gtk_socket_extended_layout_interface_init (GtkExtendedLayoutIface *iface);
 
 /* Local data */
 
@@ -98,7 +100,10 @@ _gtk_socket_get_private (GtkSocket *socket)
   return G_TYPE_INSTANCE_GET_PRIVATE (socket, GTK_TYPE_SOCKET, GtkSocketPrivate);
 }
 
-G_DEFINE_TYPE (GtkSocket, gtk_socket, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkSocket, gtk_socket, GTK_TYPE_CONTAINER,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+                                                gtk_socket_extended_layout_interface_init))
+
 
 static void
 gtk_socket_finalize (GObject *object)
@@ -185,6 +190,8 @@ gtk_socket_class_init (GtkSocketClass *class)
 static void
 gtk_socket_init (GtkSocket *socket)
 {
+  GtkSocketPrivate *priv;
+
   socket->request_width = 0;
   socket->request_height = 0;
   socket->current_width = 0;
@@ -199,6 +206,9 @@ gtk_socket_init (GtkSocket *socket)
 
   socket->accel_group = gtk_accel_group_new ();
   g_object_set_data (G_OBJECT (socket->accel_group), I_("gtk-socket"), socket);
+
+  priv = _gtk_socket_get_private (socket);
+  priv->have_natural_size = FALSE;
 }
 
 /**
@@ -1000,5 +1010,65 @@ _gtk_socket_advance_toplevel_focus (GtkSocket        *socket,
     }
 }
 
+static void
+gtk_socket_extended_layout_get_desired_size (GtkExtendedLayout *layout,
+                                             GtkRequisition    *minimal_size,
+                                             GtkRequisition    *desired_size)
+{
+  GtkSocket *socket = GTK_SOCKET (layout);
+  GtkSocketPrivate *priv;
+
+  if (socket->plug_widget)
+    {
+      gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (socket->plug_widget),
+                                                                 minimal_size,
+                                                                 desired_size); 
+    }
+  else
+    {
+      priv = _gtk_socket_get_private (socket);
+
+      if (socket->is_mapped && !priv->have_natural_size && socket->plug_window)
+        {
+           _gtk_socket_windowing_size_request (socket);
+           _gtk_socket_windowing_get_natural_size (socket);
+        }
+
+      if (socket->is_mapped && priv->have_natural_size)
+	{
+          if (minimal_size)
+            {
+              minimal_size->width = MAX (socket->request_width, 1);
+              minimal_size->height = MAX (socket->request_height, 1);
+            }
+          if (desired_size)
+            {
+              desired_size->width = MAX (priv->natural_width, 1);
+              desired_size->height = MAX (priv->natural_height, 1);
+            }
+        }
+      else
+	{
+          if (minimal_size)
+            {
+              minimal_size->width = 1;
+              minimal_size->height = 1;
+            }
+          if (desired_size)
+            {
+              desired_size->width = 1;
+              desired_size->height = 1;
+            }
+        }
+    }
+}
+
+static void
+gtk_socket_extended_layout_interface_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_desired_size = gtk_socket_extended_layout_get_desired_size;
+}
+
+
 #define __GTK_SOCKET_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtksocketprivate.h b/gtk/gtksocketprivate.h
index 44a6c6b..8eda1ae 100644
--- a/gtk/gtksocketprivate.h
+++ b/gtk/gtksocketprivate.h
@@ -31,6 +31,9 @@ typedef struct _GtkSocketPrivate GtkSocketPrivate;
 struct _GtkSocketPrivate
 {
   gint resize_count;
+  gint natural_width;
+  gint natural_height;
+  gboolean have_natural_size;
 };
 
 /* In gtksocket.c: */
@@ -83,6 +86,7 @@ void _gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket);
  */
 void _gtk_socket_windowing_size_request (GtkSocket *socket);
 
+void _gtk_socket_windowing_get_natural_size (GtkSocket *socket);
 /*
  * _gtk_socket_windowing_send_key_event:
  *



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