Managed GtkWindow for GtkFB



Ok. Here is an initial patch for #ifdefed support for managed windows in
GtkWindow. There is no externally visible API changes, all conditional
changes of structures are hidden.

Is this acceptable?

Index: gtkinvisible.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkinvisible.c,v
retrieving revision 1.8
diff -u -p -r1.8 gtkinvisible.c
--- gtkinvisible.c	2000/12/11 16:43:47	1.8
+++ gtkinvisible.c	2000/12/18 14:44:12
@@ -134,6 +134,8 @@ gtk_invisible_realize (GtkWidget *widget

   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
   gdk_window_set_user_data (widget->window, widget);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
 }

 static void
Index: gtktooltips.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktooltips.c,v
retrieving revision 1.30
diff -u -p -r1.30 gtktooltips.c
--- gtktooltips.c	2000/12/04 16:11:51	1.30
+++ gtktooltips.c	2000/12/18 14:44:13
@@ -345,7 +345,8 @@ gtk_tooltips_draw_tips (GtkTooltips * to
   else
     y = y + widget->allocation.height + 4;

-  gtk_widget_popup (tooltips->tip_window, x, y);
+  gtk_widget_set_uposition (tooltips->tip_window, x, y);
+  gtk_widget_show (tooltips->tip_window);
 }

 static gint
Index: gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.93
diff -u -p -r1.93 gtkwindow.c
--- gtkwindow.c	2000/12/13 01:34:40	1.93
+++ gtkwindow.c	2000/12/18 14:44:14
@@ -29,6 +29,14 @@
 #include "gdk/gdk.h"
 #include "gdk/gdkkeysyms.h"

+#ifdef GDK_WINDOWING_FB
+#define DECORATE_WINDOWS
+#endif
+
+#ifdef DECORATE_WINDOWS
+#include "gtkinvisible.h"
+#endif
+
 #if defined (GDK_WINDOWING_X11)
 #include "x11/gdkx.h"
 #elif defined (GDK_WINDOWING_WIN32)
@@ -89,6 +97,64 @@ typedef struct {
   GtkWindowLastGeometryInfo last;
 } GtkWindowGeometryInfo;

+typedef enum {
+  GTK_WINDOW_REGION_TITLE,
+  GTK_WINDOW_REGION_CLOSE,
+  GTK_WINDOW_REGION_BR_RESIZE
+} GtkWindowRegionType;
+
+typedef struct _GtkWindowRegion GtkWindowRegion;
+
+struct _GtkWindowRegion
+{
+  GdkRectangle rect;
+  GtkWindowRegionType type;
+};
+
+typedef enum
+{
+  RESIZE_TOP_LEFT,
+  RESIZE_TOP,
+  RESIZE_TOP_RIGHT,
+  RESIZE_RIGHT,
+  RESIZE_BOTTOM_RIGHT,
+  RESIZE_BOTTOM,
+  RESIZE_BOTTOM_LEFT,
+  RESIZE_LEFT,
+  RESIZE_NONE,
+} GtkWindowResizeType;
+
+struct _GtkWindowPrivate {
+#ifdef DECORATE_WINDOWS
+  GdkWindow *outer_window;
+
+  GtkWidget *dummy_widget;
+
+  gint n_regions;
+  GtkWindowRegion *regions;
+
+  gint last_x, last_y;
+  PangoLayout *title_layout;
+
+  GtkWindowResizeType resize;
+
+  gboolean decorated : 1;
+
+  gboolean moving : 1;
+  gboolean closing : 1;
+#endif
+};
+
+#define DECORATION_BORDER_TOP 13
+#define DECORATION_BORDER_LEFT 3
+#define DECORATION_BORDER_RIGHT 3
+#define DECORATION_BORDER_BOTTOM 3
+#define DECORATION_BORDER_TOT_X (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT)
+#define DECORATION_BORDER_TOT_Y (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM)
+#define DECORATION_BUTTON_SIZE 8
+#define DECORATION_BUTTON_Y_OFFSET 2
+#define DECORATION_TITLE_FONT "Sans 7"
+
 static void gtk_window_class_init         (GtkWindowClass    *klass);
 static void gtk_window_init               (GtkWindow         *window);
 static void gtk_window_set_arg            (GtkObject         *object,
@@ -105,6 +171,7 @@ static void gtk_window_hide
 static void gtk_window_map                (GtkWidget         *widget);
 static void gtk_window_unmap              (GtkWidget         *widget);
 static void gtk_window_realize            (GtkWidget         *widget);
+static void gtk_window_unrealize          (GtkWidget         *widget);
 static void gtk_window_size_request       (GtkWidget         *widget,
 					   GtkRequisition    *requisition);
 static void gtk_window_size_allocate      (GtkWidget         *widget,
@@ -171,6 +238,42 @@ static GtkWindowGeometryInfo* gtk_window
 							    gboolean   create);
 static void gtk_window_geometry_destroy  (GtkWindowGeometryInfo *info);

+#ifdef DECORATE_WINDOWS
+static void gtk_decorated_window_calculate_decorations (GtkWindow      *window);
+static void gtk_decorated_window_resize                (GtkWindow      *window,
+						 gint            width,
+						 gint            height);
+static void gtk_decorated_window_move_resize           (GtkWindow      *window,
+						 gint            x,
+						 gint            y,
+						 gint            width,
+						 gint            height);
+static void gtk_decorated_window_move                  (GtkWindow      *window,
+						 gint            x,
+						 gint            y);
+static void gtk_decorated_window_recalculate_regions      (GtkWindow      *window);
+static GtkWindowRegionType gtk_decorated_window_region_type    (GtkWindow      *window,
+						 gint            x,
+						 gint            y);
+static gint gtk_decorated_window_button_press             (GtkWidget      *dummy_widget,
+						 GdkEventButton *event,
+						 GtkWidget      *widget);
+static gint gtk_decorated_window_button_release           (GtkWidget      *dummy_widget,
+						 GdkEventButton *event,
+						 GtkWidget      *widget);
+static gint gtk_decorated_window_motion_notify            (GtkWidget      *dummy_widget,
+						 GdkEventMotion *event,
+						 GtkWidget      *widget);
+static gint gtk_decorated_window_expose        (GtkWidget      *dummy_widget,
+						 GdkEventExpose *event,
+						 GtkWidget      *widget);
+static gint gtk_decorated_window_configure     (GtkWidget      *dummy_widget,
+						 GdkEventConfigure *event,
+						 GtkWidget      *widget);
+static void gtk_decorated_window_paint             (GtkWidget      *widget,
+						 GdkRectangle   *area);
+#endif
+
 static GSList      *toplevel_list = NULL;
 static GtkBinClass *parent_class = NULL;
 static guint        window_signals[LAST_SIGNAL] = { 0 };
@@ -227,6 +330,7 @@ gtk_window_class_init (GtkWindowClass *k
   widget_class->map = gtk_window_map;
   widget_class->unmap = gtk_window_unmap;
   widget_class->realize = gtk_window_realize;
+  widget_class->unrealize = gtk_window_unrealize;
   widget_class->size_request = gtk_window_size_request;
   widget_class->size_allocate = gtk_window_size_allocate;
   widget_class->configure_event = gtk_window_configure_event;
@@ -243,6 +347,7 @@ gtk_window_class_init (GtkWindowClass *k
   container_class->check_resize = gtk_window_check_resize;
   container_class->focus = gtk_window_focus;

+
   klass->set_focus = gtk_window_real_set_focus;

   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
@@ -289,10 +394,24 @@ gtk_window_init (GtkWindow *window)
   window->use_uposition = TRUE;
   window->modal = FALSE;

+  window->priv = g_new (GtkWindowPrivate, 1);
+
   gtk_widget_ref (GTK_WIDGET (window));
   gtk_object_sink (GTK_OBJECT (window));
   window->has_user_ref_count = TRUE;
   toplevel_list = g_slist_prepend (toplevel_list, window);
+
+#ifdef DECORATE_WINDOWS
+  window->priv->outer_window = NULL;
+  window->priv->dummy_widget = NULL;
+  window->priv->n_regions = 0;
+  window->priv->regions = NULL;
+  window->priv->title_layout = NULL;
+  window->priv->resize = RESIZE_NONE;
+  window->priv->decorated = TRUE;
+  window->priv->moving = FALSE;
+  window->priv->closing = FALSE;
+#endif
 }

 static void
@@ -426,7 +545,13 @@ gtk_window_set_title (GtkWindow   *windo
   window->title = g_strdup (title);

   if (GTK_WIDGET_REALIZED (window))
-    gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
+    {
+      gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
+#ifdef DECORATE_WINDOWS
+      if (window->priv->title_layout)
+	pango_layout_set_text (window->priv->title_layout, title, -1);
+#endif
+    }
 }

 void
@@ -697,8 +822,12 @@ gtk_window_reposition (GtkWindow *window
 					 &info->last.geometry,
 					 info->last.flags);
 	}
-
+
+#ifdef DECORATE_WINDOWS
+      gtk_decorated_window_move (window, x, y);
+#else
       gdk_window_move (GTK_WIDGET (window)->window, x, y);
+#endif
     }
 }

@@ -984,6 +1113,20 @@ gtk_window_finalize (GObject *object)
   g_free (window->wmclass_name);
   g_free (window->wmclass_class);

+  if (window->priv)
+    {
+#ifdef DECORATE_WINDOWS
+      GtkWindowPrivate *priv = window->priv;
+
+      g_free (priv->regions);
+      priv->regions = NULL;
+      priv->n_regions = 0;
+#endif
+
+      g_free (window->priv);
+      window->priv = NULL;
+    }
+
   G_OBJECT_CLASS(parent_class)->finalize (object);
 }

@@ -1027,9 +1170,23 @@ gtk_window_show (GtkWidget *widget)
       gtk_widget_size_allocate (widget, &allocation);

       if (GTK_WIDGET_REALIZED (widget))
-	gdk_window_resize (widget->window, width, height);
+	{
+#ifdef DECORATE_WINDOWS
+	  gtk_decorated_window_calculate_decorations (window);
+	  gtk_decorated_window_resize (window, width, height);
+#else
+	  gdk_window_resize (widget->window, width, height);
+#endif
+	}
       else
-	gtk_widget_realize (widget);
+	{
+
+	  gtk_widget_realize (widget);
+#ifdef DECORATE_WINDOWS
+	  gtk_decorated_window_calculate_decorations (window);
+	  gtk_decorated_window_resize (window, width, height);
+#endif
+	}
     }

   gtk_container_check_resize (container);
@@ -1075,6 +1232,10 @@ gtk_window_map (GtkWidget *widget)
     gtk_widget_map (window->bin.child);

   gdk_window_show (widget->window);
+#ifdef DECORATE_WINDOWS
+  if (window->priv->outer_window)
+    gdk_window_show (window->priv->outer_window);
+#endif
 }

 static void
@@ -1092,6 +1253,11 @@ gtk_window_unmap (GtkWidget *widget)
   window->use_uposition = TRUE;
   window->resize_count = 0;
   window->handling_resize = FALSE;
+
+#ifdef DECORATE_WINDOWS
+  if (window->priv->outer_window)
+    gdk_window_withdraw (window->priv->outer_window);
+#endif
 }

 static void
@@ -1100,7 +1266,7 @@ gtk_window_realize (GtkWidget *widget)
   GtkWindow *window;
   GdkWindowAttr attributes;
   gint attributes_mask;
-
+
   g_return_if_fail (GTK_IS_WINDOW (widget));

   window = GTK_WINDOW (widget);
@@ -1146,11 +1312,85 @@ gtk_window_realize (GtkWidget *widget)
   attributes.title = window->title;
   attributes.wmclass_name = window->wmclass_name;
   attributes.wmclass_class = window->wmclass_class;
-  attributes.width = widget->allocation.width;
-  attributes.height = widget->allocation.height;
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
+
+#ifdef DECORATE_WINDOWS
+  {
+    GtkWindowPrivate *priv = window->priv;
+    priv->title_layout = gtk_widget_create_pango_layout (widget, (window->title)?window->title:"");
+
+    pango_layout_set_font_description (priv->title_layout,
+				       pango_font_description_from_string(DECORATION_TITLE_FONT));
+
+    attributes.width = widget->allocation.width + DECORATION_BORDER_TOT_X;
+    attributes.height = widget->allocation.height + DECORATION_BORDER_TOT_Y;
+    attributes.event_mask = (GDK_EXPOSURE_MASK |
+			     GDK_ENTER_NOTIFY_MASK |
+			     GDK_LEAVE_NOTIFY_MASK |
+			     GDK_STRUCTURE_MASK |
+			     GDK_BUTTON_MOTION_MASK |
+			     GDK_POINTER_MOTION_HINT_MASK |
+			     GDK_BUTTON_PRESS_MASK |
+			     GDK_BUTTON_RELEASE_MASK);
+
+    attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
+    attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
+    attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
+
+    priv->outer_window = gdk_window_new (NULL, &attributes, attributes_mask);
+
+    priv->dummy_widget = gtk_invisible_new ();
+
+    gdk_window_set_user_data (priv->outer_window, priv->dummy_widget);
+
+    gtk_signal_connect (GTK_OBJECT (priv->dummy_widget),
+			"button_press_event",
+			GTK_SIGNAL_FUNC (gtk_decorated_window_button_press),
+			widget);
+    gtk_signal_connect (GTK_OBJECT (priv->dummy_widget),
+			"button_release_event",
+			GTK_SIGNAL_FUNC (gtk_decorated_window_button_release),
+			widget);
+    gtk_signal_connect (GTK_OBJECT (priv->dummy_widget),
+			"motion_notify_event",
+			GTK_SIGNAL_FUNC (gtk_decorated_window_motion_notify),
+			widget);
+    gtk_signal_connect (GTK_OBJECT (priv->dummy_widget),
+			"expose_event",
+			GTK_SIGNAL_FUNC (gtk_decorated_window_expose),
+			widget);
+    gtk_signal_connect (GTK_OBJECT (priv->dummy_widget),
+			"configure_event",
+			GTK_SIGNAL_FUNC (gtk_decorated_window_configure),
+			widget);
+
+    attributes.window_type = GDK_WINDOW_CHILD;
+    attributes.x = DECORATION_BORDER_LEFT;
+    attributes.y = DECORATION_BORDER_TOP;
+    attributes.width = widget->allocation.width;
+    attributes.height = widget->allocation.height;
+    attributes.event_mask = gtk_widget_get_events (widget);
+    attributes.event_mask |= (GDK_EXPOSURE_MASK |
+			      GDK_KEY_PRESS_MASK |
+			      GDK_ENTER_NOTIFY_MASK |
+			      GDK_LEAVE_NOTIFY_MASK |
+			      GDK_FOCUS_CHANGE_MASK |
+			      GDK_STRUCTURE_MASK);
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+    widget->window = gdk_window_new (priv->outer_window, &attributes, attributes_mask);
+    gdk_window_set_user_data (widget->window, window);
+
+    widget->style = gtk_style_attach (widget->style, widget->window);
+    gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+    gtk_style_set_background (widget->style, priv->outer_window, GTK_STATE_NORMAL);
+  }
+#else
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
 			    GDK_KEY_PRESS_MASK |
@@ -1158,25 +1398,61 @@ gtk_window_realize (GtkWidget *widget)
 			    GDK_LEAVE_NOTIFY_MASK |
 			    GDK_FOCUS_CHANGE_MASK |
 			    GDK_STRUCTURE_MASK);
-
+
   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
-
+
   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
   gdk_window_set_user_data (widget->window, window);
-
+
   widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-  gtk_window_paint (widget, NULL);
+#endif

+  gtk_window_paint (widget, NULL);
+#ifdef DECORATE_WINDOWS
+  gtk_decorated_window_paint (widget, NULL);
+#endif
+
   if (window->transient_parent &&
       GTK_WIDGET_REALIZED (window->transient_parent))
     gdk_window_set_transient_for (widget->window,
 				  GTK_WIDGET (window->transient_parent)->window);
+
 }

+
 static void
+gtk_window_unrealize (GtkWidget *widget)
+{
+#ifdef DECORATE_WINDOWS
+  GtkWindow *window;
+  GtkWindowPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WINDOW (widget));
+
+  window = GTK_WINDOW (widget);
+  priv = window->priv;
+
+  gdk_window_set_user_data (priv->outer_window, NULL);
+  gdk_window_destroy (priv->outer_window);
+  priv->outer_window = NULL;
+
+  gtk_widget_destroy (priv->dummy_widget);
+  priv->dummy_widget = NULL;
+
+  if (priv->title_layout)
+    {
+      g_object_unref (G_OBJECT (priv->title_layout));
+      priv->title_layout = NULL;
+    }
+#endif
+
+  (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
 gtk_window_size_request (GtkWidget      *widget,
 			 GtkRequisition *requisition)
 {
@@ -1203,7 +1479,6 @@ gtk_window_size_request (GtkWidget
       requisition->height += child_requisition.height;
     }
 }
-
 static void
 gtk_window_size_allocate (GtkWidget     *widget,
 			  GtkAllocation *allocation)
@@ -1229,6 +1504,14 @@ gtk_window_size_allocate (GtkWidget

       gtk_widget_size_allocate (window->bin.child, &child_allocation);
     }
+
+#ifdef DECORATE_WINDOWS
+  if (GTK_WIDGET_REALIZED (widget))
+    gtk_decorated_window_resize (window, allocation->width, allocation->height);
+
+  if (window->priv->decorated)
+    gtk_decorated_window_recalculate_regions (window);
+#endif
 }

 static gint
@@ -1236,7 +1519,6 @@ gtk_window_configure_event (GtkWidget
 			    GdkEventConfigure *event)
 {
   GtkWindow *window;
-
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
@@ -1274,7 +1556,7 @@ gtk_window_configure_event (GtkWidget

 	  widget->allocation.width = event->width;
 	  widget->allocation.height = event->height;
-
+
 	  gtk_widget_queue_resize (widget);
 	}
     }
@@ -1842,7 +2124,13 @@ gtk_window_move_resize (GtkWindow *windo
 	   */

 	  if (x != -1 && y != -1)
-	    gdk_window_move (widget->window, x, y);
+	    {
+#ifdef DECORATE_WINDOWS
+	      gtk_decorated_window_move (window, x, y);
+#else
+	      gdk_window_move (widget->window, x, y);
+#endif
+	    }

 	  /* we have to preserve the values and flags that are used
 	   * for computation of default_size_changed and hints_changed
@@ -1885,10 +2173,17 @@ gtk_window_move_resize (GtkWindow *windo
        */

       /* request a new window size */
+#ifdef DECORATE_WINDOWS
+      if (x != -1 && y != -1)
+	gtk_decorated_window_move_resize (window, x, y, new_width, new_height);
+      else
+	gtk_decorated_window_resize (window, new_width, new_height);
+#else
       if (x != -1 && y != -1)
 	gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
       else
 	gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+#endif
       window->resize_count += 1;

       /* we are now awaiting the new configure event in response to our
@@ -1912,7 +2207,13 @@ gtk_window_move_resize (GtkWindow *windo
   else
     {
       if (x != -1 && y != -1)
-	gdk_window_move (widget->window, x, y);
+	{
+#ifdef DECORATE_WINDOWS
+	  gtk_decorated_window_move (window, x, y);
+#else
+	  gdk_window_move (widget->window, x, y);
+#endif
+	}

       if (container->resize_widgets)
 	gtk_container_resize_children (GTK_CONTAINER (window));
@@ -2342,9 +2643,486 @@ gtk_window_expose (GtkWidget      *widge

   if (!GTK_WIDGET_APP_PAINTABLE (widget))
     gtk_window_paint (widget, &event->area);
-
+
   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+
+  return TRUE;
+}
+
+/****************************************
+ * FB code for handling managed windows *
+ ***************************************/
+
+#ifdef DECORATE_WINDOWS
+static gint
+gtk_decorated_window_configure (GtkWidget         *dummy_widget,
+				GdkEventConfigure *event,
+				GtkWidget         *widget)
+{
+  GtkWindow *window;
+
+  window = GTK_WINDOW (widget);
+
+  if (window->priv->decorated)
+    {
+      GdkRectangle rect;
+
+      /* Invalidate the decorations: */
+      rect.x = 0;
+      rect.y = 0;
+      rect.width = event->width;
+      rect.height = event->height;
+
+      gdk_window_invalidate_rect (window->priv->outer_window, &rect, FALSE);
+
+      event->width -= DECORATION_BORDER_TOT_X;
+      event->height -= DECORATION_BORDER_TOT_Y;
+    }
+
+  gtk_window_configure_event (widget, event);
+
+  return TRUE;
+}
+
+
+static gint
+gtk_decorated_window_expose (GtkWidget      *dummy_widget,
+			     GdkEventExpose *event,
+			     GtkWidget      *widget)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (GTK_WINDOW (widget)->priv->decorated)
+    gtk_decorated_window_paint (widget, &event->area);
+
+  return TRUE;
+}
+
+
+static void
+gtk_decorated_window_calculate_decorations (GtkWindow *window)
+
+{
+  GdkWMDecoration decorations;
+
+#ifdef GDK_WINDOWING_FB
+  if (_gdk_fb_window_get_decorations (GTK_WIDGET (window)->window,
+				      &decorations))
+    {
+      if ((decorations & GDK_DECOR_BORDER) &&
+	  (decorations & GDK_DECOR_TITLE))
+	window->priv->decorated = TRUE;
+      else
+	window->priv->decorated = FALSE;
+    }
+  else
+#endif
+    window->priv->decorated = (window->type != GTK_WINDOW_POPUP);
+}
+
+
+static void
+gtk_decorated_window_resize (GtkWindow *window,
+			     gint width, gint height)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  gint border_x = 0, border_y = 0;
+  gint offset_x = 0, offset_y = 0;
+
+  if (window->priv->decorated)
+    {
+      border_x = DECORATION_BORDER_TOT_X;
+      border_y = DECORATION_BORDER_TOT_Y;
+      offset_x = DECORATION_BORDER_LEFT;
+      offset_y = DECORATION_BORDER_TOP;
+    }
+
+  gdk_window_move_resize (widget->window,
+			  offset_x, offset_y,
+			  width, height);
+  gdk_window_resize (window->priv->outer_window,
+		     width + border_x, height + border_y);
+}
+
+static void
+gtk_decorated_window_move_resize (GtkWindow *window,
+				  gint x, gint y,
+				  gint width, gint height)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  gint border_x = 0, border_y = 0;
+  gint offset_x = 0, offset_y = 0;
+
+  if (window->priv->decorated)
+    {
+      border_x = DECORATION_BORDER_TOT_X;
+      border_y = DECORATION_BORDER_TOT_Y;
+      offset_x = DECORATION_BORDER_LEFT;
+      offset_y = DECORATION_BORDER_TOP;
+    }
+
+  gdk_window_move_resize (widget->window,
+			  offset_x, offset_y,
+			  width, height);
+  gdk_window_move_resize (window->priv->outer_window,
+			  x - offset_x, y - offset_y,
+			  width + border_x, height + border_y);
+}
+
+static void
+gtk_decorated_window_move (GtkWindow *window,
+		    gint x, gint y)
+{
+  gint offset_x = 0, offset_y = 0;
+
+  if (window->priv->decorated)
+    {
+      offset_x = DECORATION_BORDER_LEFT;
+      offset_y = DECORATION_BORDER_TOP;
+    }
+
+  gdk_window_move (window->priv->outer_window,
+		   x - offset_x, y - offset_y);
+}
+
+
+static gint
+gtk_decorated_window_motion_notify (GtkWidget       *dummy_widget,
+				    GdkEventMotion  *event,
+				    GtkWidget       *widget)
+{
+  GtkWindow *window;
+  GtkWindowPrivate *priv;
+  GdkModifierType mask;
+  GdkWindow *win;
+  gint x, y;
+  gint win_x, win_y, win_w, win_h;
+
+  window = GTK_WINDOW (widget);
+  priv = window->priv;
+
+  if (!priv->decorated)
+    return TRUE;
+
+  win = widget->window;
+  gdk_window_get_pointer (priv->outer_window, &x, &y, &mask);
+
+  gdk_window_get_position (priv->outer_window, &win_x, &win_y);
+  win_x += DECORATION_BORDER_LEFT;
+  win_y += DECORATION_BORDER_TOP;
+
+  gdk_window_get_geometry (win, NULL, NULL, &win_w, &win_h, NULL);
+
+  if (priv->moving)
+    {
+      int dx, dy;
+      dx = x - priv->last_x;
+      dy = y - priv->last_y;
+
+      gtk_window_reposition (window, win_x + dx, win_y + dy);
+    }
+
+  if (priv->resize != RESIZE_NONE)
+    {
+      int w, h;
+
+      w = win_w;
+      h = win_h;
+
+      switch(priv->resize) {
+      case RESIZE_BOTTOM_RIGHT:
+	w = x - DECORATION_BORDER_TOT_X;
+	h = y - DECORATION_BORDER_TOT_Y;
+	break;
+      case RESIZE_RIGHT:
+	w = x - DECORATION_BORDER_TOT_X;
+	break;
+      case RESIZE_BOTTOM:
+	h = y - DECORATION_BORDER_TOT_Y;
+	break;
+      case RESIZE_TOP_LEFT:
+      case RESIZE_TOP:
+      case RESIZE_TOP_RIGHT:
+      case RESIZE_BOTTOM_LEFT:
+      case RESIZE_LEFT:
+      default:
+	g_warning ("Resize mode %d not handled yet.\n", priv->resize);
+	break;
+      }
+
+      if ((w > 0) && (h > 0))
+	{
+	  GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, FALSE);
+
+	  if (info)
+	    {
+	      GdkWindowHints mask = info->last.flags;
+	      GdkGeometry *g = &info->last.geometry;
+
+	      if (mask & GDK_HINT_MIN_SIZE)
+		{
+		  w = MAX (w, g->min_width);
+		  h = MAX (h, g->min_height);
+		}
+
+	      if (mask & GDK_HINT_MAX_SIZE)
+		{
+		  w = MIN (w, g->max_width);
+		  h = MIN (h, g->max_height);
+		}
+	    }
+
+	  if ((w != win_w) || (h != win_h))
+	    {
+	      gdk_window_resize (priv->outer_window,
+				 w + DECORATION_BORDER_TOT_X,
+				 h + DECORATION_BORDER_TOT_Y);
+	    }
+	}
+    }
+
+  return TRUE;
+
+}
+
+static GtkWindowRegionType
+gtk_decorated_window_region_type (GtkWindow *window, gint x, gint y)
+{
+  GtkWindowPrivate *priv;
+  int i;
+
+  priv = window->priv;
+  for (i=0;i<priv->n_regions;i++)
+    {
+      if ((x > priv->regions[i].rect.x) &&
+	  (x - priv->regions[i].rect.x < priv->regions[i].rect.width) &&
+	  (y > priv->regions[i].rect.y) &&
+	  (y - priv->regions[i].rect.y < priv->regions[i].rect.height))
+	return priv->regions[i].type;
+    }
+  return -1;
+}
+
+static gint
+gtk_decorated_window_button_press (GtkWidget       *dummy_widget,
+				   GdkEventButton  *event,
+				   GtkWidget       *widget)
+{
+  GtkWindow *window;
+  GtkWindowRegionType type;
+  GtkWindowPrivate *priv;
+  gint x, y;
+
+  window = GTK_WINDOW (widget);
+  priv = window->priv;
+
+  if (!priv->decorated)
+    return TRUE;

+  if (event->window != priv->outer_window)
+    return TRUE;
+
+  x = event->x;
+  y = event->y;
+
+  type = gtk_decorated_window_region_type (window, x, y);
+
+  priv->last_x = x;
+  priv->last_y = y;
+
+  switch (type)
+    {
+    case GTK_WINDOW_REGION_TITLE:
+      if (event->state & GDK_BUTTON1_MASK)
+	priv->moving = TRUE;
+      break;
+    case GTK_WINDOW_REGION_CLOSE:
+      if (event->state & GDK_BUTTON1_MASK)
+	priv->closing = TRUE;
+      break;
+    case GTK_WINDOW_REGION_BR_RESIZE:
+      if (event->state & GDK_BUTTON1_MASK)
+	priv->resize = RESIZE_BOTTOM_RIGHT;
+      break;
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+static gint
+gtk_decorated_window_button_release (GtkWidget	  *dummy_widget,
+				     GdkEventButton *event,
+				     GtkWidget      *widget)
+{
+  GtkWindow *window;
+  GtkWindowRegionType type;
+  GtkWindowPrivate *priv;
+
+  window = GTK_WINDOW (widget);
+  priv = window->priv;
+
+  if (priv->closing)
+    {
+      type = gtk_decorated_window_region_type (window, event->x, event->y);
+      if (type == GTK_WINDOW_REGION_CLOSE)
+	{
+	  GdkEventAny event;
+
+	  event.type = GDK_DELETE;
+	  event.window = widget->window;
+	  event.send_event = TRUE;
+
+	    /* Synthesize delete_event on key press. */
+	  g_object_ref (G_OBJECT (event.window));
+
+	  gtk_main_do_event ((GdkEvent*)&event);
+
+	  g_object_unref (G_OBJECT (event.window));
+	}
+    }
+
+  priv->closing = FALSE;
+  priv->moving = FALSE;
+  priv->resize = RESIZE_NONE;
   return TRUE;
 }
+
+static void
+gtk_decorated_window_paint (GtkWidget    *widget,
+			    GdkRectangle *area)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = window->priv;
+
+  if (priv->decorated)
+    {
+      GdkWindow *outer_window;
+      gint width, height;
+
+
+      outer_window = priv->outer_window;
+      gdk_window_get_size (outer_window, &width, &height);
+
+      /* Top */
+      gtk_paint_flat_box (widget->style, outer_window, GTK_STATE_NORMAL,
+			  GTK_SHADOW_NONE, area, widget, "base",
+			  0, 0,
+			  width, DECORATION_BORDER_TOP);
+      /* Bottom */
+      gtk_paint_flat_box (widget->style, outer_window, GTK_STATE_NORMAL,
+			  GTK_SHADOW_NONE, area, widget, "base",
+			  0, height - DECORATION_BORDER_BOTTOM,
+			  width, DECORATION_BORDER_BOTTOM);
+      /* Left */
+      gtk_paint_flat_box (widget->style, outer_window, GTK_STATE_NORMAL,
+			  GTK_SHADOW_NONE, area, widget, "base",
+			  0, DECORATION_BORDER_TOP,
+			  DECORATION_BORDER_LEFT, height - DECORATION_BORDER_TOT_Y);
+      /* Right */
+      gtk_paint_flat_box (widget->style, outer_window, GTK_STATE_NORMAL,
+			  GTK_SHADOW_NONE, area, widget, "base",
+			  width - DECORATION_BORDER_RIGHT, DECORATION_BORDER_TOP,
+			  DECORATION_BORDER_RIGHT, height - DECORATION_BORDER_TOT_Y);
+
+      /* Border: */
+      gtk_paint_box (widget->style, outer_window, GTK_STATE_NORMAL,
+		     GTK_SHADOW_OUT, area, widget, "base",
+		     0, 0, width, height);
+
+      gtk_paint_box (widget->style, outer_window, GTK_STATE_NORMAL,
+		     GTK_SHADOW_IN, area, widget, "base",
+		     DECORATION_BORDER_LEFT - 2, DECORATION_BORDER_TOP - 2,
+		     width - (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT) + 3,
+		     height - (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM) + 3);
+
+      /* Close button: */
+
+      gtk_paint_box (widget->style, outer_window, GTK_STATE_NORMAL,
+		     GTK_SHADOW_OUT, area, widget, "base",
+		     width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE,
+		     DECORATION_BUTTON_Y_OFFSET,
+		     DECORATION_BUTTON_SIZE, DECORATION_BUTTON_SIZE);
+
+      /* Title */
+      if (priv->title_layout)
+	{
+	  if (area)
+	    gdk_gc_set_clip_rectangle (widget->style->fg_gc [widget->state], area);
+	  gdk_draw_layout (outer_window,
+			   widget->style->fg_gc [widget->state],
+			   DECORATION_BORDER_LEFT, 1,
+			   priv->title_layout);
+	  if (area)
+	    gdk_gc_set_clip_rectangle (widget->style->fg_gc [widget->state], NULL);
+	}
+    }
+}
+
+
+static void
+gtk_decorated_window_recalculate_regions (GtkWindow *window)
+{
+  gint n_regions;
+  gint width, height;
+  GtkWindowRegion *region;
+  GtkWindowPrivate *priv;
+
+  priv = window->priv;
+
+  n_regions = 0;
+
+  n_regions += 2; /* close, Title */
+  if (window->allow_shrink || window->allow_grow)
+    n_regions += 2;
+
+  if (priv->n_regions != n_regions)
+    {
+      g_free (priv->regions);
+      priv->regions = g_new (GtkWindowRegion, n_regions);
+      priv->n_regions = n_regions;
+    }
+
+  width = GTK_WIDGET (window)->allocation.width + DECORATION_BORDER_TOT_X;
+  height = GTK_WIDGET (window)->allocation.height + DECORATION_BORDER_TOT_Y;
+
+  region = priv->regions;
+
+  /* Close button */
+  region->rect.x = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
+  region->rect.y = 2;
+  region->rect.width = DECORATION_BUTTON_SIZE;
+  region->rect.height = DECORATION_BUTTON_SIZE;
+  region->type = GTK_WINDOW_REGION_CLOSE;
+  region++;
+
+  /* title bar */
+  region->rect.x = 0;
+  region->rect.y = 0;
+  region->rect.width = width;
+  region->rect.height = DECORATION_BORDER_TOP;
+  region->type = GTK_WINDOW_REGION_TITLE;
+  region++;
+
+  if (window->allow_shrink || window->allow_grow)
+    {
+      region->rect.x = width - (DECORATION_BORDER_RIGHT + 10);
+      region->rect.y = height - DECORATION_BORDER_BOTTOM;
+      region->rect.width = DECORATION_BORDER_RIGHT + 10;
+      region->rect.height = DECORATION_BORDER_BOTTOM;
+      region->type = GTK_WINDOW_REGION_BR_RESIZE;
+      region++;
+
+      region->rect.x = width - DECORATION_BORDER_RIGHT;
+      region->rect.y = height - (DECORATION_BORDER_BOTTOM + 10);
+      region->rect.width = DECORATION_BORDER_RIGHT;
+      region->rect.height = DECORATION_BORDER_BOTTOM + 10;
+      region->type = GTK_WINDOW_REGION_BR_RESIZE;
+      region++;
+    }
+}
+#endif
Index: gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.24
diff -u -p -r1.24 gtkwindow.h
--- gtkwindow.h	2000/10/20 23:14:40	1.24
+++ gtkwindow.h	2000/12/18 14:44:14
@@ -47,8 +47,9 @@ extern "C" {
 #define GTK_WINDOW_GET_CLASS(obj)       (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_WINDOW, GtkWindowClass))


-typedef struct _GtkWindow       GtkWindow;
-typedef struct _GtkWindowClass  GtkWindowClass;
+typedef struct _GtkWindow        GtkWindow;
+typedef struct _GtkWindowPrivate GtkWindowPrivate;
+typedef struct _GtkWindowClass   GtkWindowClass;

 struct _GtkWindow
 {
@@ -80,6 +81,8 @@ struct _GtkWindow
   guint use_uposition : 1;
   guint modal : 1;
   guint destroy_with_parent : 1;
+
+  GtkWindowPrivate *priv;
 };

 struct _GtkWindowClass





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