parse geometry



Hi,

Here's a patch to re-add set_location() and set_size() (still no word
on what the issues there are) and also add
gtk_window_parse_geometry().

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.1894
diff -u -u -r1.1894 ChangeLog
--- ChangeLog	2001/04/12 19:04:05	1.1894
+++ ChangeLog	2001/04/13 15:32:11
@@ -1,3 +1,9 @@
+2001-04-13  Havoc Pennington  <hp redhat com>
+
+	* gtk/gtkwindow.c, gtk/gtkwindow.h: restore
+	gtk_window_set_location, gtk_window_set_size, add 
+	gtk_window_parse_geometry
+
 Thu Apr 12 21:04:26 2001  Tim Janik  <timj gtk org>
 
 	* gtk/gtktreeview.c (_gtk_tree_view_column_start_drag): get
Index: tests/testgtk.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testgtk.c,v
retrieving revision 1.242
diff -u -u -r1.242 testgtk.c
--- tests/testgtk.c	2001/04/12 16:11:54	1.242
+++ tests/testgtk.c	2001/04/13 15:32:11
@@ -8252,8 +8252,7 @@
   gchar *msg;
   gint x, y;
 
-  x = widget->allocation.x;
-  y = widget->allocation.y;
+  gtk_window_get_location (GTK_WINDOW (widget), &x, &y);
   
   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
                          "location: %d, %d",
@@ -8329,6 +8328,23 @@
 }
 
 static void
+set_geometry_callback (GtkWidget *entry,
+                       gpointer   data)
+{
+  gchar *text;
+  GtkWindow *target;
+
+  target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
+  
+  text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+
+  if (!gtk_window_parse_geometry (target, text))
+    g_print ("Bad geometry string '%s'\n", text);
+
+  g_free (text);
+}
+
+static void
 allow_shrink_callback (GtkWidget *widget,
                        gpointer   data)
 {
@@ -8375,6 +8391,7 @@
   GtkWidget *button;
   GtkWidget *spin;
   GtkAdjustment *adj;
+  GtkWidget *entry;
   GtkWidget *om;
   GtkWidget *menu;
   gint i;
@@ -8420,36 +8437,43 @@
 
   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
 
+  entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
+
+  gtk_signal_connect (GTK_OBJECT (entry), "changed",
+                      GTK_SIGNAL_FUNC (set_geometry_callback),
+                      control_window);
+  
   button = gtk_button_new_with_label ("Queue resize");
-  gtk_signal_connect_object (GTK_WIDGET (button),
+  gtk_signal_connect_object (GTK_OBJECT (button),
                              "clicked",
                              GTK_SIGNAL_FUNC (gtk_widget_queue_resize),
                              GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
   
   button = gtk_button_new_with_label ("Set size");
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_size_callback),
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
   button = gtk_button_new_with_label ("Set default size");
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_default_size_callback),
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
   button = gtk_button_new_with_label ("Set usize");
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_usize_callback),
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
   button = gtk_button_new_with_label ("Set location");
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_location_callback),
                       GTK_OBJECT (control_window));
@@ -8457,7 +8481,7 @@
 
   button = gtk_check_button_new_with_label ("Allow shrink");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "toggled",
                       GTK_SIGNAL_FUNC (allow_shrink_callback),
                       GTK_OBJECT (control_window));
@@ -8465,7 +8489,7 @@
 
   button = gtk_check_button_new_with_label ("Allow grow");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "toggled",
                       GTK_SIGNAL_FUNC (allow_grow_callback),
                       GTK_OBJECT (control_window));
@@ -8473,12 +8497,26 @@
   
   button = gtk_check_button_new_with_label ("Auto shrink");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
-  gtk_signal_connect (GTK_WIDGET (button),
+  gtk_signal_connect (GTK_OBJECT (button),
                       "toggled",
                       GTK_SIGNAL_FUNC (auto_shrink_callback),
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
+  button = gtk_button_new_with_mnemonic ("_Show");
+  gtk_signal_connect_object (GTK_OBJECT (button),
+                             "clicked",
+                             GTK_SIGNAL_FUNC (gtk_widget_show),
+                             GTK_OBJECT (window));
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_mnemonic ("_Hide");
+  gtk_signal_connect_object (GTK_OBJECT (button),
+                             "clicked",
+                             GTK_SIGNAL_FUNC (gtk_widget_hide),
+                             GTK_OBJECT (window));
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  
   menu = gtk_menu_new ();
   
   i = 0;
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.115
diff -u -u -r1.115 gtkwindow.c
--- gtk/gtkwindow.c	2001/04/02 23:33:45	1.115
+++ gtk/gtkwindow.c	2001/04/13 15:32:12
@@ -163,6 +163,9 @@
 static void gtk_window_compute_hints      (GtkWindow         *window, 
 					   GdkGeometry       *new_geometry,
 					   guint             *new_flags);
+static void gtk_window_compute_size_hints (GtkWindow         *window, 
+                                           GdkGeometry       *new_geometry,
+                                           guint             *new_flags);
 static gint gtk_window_compute_reposition (GtkWindow         *window,
 					   gint               new_width,
 					   gint               new_height,
@@ -184,6 +187,9 @@
 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
 							    gboolean   create);
 
+static void gtk_window_get_unadjusted_size (GtkWindow *window,
+                                            gint      *width,
+                                            gint      *height);
 
 static GSList      *toplevel_list = NULL;
 static GHashTable  *mnemonic_hash_table = NULL;
@@ -1088,6 +1094,54 @@
 			      (GtkDestroyNotify) g_list_free : NULL);
 }
 
+static void
+adjust_position_for_gravity (GtkWindow *window,
+                             gint      *x,
+                             gint      *y)
+{
+  gint w, h;
+  
+  gtk_window_get_unadjusted_size (window, &w, &h);
+
+  if (x)
+    {
+      switch (window->gravity)
+        {
+        case GDK_GRAVITY_NORTH:
+        case GDK_GRAVITY_CENTER:
+        case GDK_GRAVITY_SOUTH:
+          *x -= w / 2;
+          break;
+        case GDK_GRAVITY_SOUTH_EAST:
+        case GDK_GRAVITY_EAST:
+        case GDK_GRAVITY_NORTH_EAST:
+          *x -= w;
+          break;
+        default:
+          break;
+        }
+    }
+
+  if (y)
+    {
+      switch (window->gravity)
+        {
+        case GDK_GRAVITY_WEST:
+        case GDK_GRAVITY_CENTER:
+        case GDK_GRAVITY_EAST:
+          *y -= h / 2;
+          break;
+        case GDK_GRAVITY_SOUTH_WEST:
+        case GDK_GRAVITY_SOUTH:
+        case GDK_GRAVITY_SOUTH_EAST:
+          *y -= h;
+          break;
+        default:
+          break;
+        }
+    }
+}
+
 void       
 _gtk_window_reposition (GtkWindow *window,
 			gint       x,
@@ -1112,6 +1166,8 @@
 					 info->last.flags);
 	}
 
+      adjust_position_for_gravity (window, &x, &y);
+      
       if (window->frame)
 	gdk_window_move (window->frame,	 x - window->frame_left, y - window->frame_top);
       else
@@ -2804,19 +2860,12 @@
                              new_width, new_height);
 }
 
-/* Compute the set of geometry hints and flags for a window
- * based on the application set geometry, and requisiition
- * of the window. gtk_widget_size_request() must have been
- * called first.
- */
 static void
-gtk_window_compute_hints (GtkWindow   *window,
-			  GdkGeometry *new_geometry,
-			  guint       *new_flags)
+gtk_window_compute_size_hints (GtkWindow   *window, 
+                               GdkGeometry *new_geometry,
+                               guint       *new_flags)
 {
   GtkWidget *widget;
-  GtkWidgetAuxInfo *aux_info;
-  gint ux, uy;
   gint extra_width = 0;
   gint extra_height = 0;
   GtkWindowGeometryInfo *geometry_info;
@@ -2838,27 +2887,18 @@
     {
       extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
       extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
-    }
-  
-  ux = 0;
-  uy = 0;
-  
-  aux_info = _gtk_widget_get_aux_info (widget, FALSE);
-  if (aux_info && aux_info->x_set && aux_info->y_set)
-    {
-      ux = aux_info->x;
-      uy = aux_info->y;
-      *new_flags |= GDK_HINT_POS;
     }
-  
+
+  /* a) if the program set a base size, use it unconditionally
+   * b) otherwise, set base size to extra_width extra_height
+   *
+   */
   if (*new_flags & GDK_HINT_BASE_SIZE)
     {
       new_geometry->base_width += extra_width;
       new_geometry->base_height += extra_height;
     }
-  else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
-	   (*new_flags & GDK_HINT_RESIZE_INC) &&
-	   ((extra_width != 0) || (extra_height != 0)))
+  else
     {
       *new_flags |= GDK_HINT_BASE_SIZE;
       
@@ -2905,7 +2945,31 @@
       new_geometry->max_width = requisition.width;
       new_geometry->max_height = requisition.height;
     }
+}
 
+/* Compute the set of geometry hints and flags for a window
+ * based on the application set geometry, and requisiition
+ * of the window. gtk_widget_size_request() must have been
+ * called first.
+ */
+static void
+gtk_window_compute_hints (GtkWindow   *window,
+			  GdkGeometry *new_geometry,
+			  guint       *new_flags)
+{
+  GtkWidget *widget;
+  GtkWidgetAuxInfo *aux_info;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  widget = GTK_WIDGET (window);
+
+  gtk_window_compute_size_hints (window, new_geometry, new_flags);
+  
+  aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+  if (aux_info && aux_info->x_set && aux_info->y_set)
+    *new_flags |= GDK_HINT_POS;
+  
   *new_flags |= GDK_HINT_WIN_GRAVITY;
   new_geometry->win_gravity = window->gravity;
 }
@@ -2955,7 +3019,7 @@
         {
           gint ox, oy;
 	  gdk_window_get_origin (parent_widget->window,
-				   &ox, &oy);
+                                 &ox, &oy);
                                  
           *x = ox + (parent_widget->allocation.width - new_width) / 2;
           *y = oy + (parent_widget->allocation.height - new_height) / 2;
@@ -2981,9 +3045,9 @@
       if (window->use_uposition)
 	{
 	  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
-
+          
 	  if (aux_info && aux_info->x_set && aux_info->y_set)
-	    {
+            {              
 	      *x = aux_info->x;
 	      *y = aux_info->y;
 	      needs_move = TRUE;
@@ -3005,8 +3069,10 @@
       aux_info->x = *x;
       aux_info->y = *y;
       window->use_uposition = FALSE;
-    }
 
+      adjust_position_for_gravity (window, x, y);
+    }
+  
   return needs_move;
 }
 
@@ -3417,6 +3483,302 @@
 }
 
 /**
+ * gtk_window_set_size:
+ * @window: a #GtkWindow
+ * @width: width, or -1 to use the default width
+ * @height: height, or -1 to use the default height
+ *
+ * Sets the size of @window, but only works for resizeable windows
+ * (see gtk_window_set_resizeable()). Setting the size emulates a user
+ * resize operation. Therefore, setting the size less than the minimum
+ * size for the window will simply make the window its minimum size,
+ * and the user will be able to change the size that's set.
+ *
+ * This call also sets the default size of the window, so replaces
+ * gtk_window_set_default_size().
+ *
+ * To set a minimum size, or to set the size of a non-resizeable window,
+ * use gtk_widget_set_usize() on the window. Though normally it makes
+ * more sense to instead call gtk_widget_set_usize() on a child widget inside
+ * the window, rather than the window itself.
+ *
+ * Under the X Window System, window managers are allowed to ignore GTK+'s
+ * request to change a window's size. So your program should not rely on
+ * getting a specific size. (And, as noted in gtk_window_get_size(),
+ * a program that crucially relies on a specific size will generally have
+ * race conditions and be buggy anyway - rather than assuming a
+ * call to gtk_window_set_size() has taken effect, you should react
+ * to configure_event signals on your #GtkWindow.)
+ *
+ * If you set a geometry widget for the window with
+ * gtk_window_set_geometry_hints(), the size applies to the geometry
+ * widget, not the window itself.
+ *
+ * If you've called the deprecated gtk_window_set_policy() function,
+ * gtk_window_set_size() may not behave as expected, due to interaction
+ * with window policies.
+ **/
+void
+gtk_window_set_size (GtkWindow *window,
+                     gint       width,
+                     gint       height)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (width != 0);
+  g_return_if_fail (height != 0);
+  
+  /* set_default_size() uses "0" to mean "unset", but we allow "-1"
+   * for that in this newer function
+   */
+  if (width < 0)
+    width = 0;
+  if (height < 0)
+    height = 0;
+
+  gtk_window_set_default_size (window, width, height);
+}
+
+static void
+gtk_window_get_unadjusted_size (GtkWindow *window,
+                                gint      *width,
+                                gint      *height)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  if (GTK_WIDGET_REALIZED (window))
+    {
+      gdk_window_get_size (GTK_WIDGET (window)->window,
+                           width, height);
+    }
+  else
+    {
+      GdkGeometry new_geometry;
+      GdkWindowHints new_flags;
+      gint w, h;
+      
+      gtk_widget_size_request (widget, NULL);  
+      gtk_window_compute_default_size (window, &w, &h);
+      
+      gtk_window_compute_size_hints (window, &new_geometry, &new_flags);
+      gtk_window_constrain_size (window,
+                                 &new_geometry, new_flags,
+                                 w, h,
+                                 &w, &h);
+
+      if (width)
+        *width = w;
+      if (height)
+        *height = h;
+    }
+}
+
+/**
+ * gtk_window_get_size:
+ * @window: a #GtkWindow
+ * @width: return location for current width, or %NULL
+ * @height: return location for current height, or %NULL
+ * 
+ * Obtains the current size of @window. If the window is not onscreen
+ * (i.e. has not been received its first configure_event after being
+ * shown with gtk_widget_show()), the size will be the size GTK+ will
+ * request for this window when it's shown.  The window manager may
+ * not choose to give the window exactly this requested size.
+ *
+ * In general, code which depends on window size should connect to the
+ * configure_event on the window so that it can respond to changes in
+ * size caused by the user or by the window manager, in addition to
+ * changes in size created by your program.
+ *
+ * If you set a geometry widget for the window with
+ * gtk_window_set_geometry_hints(), the size retrieved is the size of
+ * the geometry widget, not the window itself.
+ * 
+ **/
+void
+gtk_window_get_size (GtkWindow *window,
+                     gint      *width,
+                     gint      *height)
+{
+  GtkWindowGeometryInfo *info;
+  GtkWidget *widget = GTK_WIDGET (window);
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  gtk_window_get_unadjusted_size (window, width, height);
+  
+  info = gtk_window_get_geometry_info (window, TRUE);
+  if (info->widget)
+    {
+      gint extra_width = widget->requisition.width - info->widget->requisition.width;
+      gint extra_height = widget->requisition.height - info->widget->requisition.height;
+      
+      if (width)
+        *width -= extra_width;
+      if (height)
+        *height -= extra_height;
+    }
+}
+
+/**
+ * gtk_window_set_location:
+ * @window: a #GtkWindow
+ * @root_x: X position of gravity-determined reference point in root window coordinates
+ * @root_y: Y position of gravity-determined reference point in root window coordinates
+ *
+ * Requests a new position for a #GtkWindow. The position is given in
+ * root window coordinates, and is the position of the window's
+ * "reference point" as determined by the window gravity (see
+ * gtk_window_set_gravity()). By default, the reference point is the
+ * northwest (top left) corner of the window's titlebar.  So if you
+ * set the window position to (0,0), the window's titlebar will end up
+ * in the top left corner of the root window. Note that the root
+ * window does not always correspond to the user's desktop area, so
+ * you may want to call gdk_workspace_get_extents() or
+ * gdk_desktop_get_extents() to decide where to place a window.  The
+ * extents of the root window can be obtained using gdk_screen_width()
+ * and gdk_screen_height().
+ *
+ * -1 can be passed for @root_x or @root_y to leave that argument unmodified.
+ * 
+ **/
+void
+gtk_window_set_location (GtkWindow *window,
+                         gint       root_x,
+                         gint       root_y)
+{
+  GtkWidgetAuxInfo *aux_info;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (window), TRUE);
+
+  if (root_x >= 0)
+    {
+      aux_info->x_set = TRUE;
+      aux_info->x = root_x;
+    }
+
+  if (root_y >= 0)
+    {
+      aux_info->y_set = TRUE;
+      aux_info->y = root_y;
+    }
+
+  if (aux_info->x_set && aux_info->y_set)
+    _gtk_window_reposition (window, aux_info->x, aux_info->y);
+}
+
+/**
+ * gtk_window_get_location:
+ * @window: a #GtkWindow
+ * @root_x: return location for X coordinate of gravity-determined reference point
+ * @root_y: return location for Y coordinate of gravity-determined reference point
+ *
+ * Attempts to obtain the current position of the reference point, as
+ * set by gtk_window_set_position(). This computation is accurate when
+ * the reference point is a corner of the window itself (as with
+ * #GDK_GRAVITY_STATIC), but may not be accurate when the reference
+ * point is a position on the titlebar or window border, because the X
+ * Window System does not provide a reliable way of obtaining this
+ * information. GTK+ will do a "best guess" which may not be fully
+ * accurate with some window managers, but will probably be
+ * reasonable.
+ * 
+ **/
+void
+gtk_window_get_location (GtkWindow *window,
+                         gint      *root_x,
+                         gint      *root_y)
+{
+  GdkRectangle frame_extents;
+  GtkWidget *widget;
+  GtkWidgetAuxInfo *aux_info;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  widget = GTK_WIDGET (window);
+  
+  if (GTK_WIDGET_REALIZED (window))
+    {
+      if (window->gravity == GDK_GRAVITY_STATIC)
+        {
+          gdk_window_get_origin (widget->window, root_x, root_y);
+          return;
+        }
+      else
+        {
+          gint x, y;
+          
+          gdk_window_get_frame_extents (widget->window, &frame_extents);
+          
+          x = frame_extents.x;
+          y = frame_extents.y;
+
+          switch (window->gravity)
+            {
+            case GDK_GRAVITY_NORTH:
+            case GDK_GRAVITY_CENTER:
+            case GDK_GRAVITY_SOUTH:
+              x += frame_extents.width / 2;
+              break;
+            case GDK_GRAVITY_SOUTH_EAST:
+            case GDK_GRAVITY_EAST:
+            case GDK_GRAVITY_NORTH_EAST:
+              x += frame_extents.width;
+              break;
+            default:
+              break;
+            }
+
+          switch (window->gravity)
+            {
+            case GDK_GRAVITY_WEST:
+            case GDK_GRAVITY_CENTER:
+            case GDK_GRAVITY_EAST:
+              y += frame_extents.height / 2;
+              break;
+            case GDK_GRAVITY_SOUTH_WEST:
+            case GDK_GRAVITY_SOUTH:
+            case GDK_GRAVITY_SOUTH_EAST:
+              y += frame_extents.height;
+              break;
+            default:
+              break;
+            }
+
+          if (root_x)
+            *root_x = x;
+          if (root_y)
+            *root_y = y;
+        }
+    }
+  else
+    {
+      /* We really don't have a location yet, so we make up some stuff,
+       * using the uposition if it's been set.
+       */
+      if (root_x)
+        *root_x = 0;
+
+      if (root_y)
+        *root_y = 0;
+      
+      aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+      if (aux_info && aux_info->x_set && aux_info->y_set)
+        {
+          if (root_x)
+            *root_x = aux_info->x;
+          if (root_y)
+            *root_y = aux_info->y;
+        }
+
+      adjust_position_for_gravity (window, root_x, root_y);
+    }
+}
+
+/**
  * gtk_window_set_gravity:
  * @window: a #GtkWindow
  * @gravity: window gravity
@@ -3554,4 +3916,260 @@
                               button,
                               root_x, root_y,
                               timestamp);
+}
+
+/*
+  Derived from XParseGeometry() in XFree86  
+
+  Copyright 1985, 1986, 1987,1998  The Open Group
+
+  All Rights Reserved.
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+
+  Except as contained in this notice, the name of The Open Group shall
+  not be used in advertising or otherwise to promote the sale, use or
+  other dealings in this Software without prior written authorization
+  from The Open Group.
+*/
+
+
+/*
+ *    XParseGeometry parses strings of the form
+ *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
+ *   width, height, xoffset, and yoffset are unsigned integers.
+ *   Example:  "=80x24+300-49"
+ *   The equal sign is optional.
+ *   It returns a bitmask that indicates which of the four values
+ *   were actually found in the string.  For each value found,
+ *   the corresponding argument is updated;  for each value
+ *   not found, the corresponding argument is left unchanged. 
+ */
+
+/* The following code is from Xlib, and is minimally modified, so we
+ * can track any upstream changes if required.  Don't change this
+ * code. Or if you do, put in a huge comment marking which thing
+ * changed.
+ */
+
+static int
+read_int (gchar   *string,
+          gchar  **next)
+{
+  int result = 0;
+  int sign = 1;
+  
+  if (*string == '+')
+    string++;
+  else if (*string == '-')
+    {
+      string++;
+      sign = -1;
+    }
+
+  for (; (*string >= '0') && (*string <= '9'); string++)
+    {
+      result = (result * 10) + (*string - '0');
+    }
+
+  *next = string;
+
+  if (sign >= 0)
+    return (result);
+  else
+    return (-result);
+}
+
+/* 
+ * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
+ * value (x, y, width, height) was found in the parsed string.
+ */
+#define NoValue         0x0000
+#define XValue          0x0001
+#define YValue          0x0002
+#define WidthValue      0x0004
+#define HeightValue     0x0008
+#define AllValues       0x000F
+#define XNegative       0x0010
+#define YNegative       0x0020
+
+static int
+gtk_XParseGeometry (const char   *string,
+                    int          *x,
+                    int          *y,
+                    unsigned int *width,   
+                    unsigned int *height)  
+{
+  int mask = NoValue;
+  char *strind;
+  unsigned int tempWidth, tempHeight;
+  int tempX, tempY;
+  char *nextCharacter;
+
+  if ( (string == NULL) || (*string == '\0')) return(mask);
+  if (*string == '=')
+    string++;  /* ignore possible '=' at beg of geometry spec */
+
+  strind = (char *)string;
+  if (*strind != '+' && *strind != '-' && *strind != 'x') {
+    tempWidth = read_int(strind, &nextCharacter);
+    if (strind == nextCharacter) 
+      return (0);
+    strind = nextCharacter;
+    mask |= WidthValue;
+  }
+
+  if (*strind == 'x' || *strind == 'X') {	
+    strind++;
+    tempHeight = read_int(strind, &nextCharacter);
+    if (strind == nextCharacter)
+      return (0);
+    strind = nextCharacter;
+    mask |= HeightValue;
+  }
+
+  if ((*strind == '+') || (*strind == '-')) {
+    if (*strind == '-') {
+      strind++;
+      tempX = -read_int(strind, &nextCharacter);
+      if (strind == nextCharacter)
+        return (0);
+      strind = nextCharacter;
+      mask |= XNegative;
+
+    }
+    else
+      {	strind++;
+      tempX = read_int(strind, &nextCharacter);
+      if (strind == nextCharacter)
+        return(0);
+      strind = nextCharacter;
+      }
+    mask |= XValue;
+    if ((*strind == '+') || (*strind == '-')) {
+      if (*strind == '-') {
+        strind++;
+        tempY = -read_int(strind, &nextCharacter);
+        if (strind == nextCharacter)
+          return(0);
+        strind = nextCharacter;
+        mask |= YNegative;
+
+      }
+      else
+        {
+          strind++;
+          tempY = read_int(strind, &nextCharacter);
+          if (strind == nextCharacter)
+            return(0);
+          strind = nextCharacter;
+        }
+      mask |= YValue;
+    }
+  }
+	
+  /* If strind isn't at the end of the string the it's an invalid
+		geometry specification. */
+
+  if (*strind != '\0') return (0);
+
+  if (mask & XValue)
+    *x = tempX;
+  if (mask & YValue)
+    *y = tempY;
+  if (mask & WidthValue)
+    *width = tempWidth;
+  if (mask & HeightValue)
+    *height = tempHeight;
+  return (mask);
+}
+
+gboolean
+gtk_window_parse_geometry (GtkWindow   *window,
+                           const gchar *geometry)
+{
+  gint result, x, y;
+  guint uw, uh;
+  gint w, h;
+  GdkGravity grav;
+  GtkWidget *widget;
+  gint extra_width = 0;
+  gint extra_height = 0;
+  GtkWindowGeometryInfo *geometry_info;
+  GtkRequisition requisition;
+  
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (geometry != NULL, FALSE);
+  
+  result = gtk_XParseGeometry (geometry, &x, &y, &uw, &uh);
+  w = uw;
+  h = uh;
+  
+  widget = GTK_WIDGET (window);
+  
+  gtk_widget_get_child_requisition (widget, &requisition);
+  geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
+
+  g_return_val_if_fail (geometry_info != NULL, FALSE);
+
+  if (geometry_info->mask & GDK_HINT_RESIZE_INC)
+    {
+      w *= geometry_info->geometry.width_inc;
+      h *= geometry_info->geometry.height_inc;
+    }
+  
+  if (geometry_info->widget)
+    {
+      extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
+      extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
+    }
+
+  w -= extra_width;
+  h -= extra_height;
+
+  if ((result & WidthValue) && w > 0)
+    gtk_window_set_default_size (window, w, -1);
+  if ((result & HeightValue) && h > 0)
+    gtk_window_set_default_size (window, -1, h);
+
+  grav = GDK_GRAVITY_NORTH_WEST;
+
+  if ((result & XNegative) && (result & YNegative))
+    grav = GDK_GRAVITY_SOUTH_EAST;
+  else if (result & XNegative)
+    grav = GDK_GRAVITY_NORTH_EAST;
+  else if (result & YNegative)
+    grav = GDK_GRAVITY_SOUTH_WEST;
+
+  gtk_window_set_gravity (window, grav);
+  
+  if (grav == GDK_GRAVITY_SOUTH_WEST ||
+      grav == GDK_GRAVITY_SOUTH_EAST)
+    y = gdk_screen_height () + y;
+
+  if (grav == GDK_GRAVITY_SOUTH_EAST ||
+      grav == GDK_GRAVITY_NORTH_EAST)
+    x = gdk_screen_width () + x;
+
+  if (y < 0)
+    y = 0;
+
+  if (x < 0)
+    x = 0;
+  
+  if (result & XValue)
+    gtk_window_set_location (window, x, -1);
+  if (result & YValue)
+    gtk_window_set_location (window, -1, y);
+  
+  return result != 0;
 }
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.36
diff -u -u -r1.36 gtkwindow.h
--- gtk/gtkwindow.h	2001/04/01 07:32:41	1.36
+++ gtk/gtkwindow.h	2001/04/13 15:32:12
@@ -159,6 +159,23 @@
 						GdkGeometry         *geometry,
 						GdkWindowHints       geom_mask);
 
+void       gtk_window_set_size                 (GtkWindow           *window,
+                                                gint                 width,
+                                                gint                 height);
+void       gtk_window_get_size                 (GtkWindow           *window,
+                                                gint                *width,
+                                                gint                *height);
+
+void       gtk_window_set_location             (GtkWindow           *window,
+                                                gint                 root_x,
+                                                gint                 root_y);
+void       gtk_window_get_location             (GtkWindow           *window,
+                                                gint                *root_x,
+                                                gint                *root_y);
+gboolean   gtk_window_parse_geometry           (GtkWindow           *window,
+                                                const gchar         *geometry);
+
+
 /* gtk_window_set_has_frame () must be called before realizing the window_*/
 void       gtk_window_set_has_frame            (GtkWindow *window);
 void       gtk_window_set_frame_dimensions     (GtkWindow *window, 




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