window sizing patch



Hi,

This patch is a month or more old now - it needs to go in ASAP,
because it needs testing, and changes API.

So, I'm going to commit in a day or two unless it gets reviewed and
specific issues are brought up.

This closes two API bugs:
 http://bugzilla.gnome.org/show_bug.cgi?id=52574
 http://bugzilla.gnome.org/show_bug.cgi?id=53151

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2106
diff -u -p -u -b -r1.2106 ChangeLog
--- ChangeLog	2001/07/04 03:02:22	1.2106
+++ ChangeLog	2001/07/04 18:29:27
@@ -1,3 +1,56 @@
+2001-07-04  Havoc Pennington  <hp pobox com>
+
+	* gtk/gtkplug.c (gtk_plug_init): remove setting of auto_shrink;
+	some fixage is needed here, but nothing simple. Owen understands
+	it. ;-)
+
+        * gtk/gtkwindow.h, gtk/gtkwindow.c: Rework code and API for window
+	sizing and positioning.  Also, fix bug in compute_geometry_hints
+	(width/height confusion for setting min size). 
+	(gtk_window_move): new function
+	(gtk_window_resize): new function
+	(gtk_window_get_size): new function
+	(gtk_window_get_position): new function
+	(gtk_window_parse_geometry): new function
+	
+ 	* gtk/gtkwidget.c (gtk_widget_set_size_request): new function
+ 	(gtk_widget_get_size_request): new function
+ 	(gtk_widget_get_usize): delete, that was a short-lived function
+ 	;-)
+ 	(gtk_widget_set_usize): deprecate
+ 	(gtk_widget_set_uposition): deprecate, make it a trivial 
+	gtk_window_move() wrapper
+	(gtk_widget_class_init): remove x/y/width/height properties,
+	add width_request height_request
+	
+        * demos/*: update to avoid deprecated functions
+	
+	* gtk/gtklayout.c: add x/y child properties
+
+	* gtk/gtkfixed.c: add x/y child properties, and get rid of 
+	uses of "gint16"
+
+	* tests/testgtk.c (create_window_sizing): lots of tweaks to window
+	sizing test
+
+	* gdk/x11/gdkevents-x11.c (gdk_event_translate): Ensure that
+	configure events on toplevel windows are always in root window
+	coordinates, following ICCCM spec that all synthetic events 
+	are in root window coords already, while real events are 
+	in parent window coords. Previously the code assumed that 
+	coords of 0,0 were parent window coords, which was 
+	really broken.
+  
+ 	* gtk/gtkcontainer.c (gtk_container_get_focus_chain): fix
+ 	warning
+ 
+ 	* gdk/gdkwindow.h (GdkWindowHints): add GDK_HINT_USER_POS 
+ 	and GDK_HINT_USER_SIZE so we can set USSize and USPosition 
+ 	hints in gtk_window_parse_geometry()
+ 
+ 	* gdk/x11/gdkwindow-x11.c (gdk_window_set_geometry_hints): support
+ 	new USER_POS USER_SIZE hints 	
+ 
 2001-07-04  James Henstridge  <james daa com au>
 
 	* gtk/gtkliststore.h: add missing gtk_list_store_newv prototype.
Index: demos/pixbuf-demo.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/pixbuf-demo.c,v
retrieving revision 1.7
diff -u -p -u -b -r1.7 pixbuf-demo.c
--- demos/pixbuf-demo.c	2001/04/18 18:09:15	1.7
+++ demos/pixbuf-demo.c	2001/07/04 18:29:27
@@ -212,8 +212,8 @@ main (int argc, char **argv)
 	frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, back_width, back_height);
 
 	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-	gtk_widget_set_usize (window, back_width, back_height);
-	gtk_window_set_policy (GTK_WINDOW (window), FALSE, FALSE, FALSE);
+	gtk_widget_set_size_request (window, back_width, back_height);
+        gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
 
 	gtk_signal_connect (GTK_OBJECT (window), "destroy",
 			    GTK_SIGNAL_FUNC (destroy_cb), NULL);
Index: demos/testpixbuf-drawable.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/testpixbuf-drawable.c,v
retrieving revision 1.15
diff -u -p -u -b -r1.15 testpixbuf-drawable.c
--- demos/testpixbuf-drawable.c	2001/05/07 19:27:51	1.15
+++ demos/testpixbuf-drawable.c	2001/07/04 18:29:27
@@ -104,7 +104,7 @@ int main(int argc, char **argv)
    gtk_container_add(GTK_CONTAINER(window), vbox);  
    
    drawing_area = gtk_drawing_area_new();
-   gtk_widget_set_usize(GTK_WIDGET(drawing_area),
+   gtk_widget_set_size_request (GTK_WIDGET(drawing_area),
                         gdk_pixbuf_get_width (pixbuf),
                         gdk_pixbuf_get_height (pixbuf));
    gtk_signal_connect(GTK_OBJECT(drawing_area), "expose_event",
Index: demos/testpixbuf-save.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/testpixbuf-save.c,v
retrieving revision 1.4
diff -u -p -u -b -r1.4 testpixbuf-save.c
--- demos/testpixbuf-save.c	2001/05/07 19:27:51	1.4
+++ demos/testpixbuf-save.c	2001/07/04 18:29:27
@@ -142,7 +142,7 @@ main (int argc, char **argv)
         gtk_container_add (GTK_CONTAINER (window), vbox);  
    
         drawing_area = gtk_drawing_area_new ();
-        gtk_widget_set_usize (GTK_WIDGET (drawing_area),
+        gtk_widget_set_size_request (GTK_WIDGET (drawing_area),
                               gdk_pixbuf_get_width (pixbuf),
                               gdk_pixbuf_get_height (pixbuf));
         gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
Index: demos/testpixbuf.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/testpixbuf.c,v
retrieving revision 1.47
diff -u -p -u -b -r1.47 testpixbuf.c
--- demos/testpixbuf.c	2001/06/28 17:12:35	1.47
+++ demos/testpixbuf.c	2001/07/04 18:29:27
@@ -393,7 +393,7 @@ new_testrgb_window (GdkPixbuf *pixbuf, g
 	drawing_area = gtk_drawing_area_new ();
 
 	temp_box = gtk_hbox_new (FALSE, 0);
-	gtk_widget_set_usize (GTK_WIDGET(drawing_area), w, h);
+	gtk_widget_set_size_request (GTK_WIDGET(drawing_area), w, h);
 	gtk_box_pack_start (GTK_BOX (temp_box), drawing_area, FALSE, FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (vbox), temp_box, FALSE, FALSE, 0);
 	
Index: demos/gtk-demo/colorsel.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/colorsel.c,v
retrieving revision 1.2
diff -u -p -u -b -r1.2 colorsel.c
--- demos/gtk-demo/colorsel.c	2001/05/18 16:28:30	1.2
+++ demos/gtk-demo/colorsel.c	2001/07/04 18:29:27
@@ -78,7 +78,7 @@ do_colorsel (void)
       
       da = gtk_drawing_area_new ();
       /* set a minimum size */
-      gtk_widget_set_usize (da, 200, 200);
+      gtk_widget_set_size_request (da, 200, 200);
       /* set the color */
       gtk_widget_modify_bg (da, GTK_STATE_NORMAL, &color);
       
Index: demos/gtk-demo/item_factory.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/item_factory.c,v
retrieving revision 1.3
diff -u -p -u -b -r1.3 item_factory.c
--- demos/gtk-demo/item_factory.c	2001/05/18 16:28:30	1.3
+++ demos/gtk-demo/item_factory.c	2001/07/04 18:29:27
@@ -92,7 +92,7 @@ do_item_factory (void)
 			  FALSE, FALSE, 0);
 
       label = gtk_label_new ("Type\n<alt>\nto start");
-      gtk_widget_set_usize (label, 200, 200);
+      gtk_widget_set_size_request (label, 200, 200);
       gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
 
Index: demos/gtk-demo/main.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/main.c,v
retrieving revision 1.27
diff -u -p -u -b -r1.27 main.c
--- demos/gtk-demo/main.c	2001/06/30 02:38:16	1.27
+++ demos/gtk-demo/main.c	2001/07/04 18:29:27
@@ -686,7 +686,7 @@ create_tree (void)
 
   gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
 			       GTK_TREE_SELECTION_SINGLE);
-  gtk_widget_set_usize (tree_view, 200, -1);
+  gtk_widget_set_size_request (tree_view, 200, -1);
 
   for (i=0; i < G_N_ELEMENTS (testgtk_demos); i++)
     {
Index: demos/gtk-demo/panes.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/panes.c,v
retrieving revision 1.5
diff -u -p -u -b -r1.5 panes.c
--- demos/gtk-demo/panes.c	2001/05/18 16:28:30	1.5
+++ demos/gtk-demo/panes.c	2001/07/04 18:29:27
@@ -148,7 +148,7 @@ do_panes (void)
 
       frame = gtk_frame_new (NULL);
       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
-      gtk_widget_set_usize (frame, 60, 60);
+      gtk_widget_set_size_request (frame, 60, 60);
       gtk_paned_add1 (GTK_PANED (hpaned), frame);
       
       button = gtk_button_new_with_mnemonic ("_Hi there");
Index: demos/gtk-demo/pixbufs.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/pixbufs.c,v
retrieving revision 1.4
diff -u -p -u -b -r1.4 pixbufs.c
--- demos/gtk-demo/pixbufs.c	2001/06/25 23:48:47	1.4
+++ demos/gtk-demo/pixbufs.c	2001/07/04 18:29:27
@@ -246,7 +246,7 @@ do_pixbufs (void)
 	}
       else
 	{
-	  gtk_widget_set_usize (window, back_width, back_height);
+	  gtk_widget_set_size_request (window, back_width, back_height);
 
 	  frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, back_width, back_height);
 
Index: docs/Changes-2.0.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/Changes-2.0.txt,v
retrieving revision 1.24
diff -u -p -u -b -r1.24 Changes-2.0.txt
--- docs/Changes-2.0.txt	2001/06/30 16:08:18	1.24
+++ docs/Changes-2.0.txt	2001/07/04 18:29:27
@@ -396,3 +396,20 @@ Incompatible Changes from GTK+-1.2 to GT
   undefined contents for the offscreen areas. In most cases, code
   using gdk_image_get() should really be ported to
   gdk_pixbuf_get_from_drawable().
+
+* gtk_widget_set_usize() has been renamed to
+  gtk_widget_set_size_request(), however the old name still exists
+  unless you define GTK_DISABLE_DEPRECATED.
+
+* gtk_widget_set_uposition() is deprecated; use gtk_window_move(), 
+  gtk_fixed_put(), or gtk_layout_put() instead.
+
+* gtk_window_set_policy() is deprecated. To get the effect of
+  "allow_shrink", call gtk_widget_set_size_request(window, 0, 0).  To
+  get the effect of "allow_grow", call
+  gtk_window_set_resizable(window, TRUE). You didn't want the effect
+  of auto_shrink, it made no sense. But maybe if you were using it you
+  want to use gtk_window_resize (window, 1, 1) to snap a window back
+  to its minimum size (the 1, 1 will be rounded up to the minimum
+  window size).
+
Index: docs/sizing-test.txt
===================================================================
RCS file: sizing-test.txt
diff -N sizing-test.txt
--- /dev/null	Tue May  5 16:32:27 1998
+++ sizing-test.txt	Wed Jul  4 14:29:27 2001
@@ -0,0 +1,121 @@
+This is a list of things to check when testing window size/pos functions.
+===
+
+gtk_widget_set_size_request():
+ - causes the widget to request the given size
+ - for toplevel windows, changes the default-requested size if 
+   no default size is set and gtk_window_resize() has not been called
+ - passing -1 for either width or height reverts to "natural" request
+   in that dimension
+ - passing 0 is allowed, and results in requisition of 1x1 
+   (0x0 is a permitted requisition, but equivalent to 1x1, 
+   we use 1x1 for implementation convenience)
+ - causes notifies on width_request, height_request properties
+
+gtk_window_resize():
+ - causes a configure request in all cases if the window is mapped, 
+   unless the new size is the same as the old size
+ - overrides the default size on map if the window is unmapped
+ - allows size of 0, equivalent to 1
+ - clamped to geometry hints
+
+gtk_window_set_default_size():
+ - has no effect after the window has been mapped the first time, 
+   unless the window has been unrealized in which case it should 
+   have an effect
+ - allows size of 0, equivalent to 1
+ - allows size of -1 to unset the default size
+ - clamped to geometry hints
+ - gtk_window_resize() overrides it
+ - causes notifies on default_width, default_height properties
+
+gtk_window_get_default_size():
+ - returns the values last passed to set_default_size(), including 
+   -1. If set_default_size() has not been called, returns -1.
+
+gtk_window_move():
+ - always causes a configure request if the window is mapped, 
+   unless the last configure request we sent was for the same
+   position being moved to
+ - position may be negative to move windows offscreen
+ - if GTK_WIN_POS_CENTER_ALWAYS (or other future position 
+   constraints we may add) is in effect, the move
+   request is clamped to obey the constraints. thus
+   calling gtk_window_move() on a CENTER_ALWAYS window 
+   may trigger the window to bounce back to center if it 
+   wasn't there
+ - overrides all GTK_WIN_POS_ except CENTER_ALWAYS
+
+gtk_window_get_size():
+ - obtains the client-side known size of widget->window, 
+   as last received from a configure event
+ - prior to mapping, returns the default size we will request
+ - between realization and mapping, computes default size 
+   rather than looking at widget->window up-to-date size, 
+   so the size will be correct after force-realizing a window
+
+gtk_window_get_position():
+ - obtains the point to be passed to gtk_window_move() in order
+   to keep the window in its current position
+ - round-trips to the server to get the position; this is suboptimal
+   from both a race condition and speed standpoint but required to get
+   window frame size
+ - if the window is unmapped, returns the default position we will 
+   request
+
+gtk_window_set_position():
+ - not the inverse of get_position(), sadly
+ - modifies the default positioning of the window
+ - if set to CENTER_ALWAYS and the window is mapped, results in a
+   configure request moving the window to the center, unless the 
+   window was already centered
+ - ignored if gtk_window_move() called, with the exception 
+   of CENTER_ALWAYS
+
+gtk_window_parse_geometry():
+ - parses a standard X geometry string
+ - toggles on one or both of GDK_HINT_USER_SIZE, GDK_HINT_USER_POS
+ - "xprop" shows user size/position are set on the window
+ - calls gtk_window_set_default_size() to set the window size
+ - calls gtk_window_move() to set the window position
+ - calls gtk_window_set_gravity() to set the window gravity
+
+gtk_window_reshow_with_initial_size():
+ - for use by GUI builders; unrealizes and re-shows the window, 
+   using default size (and also position, but position 
+   is reset on any hide anyway)
+ - window should be positioned and sized as it was on initial map,
+   barring odd window managers
+
+gtk_window_set_geometry_hints():
+ - if a hint is set with this function, we do not override it
+   in other parts of the code
+
+General behavior
+===
+
+ - no infinite loops or nasty fighting-the-user flicker during 
+   operations such as moving/resizing a window
+
+Properties
+===
+
+GtkWindow::default_width, GtkWindow::default_height:
+ - default_width is -1 if unset, or >= 0 if 
+   a default width is set
+ - default_height is -1 if unset, or >= 0 if
+   a default height is set
+
+GtkWindow::allow_grow, GtkWindow::resizable:
+ - equivalent properties; changing one notifies on the other
+ - if FALSE, we set the min size to the max size in the geometry 
+   hints. 
+ - If the app programmer has called gtk_window_set_geometry_hints()
+   however and set min or max size, we don't replace the hint they
+   set.
+
+GtkWidget::width_request, GtkWidget::height_request:
+ - if -1, default requisition of widget is used
+ - otherwise, override default requisition
+
+
Index: docs/reference/gdk/tmpl/windows.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gdk/tmpl/windows.sgml,v
retrieving revision 1.13
diff -u -p -u -b -r1.13 windows.sgml
--- docs/reference/gdk/tmpl/windows.sgml	2001/04/17 18:12:45	1.13
+++ docs/reference/gdk/tmpl/windows.sgml	2001/07/04 18:29:28
@@ -87,6 +87,8 @@ Windows
 @GDK_HINT_ASPECT: 
 @GDK_HINT_RESIZE_INC: 
 @GDK_HINT_WIN_GRAVITY: 
+ GDK_HINT_USER_POS: 
+ GDK_HINT_USER_SIZE: 
 
 <!-- ##### STRUCT GdkGeometry ##### -->
 <para>
Index: docs/reference/gtk/tmpl/gtk-unused.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtk-unused.sgml,v
retrieving revision 1.52
diff -u -p -u -b -r1.52 gtk-unused.sgml
--- docs/reference/gtk/tmpl/gtk-unused.sgml	2001/07/02 05:03:18	1.52
+++ docs/reference/gtk/tmpl/gtk-unused.sgml	2001/07/04 18:29:28
@@ -896,6 +896,12 @@ Holds the data for a statusbar message. 
 @context_id: 
 @message_id: 
 
+<!-- ##### ARG GtkTextTag:font-desc ##### -->
+<para>
+Font as a #PangoFontDescription.
+</para>
+
+
 <!-- ##### ARG GtkTextTag:justify ##### -->
 <para>
 A #GtkJustification for the text. This is only used when the tag is
@@ -923,12 +929,25 @@ produce superscript and subscript.
 </para>
 
 
+<!-- ##### ARG GtkTextTag:tabs ##### -->
+<para>
+A #PangoTabArray indicating tabs for this text.  Only used if the tag
+applies to the first character in a paragraph.
+</para>
+
+
 <!-- ##### ARG GtkTextView:justify ##### -->
 <para>
 
 </para>
 
 
+<!-- ##### ARG GtkTextView:tabs ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### ARG GtkVScale:adjustment ##### -->
 <para>
 the #GtkAdjustment which sets the range of the scale.
@@ -979,6 +998,36 @@ the #GtkAdjustment which sets the range 
 </para>
 
 @widget: the object which received the signal.
+
+<!-- ##### ARG GtkWidget:height ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkWidget:width ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkWidget:x ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkWidget:y ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkWindow:auto-shrink ##### -->
+<para>
+If the window shrinks automatically when widgets within it shrink.
+</para>
+
 
 <!-- ##### FUNCTION gtk_arg_copy ##### -->
 <para>
Index: docs/reference/gtk/tmpl/gtkrc.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkrc.sgml,v
retrieving revision 1.39
diff -u -p -u -b -r1.39 gtkrc.sgml
--- docs/reference/gtk/tmpl/gtkrc.sgml	2001/07/02 05:03:19	1.39
+++ docs/reference/gtk/tmpl/gtkrc.sgml	2001/07/04 18:29:28
@@ -495,7 +495,6 @@ This can later be composited together wi
 #GtkRcStyle structures to form a #GtkStyle.
 </para>
 
- parent_instance: 
 @name: 
 @bg_pixmap_name: 
 @font_desc: 
Index: docs/reference/gtk/tmpl/gtktexttag.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtktexttag.sgml,v
retrieving revision 1.13
diff -u -p -u -b -r1.13 gtktexttag.sgml
--- docs/reference/gtk/tmpl/gtktexttag.sgml	2001/06/21 17:44:27	1.13
+++ docs/reference/gtk/tmpl/gtktexttag.sgml	2001/07/04 18:29:28
@@ -228,11 +228,6 @@ A #GdkBitmap to use as a stipple pattern
 Font as a Pango font name, e.g. "Sans Italic 12"
 </para>
 
-<!-- ##### ARG GtkTextTag:font-desc ##### -->
-<para>
-Font as a #PangoFontDescription.
-</para>
-
 <!-- ##### ARG GtkTextTag:family ##### -->
 <para>
 
@@ -352,12 +347,6 @@ used for the current character.
 The language this text is in, as an ISO code. Pango can use this as a
 hint when rendering the text. If you don't understand this argument, 
 you probably don't need it.
-</para>
-
-<!-- ##### ARG GtkTextTag:tabs ##### -->
-<para>
-A #PangoTabArray indicating tabs for this text.  Only used if the tag
-applies to the first character in a paragraph.
 </para>
 
 <!-- ##### ARG GtkTextTag:invisible ##### -->
Index: docs/reference/gtk/tmpl/gtktextview.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtktextview.sgml,v
retrieving revision 1.16
diff -u -p -u -b -r1.16 gtktextview.sgml
--- docs/reference/gtk/tmpl/gtktextview.sgml	2001/06/25 01:51:57	1.16
+++ docs/reference/gtk/tmpl/gtktextview.sgml	2001/07/04 18:29:28
@@ -675,11 +675,6 @@ types related to the text widget and how
 
 </para>
 
-<!-- ##### ARG GtkTextView:tabs ##### -->
-<para>
-
-</para>
-
 <!-- ##### ARG GtkTextView:cursor-visible ##### -->
 <para>
 
Index: docs/reference/gtk/tmpl/gtkwidget.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkwidget.sgml,v
retrieving revision 1.26
diff -u -p -u -b -r1.26 gtkwidget.sgml
--- docs/reference/gtk/tmpl/gtkwidget.sgml	2001/07/02 05:03:19	1.26
+++ docs/reference/gtk/tmpl/gtkwidget.sgml	2001/07/04 18:29:28
@@ -1874,22 +1874,12 @@ a widget changes from un-anchored to anc
 
 </para>
 
-<!-- ##### ARG GtkWidget:x ##### -->
+<!-- ##### ARG GtkWidget:width-request ##### -->
 <para>
 
 </para>
 
-<!-- ##### ARG GtkWidget:y ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG GtkWidget:width ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG GtkWidget:height ##### -->
+<!-- ##### ARG GtkWidget:height-request ##### -->
 <para>
 
 </para>
Index: docs/reference/gtk/tmpl/gtkwindow.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkwindow.sgml,v
retrieving revision 1.19
diff -u -p -u -b -r1.19 gtkwindow.sgml
--- docs/reference/gtk/tmpl/gtkwindow.sgml	2001/06/28 05:23:59	1.19
+++ docs/reference/gtk/tmpl/gtkwindow.sgml	2001/07/04 18:29:28
@@ -509,11 +509,6 @@ The type of the window.
 The title of the window.
 </para>
 
-<!-- ##### ARG GtkWindow:auto-shrink ##### -->
-<para>
-If the window shrinks automatically when widgets within it shrink.
-</para>
-
 <!-- ##### ARG GtkWindow:allow-shrink ##### -->
 <para>
 If the window can be resized to a smaller size by the user.
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.25
diff -u -p -u -b -r1.25 gdkwindow.h
--- gdk/gdkwindow.h	2001/06/28 05:24:00	1.25
+++ gdk/gdkwindow.h	2001/07/04 18:29:29
@@ -81,7 +81,9 @@ typedef enum
   GDK_HINT_BASE_SIZE   = 1 << 3,
   GDK_HINT_ASPECT      = 1 << 4,
   GDK_HINT_RESIZE_INC  = 1 << 5,
-  GDK_HINT_WIN_GRAVITY = 1 << 6
+  GDK_HINT_WIN_GRAVITY = 1 << 6,
+  GDK_HINT_USER_POS    = 1 << 7,
+  GDK_HINT_USER_SIZE   = 1 << 8
 } GdkWindowHints;
 
 
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.56
diff -u -p -u -b -r1.56 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	2001/06/30 16:08:23	1.56
+++ gdk/x11/gdkevents-x11.c	2001/07/04 18:29:29
@@ -1299,7 +1299,9 @@ gdk_event_translate (GdkEvent *event,
 	  (window_private->extension_events != 0))
 	_gdk_input_configure_event (&xevent->xconfigure, window);
 
-      if (!window || GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+      if (!window ||
+          GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
+          GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
 	return_val = FALSE;
       else
 	{
@@ -1308,8 +1310,7 @@ gdk_event_translate (GdkEvent *event,
 	  event->configure.width = xevent->xconfigure.width;
 	  event->configure.height = xevent->xconfigure.height;
 	  
-	  if (!xevent->xconfigure.x &&
-	      !xevent->xconfigure.y &&
+	  if (!xevent->xconfigure.send_event && 
 	      !GDK_WINDOW_DESTROYED (window))
 	    {
 	      gint tx = 0;
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.119
diff -u -p -u -b -r1.119 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	2001/07/03 01:39:36	1.119
+++ gdk/x11/gdkwindow-x11.c	2001/07/04 18:29:29
@@ -1348,6 +1348,16 @@ gdk_window_set_geometry_hints (GdkWindow
       size_hints.x = 0;
       size_hints.y = 0;
     }
+
+  if (geom_mask & GDK_HINT_USER_POS)
+    {
+      size_hints.flags |= USPosition;
+    }
+
+  if (geom_mask & GDK_HINT_USER_SIZE)
+    {
+      size_hints.flags |= USSize;
+    }
   
   if (geom_mask & GDK_HINT_MIN_SIZE)
     {
Index: gtk/gtkcontainer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.c,v
retrieving revision 1.81
diff -u -p -u -b -r1.81 gtkcontainer.c
--- gtk/gtkcontainer.c	2001/07/01 00:57:20	1.81
+++ gtk/gtkcontainer.c	2001/07/04 18:29:30
@@ -2126,7 +2126,7 @@ gboolean
 gtk_container_get_focus_chain (GtkContainer *container,
 			       GList       **focus_chain)
 {
-  g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
+  g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
 
   if (focus_chain)
     {
Index: gtk/gtkfixed.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfixed.c,v
retrieving revision 1.25
diff -u -p -u -b -r1.25 gtkfixed.c
--- gtk/gtkfixed.c	2001/03/18 04:50:33	1.25
+++ gtk/gtkfixed.c	2001/07/04 18:29:30
@@ -25,7 +25,13 @@
  */
 
 #include "gtkfixed.h"
+#include "gtkintl.h"
 
+enum {
+  CHILD_PROP_0,
+  CHILD_PROP_X,
+  CHILD_PROP_Y
+};
 
 static void gtk_fixed_class_init    (GtkFixedClass    *klass);
 static void gtk_fixed_init          (GtkFixed         *fixed);
@@ -45,6 +51,16 @@ static void gtk_fixed_forall        (Gtk
 				     gpointer          callback_data);
 static GtkType gtk_fixed_child_type (GtkContainer     *container);
 
+static void gtk_fixed_set_child_property (GtkContainer *container,
+                                          GtkWidget    *child,
+                                          guint         property_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec);
+static void gtk_fixed_get_child_property (GtkContainer *container,
+                                          GtkWidget    *child,
+                                          guint         property_id,
+                                          GValue       *value,
+                                          GParamSpec   *pspec);
 
 static GtkContainerClass *parent_class = NULL;
 
@@ -96,6 +112,29 @@ gtk_fixed_class_init (GtkFixedClass *cla
   container_class->remove = gtk_fixed_remove;
   container_class->forall = gtk_fixed_forall;
   container_class->child_type = gtk_fixed_child_type;
+
+  container_class->set_child_property = gtk_fixed_set_child_property;
+  container_class->get_child_property = gtk_fixed_get_child_property;
+
+  gtk_container_class_install_child_property (container_class,
+					      CHILD_PROP_X,
+					      g_param_spec_int ("x",
+                                                                _("X position"),
+                                                                _("X position of child widget"),
+                                                                G_MININT,
+                                                                G_MAXINT,
+                                                                0,
+                                                                G_PARAM_READWRITE));
+
+  gtk_container_class_install_child_property (container_class,
+					      CHILD_PROP_Y,
+					      g_param_spec_int ("y",
+                                                                _("Y position"),
+                                                                _("Y position of child widget"),
+                                                                G_MININT,
+                                                                G_MAXINT,
+                                                                0,
+                                                                G_PARAM_READWRITE));
 }
 
 static GtkType
@@ -121,11 +160,32 @@ gtk_fixed_new (void)
   return GTK_WIDGET (fixed);
 }
 
+static GtkFixedChild*
+get_child (GtkFixed  *fixed,
+           GtkWidget *widget)
+{
+  GList *children;
+  
+  children = fixed->children;
+  while (children)
+    {
+      GtkFixedChild *child;
+      
+      child = children->data;
+      children = children->next;
+
+      if (child->widget == widget)
+        return child;
+    }
+
+  return NULL;
+}
+
 void
 gtk_fixed_put (GtkFixed       *fixed,
                GtkWidget      *widget,
-               gint16         x,
-               gint16         y)
+               gint            x,
+               gint            y)
 {
   GtkFixedChild *child_info;
 
@@ -154,35 +214,106 @@ gtk_fixed_put (GtkFixed       *fixed,
     }
 }
 
-void
-gtk_fixed_move (GtkFixed       *fixed,
+static void
+gtk_fixed_move_internal (GtkFixed       *fixed,
                 GtkWidget      *widget,
-                gint16         x,
-                gint16         y)
+                         gboolean        change_x,
+                         gint            x,
+                         gboolean        change_y,
+                         gint            y)
 {
   GtkFixedChild *child;
-  GList *children;
 
-  g_return_if_fail (fixed != NULL);
   g_return_if_fail (GTK_IS_FIXED (fixed));
-  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (widget->parent == GTK_WIDGET (fixed));  
 
-  children = fixed->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
+  child = get_child (fixed, widget);
 
-      if (child->widget == widget)
+  g_assert (child);
+
+  gtk_widget_freeze_child_notify (widget);
+  
+  if (change_x)
         {
           child->x = x;
+      gtk_widget_child_notify (widget, "x");
+    }
+
+  if (change_y)
+    {
           child->y = y;
+      gtk_widget_child_notify (widget, "y");
+    }
+
+  gtk_widget_thaw_child_notify (widget);
 
           if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
             gtk_widget_queue_resize (GTK_WIDGET (fixed));
+}
+
+void
+gtk_fixed_move (GtkFixed       *fixed,
+                GtkWidget      *widget,
+                gint            x,
+                gint            y)
+{
+  g_return_if_fail (GTK_IS_FIXED (fixed));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (widget->parent == GTK_WIDGET (fixed));
+
+  gtk_fixed_move_internal (fixed, widget, TRUE, x, TRUE, y);
+}
 
+static void
+gtk_fixed_set_child_property (GtkContainer    *container,
+                              GtkWidget       *child,
+                              guint            property_id,
+                              const GValue    *value,
+                              GParamSpec      *pspec)
+{
+  switch (property_id)
+    {
+    case CHILD_PROP_X:
+      gtk_fixed_move_internal (GTK_FIXED (container),
+                               child,
+                               TRUE, g_value_get_int (value),
+                               FALSE, 0);
+      break;
+    case CHILD_PROP_Y:
+      gtk_fixed_move_internal (GTK_FIXED (container),
+                               child,
+                               FALSE, 0,
+                               TRUE, g_value_get_int (value));
           break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+      break;
         }
+}
+
+static void
+gtk_fixed_get_child_property (GtkContainer *container,
+                              GtkWidget    *child,
+                              guint         property_id,
+                              GValue       *value,
+                              GParamSpec   *pspec)
+{
+  GtkFixedChild *fixed_child;
+
+  fixed_child = get_child (GTK_FIXED (container), child);
+  
+  switch (property_id)
+    {
+    case CHILD_PROP_X:
+      g_value_set_int (value, fixed_child->x);
+      break;
+    case CHILD_PROP_Y:
+      g_value_set_int (value, fixed_child->y);
+      break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+      break;
     }
 }
 
Index: gtk/gtkfixed.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfixed.h,v
retrieving revision 1.9
diff -u -p -u -b -r1.9 gtkfixed.h
--- gtk/gtkfixed.h	2000/08/30 00:33:37	1.9
+++ gtk/gtkfixed.h	2001/07/04 18:29:30
@@ -64,8 +64,8 @@ struct _GtkFixedClass
 struct _GtkFixedChild
 {
   GtkWidget *widget;
-  gint16 x;
-  gint16 y;
+  gint x;
+  gint y;
 };
 
 
@@ -73,12 +73,12 @@ GtkType    gtk_fixed_get_type          (
 GtkWidget* gtk_fixed_new               (void);
 void       gtk_fixed_put               (GtkFixed       *fixed,
                                         GtkWidget      *widget,
-                                        gint16         x,
-                                        gint16         y);
+                                        gint            x,
+                                        gint            y);
 void       gtk_fixed_move              (GtkFixed       *fixed,
                                         GtkWidget      *widget,
-                                        gint16         x,
-                                        gint16         y);
+                                        gint            x,
+                                        gint            y);
 
 #ifdef __cplusplus
 }
Index: gtk/gtklayout.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklayout.c,v
retrieving revision 1.39
diff -u -p -u -b -r1.39 gtklayout.c
--- gtk/gtklayout.c	2001/06/24 15:34:47	1.39
+++ gtk/gtklayout.c	2001/07/04 18:29:30
@@ -51,6 +51,12 @@ enum {
    PROP_HEIGHT
 };
 
+enum {
+  CHILD_PROP_0,
+  CHILD_PROP_X,
+  CHILD_PROP_Y
+};
+
 static void     gtk_layout_class_init         (GtkLayoutClass *class);
 static void     gtk_layout_get_property       (GObject        *object,
 					       guint          prop_id,
@@ -61,7 +67,6 @@ static void     gtk_layout_set_property 
 					       const GValue   *value,
 					       GParamSpec     *pspec);
 static void     gtk_layout_init               (GtkLayout      *layout);
-
 static void     gtk_layout_finalize           (GObject        *object);
 static void     gtk_layout_realize            (GtkWidget      *widget);
 static void     gtk_layout_unrealize          (GtkWidget      *widget);
@@ -72,7 +77,6 @@ static void     gtk_layout_size_allocate
 					       GtkAllocation  *allocation);
 static gint     gtk_layout_expose             (GtkWidget      *widget, 
 					       GdkEventExpose *event);
-
 static void     gtk_layout_remove             (GtkContainer *container, 
 					       GtkWidget    *widget);
 static void     gtk_layout_forall             (GtkContainer *container,
@@ -82,14 +86,22 @@ static void     gtk_layout_forall       
 static void     gtk_layout_set_adjustments    (GtkLayout     *layout,
 					       GtkAdjustment *hadj,
 					       GtkAdjustment *vadj);
-
+static void gtk_layout_set_child_property (GtkContainer   *container,
+                                           GtkWidget      *child,
+                                           guint           property_id,
+                                           const GValue   *value,
+                                           GParamSpec     *pspec);
+static void gtk_layout_get_child_property (GtkContainer   *container,
+                                           GtkWidget      *child,
+                                           guint           property_id,
+                                           GValue         *value,
+                                           GParamSpec     *pspec);
 static void     gtk_layout_allocate_child     (GtkLayout      *layout,
 					       GtkLayoutChild *child);
-
-
 static void     gtk_layout_adjustment_changed (GtkAdjustment  *adjustment,
 					       GtkLayout      *layout);
 
+
 static GtkWidgetClass *parent_class = NULL;
 
 /* Public interface
@@ -218,6 +230,26 @@ gtk_layout_set_vadjustment (GtkLayout   
   g_object_notify (G_OBJECT (layout), "vadjustment");
 }
 
+static GtkLayoutChild*
+get_child (GtkLayout  *layout,
+           GtkWidget  *widget)
+{
+  GList *children;
+  
+  children = layout->children;
+  while (children)
+    {
+      GtkLayoutChild *child;
+      
+      child = children->data;
+      children = children->next;
+
+      if (child->widget == widget)
+        return child;
+    }
+
+  return NULL;
+}
 
 void           
 gtk_layout_put (GtkLayout     *layout, 
@@ -256,35 +288,55 @@ gtk_layout_put (GtkLayout     *layout, 
     }
 }
 
-void           
-gtk_layout_move (GtkLayout     *layout, 
-		 GtkWidget     *child_widget, 
+static void
+gtk_layout_move_internal (GtkLayout       *layout,
+                          GtkWidget       *widget,
+                          gboolean         change_x,
 		 gint           x, 
+                          gboolean         change_y,
 		 gint           y)
 {
-  GList *tmp_list;
   GtkLayoutChild *child;
   
-  g_return_if_fail (layout != NULL);
   g_return_if_fail (GTK_IS_LAYOUT (layout));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (widget->parent == GTK_WIDGET (layout));  
 
-  tmp_list = layout->children;
-  while (tmp_list)
-    {
-      child = tmp_list->data;
-      tmp_list = tmp_list->next;
+  child = get_child (layout, widget);
+
+  g_assert (child);
+
+  gtk_widget_freeze_child_notify (widget);
 
-      if (child->widget == child_widget)
+  if (change_x)
 	{
 	  child->x = x;
+      gtk_widget_child_notify (widget, "x");
+    }
+
+  if (change_y)
+    {
 	  child->y = y;
+      gtk_widget_child_notify (widget, "y");
+    }
 
-	  if (GTK_WIDGET_VISIBLE (child_widget) && GTK_WIDGET_VISIBLE (layout))
-	    gtk_widget_queue_resize (child_widget);
+  gtk_widget_thaw_child_notify (widget);
 
-	  return;
-	}
-    }
+  if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (layout))
+    gtk_widget_queue_resize (GTK_WIDGET (layout));
+}
+
+void           
+gtk_layout_move (GtkLayout     *layout, 
+		 GtkWidget     *child_widget, 
+		 gint           x, 
+		 gint           y)
+{
+  g_return_if_fail (GTK_IS_LAYOUT (layout));
+  g_return_if_fail (GTK_IS_WIDGET (child_widget));
+  g_return_if_fail (child_widget->parent == GTK_WIDGET (layout));  
+
+  gtk_layout_move_internal (layout, child_widget, TRUE, x, TRUE, y);
 }
 
 static void
@@ -434,6 +486,29 @@ gtk_layout_class_init (GtkLayoutClass *c
   gobject_class->get_property = gtk_layout_get_property;
   gobject_class->finalize = gtk_layout_finalize;
 
+  container_class->set_child_property = gtk_layout_set_child_property;
+  container_class->get_child_property = gtk_layout_get_child_property;
+
+  gtk_container_class_install_child_property (container_class,
+					      CHILD_PROP_X,
+					      g_param_spec_int ("x",
+                                                                _("X position"),
+                                                                _("X position of child widget"),
+                                                                G_MININT,
+                                                                G_MAXINT,
+                                                                0,
+                                                                G_PARAM_READWRITE));
+
+  gtk_container_class_install_child_property (container_class,
+					      CHILD_PROP_Y,
+					      g_param_spec_int ("y",
+                                                                _("Y position"),
+                                                                _("Y position of child widget"),
+                                                                G_MININT,
+                                                                G_MAXINT,
+                                                                0,
+                                                                G_PARAM_READWRITE));
+  
   g_object_class_install_property (gobject_class,
 				   PROP_HADJUSTMENT,
 				   g_param_spec_object ("hadjustment",
@@ -549,6 +624,57 @@ gtk_layout_set_property (GObject      *o
     }
 }
 
+static void
+gtk_layout_set_child_property (GtkContainer    *container,
+                               GtkWidget       *child,
+                               guint            property_id,
+                               const GValue    *value,
+                               GParamSpec      *pspec)
+{
+  switch (property_id)
+    {
+    case CHILD_PROP_X:
+      gtk_layout_move_internal (GTK_LAYOUT (container),
+                                child,
+                                TRUE, g_value_get_int (value),
+                                FALSE, 0);
+      break;
+    case CHILD_PROP_Y:
+      gtk_layout_move_internal (GTK_LAYOUT (container),
+                                child,
+                                FALSE, 0,
+                                TRUE, g_value_get_int (value));
+      break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_layout_get_child_property (GtkContainer *container,
+                               GtkWidget    *child,
+                               guint         property_id,
+                               GValue       *value,
+                               GParamSpec   *pspec)
+{
+  GtkLayoutChild *layout_child;
+
+  layout_child = get_child (GTK_LAYOUT (container), child);
+  
+  switch (property_id)
+    {
+    case CHILD_PROP_X:
+      g_value_set_int (value, layout_child->x);
+      break;
+    case CHILD_PROP_Y:
+      g_value_set_int (value, layout_child->y);
+      break;
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+      break;
+    }
+}
 
 static void
 gtk_layout_init (GtkLayout *layout)
Index: gtk/gtkplug.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkplug.c,v
retrieving revision 1.27
diff -u -p -u -b -r1.27 gtkplug.c
--- gtk/gtkplug.c	2001/07/03 14:14:28	1.27
+++ gtk/gtkplug.c	2001/07/04 18:29:30
@@ -139,7 +139,6 @@ gtk_plug_init (GtkPlug *plug)
   window = GTK_WINDOW (plug);
 
   window->type = GTK_WINDOW_TOPLEVEL;
-  window->auto_shrink = TRUE;
 }
 
 static void
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.235
diff -u -p -u -b -r1.235 gtkwidget.c
--- gtk/gtkwidget.c	2001/07/03 14:14:28	1.235
+++ gtk/gtkwidget.c	2001/07/04 18:29:31
@@ -121,10 +121,8 @@ enum {
   PROP_0,
   PROP_NAME,
   PROP_PARENT,
-  PROP_X,
-  PROP_Y,
-  PROP_WIDTH,
-  PROP_HEIGHT,
+  PROP_WIDTH_REQUEST,
+  PROP_HEIGHT_REQUEST,
   PROP_VISIBLE,
   PROP_SENSITIVE,
   PROP_APP_PAINTABLE,
@@ -215,7 +213,6 @@ static void		gtk_widget_propagate_hierar
 static gboolean		gtk_widget_real_mnemonic_activate	(GtkWidget	  *widget,
 								 gboolean	   group_cycling);
 static void		gtk_widget_aux_info_destroy		(GtkWidgetAuxInfo *aux_info);
-static void		gtk_widget_do_uposition			(GtkWidget	  *widget);
 static AtkObject*	gtk_widget_real_get_accessible		(GtkWidget	  *widget);
 static void		gtk_widget_accessible_interface_init	(AtkImplementorIface *iface);
 static AtkObject*	gtk_widget_ref_accessible		(AtkImplementor *implementor);
@@ -402,38 +399,21 @@ gtk_widget_class_init (GtkWidgetClass *k
 							_("The parent widget of this widget. Must be a Container widget."),
 							GTK_TYPE_CONTAINER,
 							G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-				   PROP_X,
-				   g_param_spec_int ("x",
- 						     _("x coordinate"),
- 						     _("The x coordinate of the top-left corner of the widget, or -1 if not set"),
- 						     -G_MAXINT,
- 						     G_MAXINT,
- 						     -1,
- 						     G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-				   PROP_Y,
-				   g_param_spec_int ("y",
- 						     _("y coordinate"),
- 						     _("The y coordinate of the top-left corner of the widget, or -1 if not set"),
- 						     -G_MAXINT,
- 						     G_MAXINT,
- 						     -1,
- 						     G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class,
-				   PROP_WIDTH,
-				   g_param_spec_int ("width",
- 						     _("Width"),
- 						     _("The width of the widget, or -1 if unset."),
+				   PROP_WIDTH_REQUEST,
+				   g_param_spec_int ("width_request",
+ 						     _("Width request"),
+ 						     _("Override for width request of the widget, or -1 if natural request should be used."),
  						     -1,
  						     G_MAXINT,
  						     -1,
  						     G_PARAM_READWRITE));
   g_object_class_install_property (gobject_class,
-				   PROP_HEIGHT,
-				   g_param_spec_int ("height",
- 						     _("Height"),
- 						     _("The height of the widget, or -1 if unset."),
+				   PROP_HEIGHT_REQUEST,
+				   g_param_spec_int ("height_request",
+ 						     _("Height request"),
+ 						     _("Override for height request of the widget, or -1 if natural request should be used."),
  						     -1,
  						     G_MAXINT,
  						     -1,
@@ -1076,7 +1056,6 @@ gtk_widget_set_property (GObject        
 			 GParamSpec      *pspec)
 {
   GtkWidget *widget;
-  GtkWidgetAuxInfo *aux_info;
 
   widget = GTK_WIDGET (object);
 
@@ -1090,32 +1069,10 @@ gtk_widget_set_property (GObject        
     case PROP_PARENT:
       gtk_container_add (GTK_CONTAINER (g_value_get_object (value)), widget);
       break;
-    case PROP_X:
-      aux_info = _gtk_widget_get_aux_info (widget, TRUE);
-      if (g_value_get_int (value) == -1)
-	aux_info->x_set = FALSE;
-      else
-	{
-	  aux_info->x_set = TRUE;
-	  aux_info->x = g_value_get_int (value);
-	}
-      gtk_widget_do_uposition (widget);
-      break;
-    case PROP_Y:
-      aux_info = _gtk_widget_get_aux_info (widget, TRUE);
-      if (g_value_get_int (value) == -1)
-	aux_info->y_set = FALSE;
-      else
-	{
-	  aux_info->y_set = TRUE;
-	  aux_info->y = g_value_get_int (value);
-	}
-      gtk_widget_do_uposition (widget);
-      break;
-    case PROP_WIDTH:
+    case PROP_WIDTH_REQUEST:
       gtk_widget_set_usize (widget, g_value_get_int (value), -2);
       break;
-    case PROP_HEIGHT:
+    case PROP_HEIGHT_REQUEST:
       gtk_widget_set_usize (widget, -2, g_value_get_int (value));
       break;
     case PROP_VISIBLE:
@@ -1189,7 +1146,6 @@ gtk_widget_get_property (GObject        
   
   switch (prop_id)
     {
-      GtkWidgetAuxInfo *aux_info;
       gint *eventp;
       GdkExtensionMode *modep;
 
@@ -1205,34 +1161,6 @@ gtk_widget_get_property (GObject        
       else
 	g_value_set_object (value, NULL);
       break;
-    case PROP_X:
-      aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-      if (!aux_info || !aux_info->x_set)
-	g_value_set_int (value, -1);
-      else
-	g_value_set_int (value, aux_info->x);
-      break;
-    case PROP_Y:
-      aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-      if (!aux_info || !aux_info->y_set)
-	g_value_set_int (value, -1);
-      else
-	g_value_set_int (value, aux_info->y);
-      break;
-    case PROP_WIDTH:
-      aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-      if (!aux_info)
- 	g_value_set_int (value, -1);
-      else
-	g_value_set_int (value, aux_info->width);
-      break;
-    case PROP_HEIGHT:
-      aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-      if (!aux_info)
- 	g_value_set_int (value, -1);
-      else
- 	g_value_set_int (value, aux_info->height);
-      break;
     case PROP_VISIBLE:
       g_value_set_boolean (value, (GTK_WIDGET_VISIBLE (widget) != FALSE));
       break;
@@ -2255,11 +2183,21 @@ gtk_widget_draw (GtkWidget    *widget,
  * gtk_widget_size_request:
  * @widget: a #GtkWidget
  * @requisition: a #GtkRequisition to be filled in
+ * 
+ * This function is typically used when implementing a #GtkContainer
+ * subclass.  Obtains the preferred size of a widget. The container
+ * uses this information to arrange its child widgets and decide what
+ * size allocations to give them with gtk_widget_size_allocate().
+ *
+ * You can also call this function from an application, with some
+ * caveats. Most notably, getting a size request requires the widget
+ * to be associated with a screen, because font information may be
+ * needed. Multihead-aware applications should keep this in mind.
+ *
+ * Also remember that the size request is not necessarily the size
+ * a widget will actually be allocated.
  * 
- * This function is only used when implementing a #GtkContainer subclass.
- * Obtains the preferred size of a widget. The container uses this
- * information to arrange its child widgets and decide what size allocations
- * to give them with gtk_widget_size_allocate().
+ * See also gtk_widget_get_child_requisition().
  **/
 void
 gtk_widget_size_request (GtkWidget	*widget,
@@ -2292,6 +2230,19 @@ gtk_widget_size_request (GtkWidget	*widg
  * @widget->requisition, unless someone has forced a particular
  * geometry on the widget (e.g. with gtk_widget_set_usize()), in which
  * case it returns that geometry instead of the widget's requisition.
+ *
+ * This function differs from gtk_widget_size_request() in that
+ * it retrieves the last size request value from widget->requisition,
+ * while gtk_widget_size_request() actually calls the "size_request" method
+ * on @widget to compute the size request and fill in widget->requisition,
+ * and only then returns widget->requisition.
+ *
+ * Because this function does not call the "size_request" method, it
+ * can only be used when you know that widget->requisition is
+ * up-to-date, that is, gtk_widget_size_request() has been called
+ * since the last time a resize was queued. In general, only container
+ * implementations have this information; applications should use
+ * gtk_widget_size_request().
  **/
 void
 gtk_widget_get_child_requisition (GtkWidget	 *widget,
@@ -4249,28 +4200,6 @@ gtk_widget_child_focus (GtkWidget       
   return return_val;
 }
 
-/* Update the position from aux_info. Used from gtk_widget_set_uposition
- * and gtk_widget_set_property().
- */
-static void
-gtk_widget_do_uposition (GtkWidget *widget)
-{
-  GtkWidgetAuxInfo *aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-
-  if (GTK_IS_WINDOW (widget) && aux_info->x_set && aux_info->y_set)
-    _gtk_window_reposition (GTK_WINDOW (widget), aux_info->x, aux_info->y);
-  
-  if (GTK_WIDGET_VISIBLE (widget) && widget->parent)
-    gtk_widget_size_allocate (widget, &widget->allocation);
-
-  g_object_freeze_notify (G_OBJECT (widget));
-  if (aux_info->x_set)
-    g_object_notify (G_OBJECT (widget), "x");
-  if (aux_info->y_set)
-    g_object_notify (G_OBJECT (widget), "y");
-  g_object_thaw_notify (G_OBJECT (widget));
-}
-
 /**
  * gtk_widget_set_uposition:
  * @widget: a #GtkWidget
@@ -4299,6 +4228,11 @@ gtk_widget_set_uposition (GtkWidget *wid
 			  gint	     x,
 			  gint	     y)
 {
+  /* FIXME this function is the only place that aux_info->x and
+   * aux_info->y are even used I believe, and this function is
+   * deprecated. Should be cleaned up.
+   */
+  
   GtkWidgetAuxInfo *aux_info;
   
   g_return_if_fail (widget != NULL);
@@ -4328,7 +4262,11 @@ gtk_widget_set_uposition (GtkWidget *wid
 	}
     }
 
-  gtk_widget_do_uposition (widget);
+  if (GTK_IS_WINDOW (widget) && aux_info->x_set && aux_info->y_set)
+    _gtk_window_reposition (GTK_WINDOW (widget), aux_info->x, aux_info->y);
+  
+  if (GTK_WIDGET_VISIBLE (widget) && widget->parent)
+    gtk_widget_size_allocate (widget, &widget->allocation);
 }
 
 /**
@@ -4337,6 +4275,9 @@ gtk_widget_set_uposition (GtkWidget *wid
  * @width: minimum width, or -1 to unset
  * @height: minimum height, or -1 to unset
  *
+ * This function is deprecated; use gtk_widget_set_size_request()
+ * instead.
+ * 
  * Sets the minimum size of a widget; that is, the widget's size
  * request will be @width by @height. You can use this function to
  * force a widget to be either larger or smaller than it is. The
@@ -4372,12 +4313,12 @@ gtk_widget_set_usize (GtkWidget *widget,
   
   if (width > -2)
     {
-      g_object_notify (G_OBJECT (widget), "width");
+      g_object_notify (G_OBJECT (widget), "width_request");
       aux_info->width = width;
     }
   if (height > -2)
     {
-      g_object_notify (G_OBJECT (widget), "height");  
+      g_object_notify (G_OBJECT (widget), "height_request");  
       aux_info->height = height;
     }
   
@@ -4388,19 +4329,76 @@ gtk_widget_set_usize (GtkWidget *widget,
 }
 
 /**
- * gtk_widget_get_usize:
+ * gtk_widget_set_size_request:
  * @widget: a #GtkWidget
- * @width: location to store the width, or %NULL
- * @height: location to store the height, or %NULL
+ * @width: width @widget should request, or -1 to unset
+ * @height: height @widget should request, or -1 to unset
  *
- * Gets the size that has explicitely set for the widget to request,
- * if any. A value of -1 stored in @width or @height indicates that
- * that dimension has not been set explicitely and the natural
- * requisition of the widget will be used intead. See
- * gtk_widget_set_usize().
+ * Sets the minimum size of a widget; that is, the widget's size
+ * request will be @width by @height. You can use this function to
+ * force a widget to be either larger or smaller than it normally
+ * would be.
+ *
+ * In most cases, gtk_window_set_default_size() is a better choice for
+ * toplevel windows than this function; setting the default size will
+ * still allow users to shrink the window. Setting the size request
+ * will force them to leave the window at least as large as the size
+ * request. When dealing with window sizes,
+ * gtk_window_set_geometry_hints() can be a useful function as well.
+ * 
+ * Note the inherent danger of setting any fixed size - themes,
+ * translations into other languages, different fonts, and user action
+ * can all change the appropriate size for a given widget. So, it's
+ * basically impossible to hardcode a size that will always be
+ * correct.
+ *
+ * The size request of a widget is the smallest size a widget can
+ * accept while still functioning well and drawing itself correctly.
+ * However in some strange cases a widget may be allocated less than
+ * its requested size, and in many cases a widget may be allocated more
+ * space than it requested.
+ *
+ * If the size request in a given direction is -1 (unset), then
+ * the "natural" size request of the widget will be used instead.
+ *
+ * Widgets can't actually be allocated a size less than 1 by 1, but
+ * you can pass 0,0 to this function to mean "as small as possible."
+ **/
+void
+gtk_widget_set_size_request (GtkWidget *widget,
+                             gint       width,
+                             gint       height)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (width >= -1);
+  g_return_if_fail (height >= -1);
+
+  if (width == 0)
+    width = 1;
+  if (height == 0)
+    height = 1;
+  
+  gtk_widget_set_usize (widget, width, height);
+}
+
+/**
+ * gtk_widget_get_size_request:
+ * @widget: a #GtkWidget
+ * @width: return location for width, or %NULL
+ * @height: return location for height, or %NULL
+ *
+ * Gets the size request that was explicitly set for the widget using
+ * gtk_widget_set_size_request().  A value of -1 stored in @width or
+ * @height indicates that that dimension has not been set explicitly
+ * and the natural requisition of the widget will be used intead. See
+ * gtk_widget_set_size_request(). To get the size a widget will
+ * actually use, call gtk_widget_size_request() instead of
+ * this function.
+ * 
  **/
+ 
 void
-gtk_widget_get_usize (GtkWidget *widget,
+gtk_widget_get_size_request (GtkWidget *widget,
 		      gint      *width,
 		      gint      *height)
 {
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.115
diff -u -p -u -b -r1.115 gtkwidget.h
--- gtk/gtkwidget.h	2001/07/01 00:57:21	1.115
+++ gtk/gtkwidget.h	2001/07/04 18:29:31
@@ -558,6 +558,14 @@ GtkWidget *gtk_widget_get_parent        
 GdkWindow *gtk_widget_get_parent_window	  (GtkWidget	       *widget);
 gboolean   gtk_widget_child_focus         (GtkWidget           *widget,
                                            GtkDirectionType     direction);
+
+void       gtk_widget_set_size_request    (GtkWidget           *widget,
+                                           gint                 width,
+                                           gint                 height);
+void       gtk_widget_get_size_request    (GtkWidget           *widget,
+                                           gint                *width,
+                                           gint                *height);
+#ifndef GTK_DISABLE_DEPRECATED
 void	   gtk_widget_set_uposition	  (GtkWidget	       *widget,
 					   gint			x,
 					   gint			y);
@@ -567,6 +575,8 @@ void	   gtk_widget_set_usize		  (GtkWidg
 void       gtk_widget_get_usize           (GtkWidget           *widget,
 					   gint                *width,
 					   gint                *height);
+#endif
+
 void	   gtk_widget_set_events	  (GtkWidget	       *widget,
 					   gint			events);
 void       gtk_widget_add_events          (GtkWidget           *widget,
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.134
diff -u -p -u -b -r1.134 gtkwindow.c
--- gtk/gtkwindow.c	2001/07/02 05:03:21	1.134
+++ gtk/gtkwindow.c	2001/07/04 18:29:32
@@ -82,8 +82,7 @@ enum {
 typedef struct {
   GdkGeometry    geometry; /* Last set of geometry hints we set */
   GdkWindowHints flags;
-  gint           width;
-  gint           height;
+  GdkRectangle   configure_request;
 } GtkWindowLastGeometryInfo;
 
 struct _GtkWindowGeometryInfo
@@ -93,9 +92,29 @@ struct _GtkWindowGeometryInfo
   GdkGeometry    geometry;	/* Geometry hints */
   GdkWindowHints mask;
   GtkWidget     *widget;	/* subwidget to which hints apply */
-  gint           width;		/* Default size */
-  gint           height;
-  guint		 may_shrink : 1; /* one-shot auto_shrink behaviour after set_default_size */
+  /* from last gtk_window_resize () - if > 0, indicates that
+   * we should resize to this size.
+   */
+  gint           resize_width;  
+  gint           resize_height;
+
+  /* From last gtk_window_move () prior to mapping -
+   * only used if initial_pos_set
+   */
+  gint           initial_x;
+  gint           initial_y;
+  
+  /* Default size - used only the FIRST time we map a window,
+   * only if > 0.
+   */
+  gint           default_width; 
+  gint           default_height;
+  /* whether to use initial_x, initial_y */
+  guint          initial_pos_set : 1;
+  /* CENTER_ALWAYS or other position constraint changed since
+   * we sent the last configure request.
+   */
+  guint          position_constraints_changed : 1;
 
   GtkWindowLastGeometryInfo last;
 };
@@ -153,15 +172,26 @@ static void gtk_window_real_activate_def
 static void gtk_window_real_activate_focus   (GtkWindow         *window);
 static void gtk_window_move_focus            (GtkWindow         *window,
                                               GtkDirectionType   dir);
+static void gtk_window_read_rcfiles       (GtkWidget         *widget,
+					   GdkEventClient    *event);
+static void gtk_window_paint              (GtkWidget         *widget,
+					   GdkRectangle      *area);
+static gint gtk_window_expose             (GtkWidget         *widget,
+				           GdkEventExpose    *event);
+static void gtk_window_unset_transient_for         (GtkWindow  *window);
+static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
+						    GtkWidget  *window);
+static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
+						    GtkWidget  *window);
+
+static GtkWindowGeometryInfo* gtk_window_get_geometry_info         (GtkWindow    *window,
+                                                                    gboolean      create);
 
 static void gtk_window_move_resize        (GtkWindow         *window);
 static gboolean gtk_window_compare_hints  (GdkGeometry       *geometry_a,
 					   guint              flags_a,
 					   GdkGeometry       *geometry_b,
 					   guint              flags_b);
-static void gtk_window_compute_default_size (GtkWindow       *window,
-					     guint           *width,
-					     guint           *height);
 static void  gtk_window_constrain_size      (GtkWindow       *window,
 					     GdkGeometry     *geometry,
 					     guint            flags,
@@ -169,29 +199,24 @@ static void  gtk_window_constrain_size  
 					     gint             height,
 					     gint            *new_width,
 					     gint            *new_height);
-static void gtk_window_compute_hints      (GtkWindow         *window, 
-					   GdkGeometry       *new_geometry,
-					   guint             *new_flags);
-static gint gtk_window_compute_reposition (GtkWindow         *window,
+static void     gtk_window_constrain_position        (GtkWindow    *window,
 					   gint               new_width,
 					   gint               new_height,
 					   gint              *x,
 					   gint              *y);
-
-static void gtk_window_read_rcfiles       (GtkWidget         *widget,
-					   GdkEventClient    *event);
-static void gtk_window_paint              (GtkWidget         *widget,
-					   GdkRectangle      *area);
-static gint gtk_window_expose             (GtkWidget         *widget,
-				           GdkEventExpose    *event);
-static void gtk_window_unset_transient_for         (GtkWindow  *window);
-static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
-						    GtkWidget  *window);
-static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
-						    GtkWidget  *window);
+static void     gtk_window_compute_hints             (GtkWindow    *window,
+                                                      GdkGeometry  *new_geometry,
+                                                      guint        *new_flags);
+static void     gtk_window_compute_configure_request (GtkWindow    *window,
+                                                      GdkRectangle *request,
+                                                      GdkGeometry  *geometry,
+                                                      guint        *flags);
 
-static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
-							    gboolean   create);
+static void     gtk_window_set_default_size_internal (GtkWindow    *window,
+                                                      gboolean      change_width,
+                                                      gint          width,
+                                                      gboolean      change_height,
+                                                      gint          height);
 
 
 static GSList      *toplevel_list = NULL;
@@ -335,18 +360,10 @@ gtk_window_class_init (GtkWindowClass *k
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
-                                   PROP_AUTO_SHRINK,
-                                   g_param_spec_boolean ("auto_shrink",
-							 _("Auto Shrink"),
-							 _("If TRUE, the window automatically shrinks to its size request anytime a resize occurs. Don't use this feature, it makes no sense."),
-							 FALSE,
-							 G_PARAM_READWRITE));
-
-  g_object_class_install_property (gobject_class,
                                    PROP_ALLOW_SHRINK,
                                    g_param_spec_boolean ("allow_shrink",
 							 _("Allow Shrink"),
-							 _("If TRUE, the window has no mimimum size. Don't use this feature, it makes no sense."),
+							 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
 							 FALSE,
 							 G_PARAM_READWRITE));
 
@@ -387,20 +404,20 @@ gtk_window_class_init (GtkWindowClass *k
                                    PROP_DEFAULT_WIDTH,
                                    g_param_spec_int ("default_width",
 						     _("Default Width"),
-						     _("The default width of the window, or 0 to use the size request."),
-						     0,
+						     _("The default width of the window, used when initially showing the window."),
+						     -1,
 						     G_MAXINT,
-						     0,
+						     -1,
 						     G_PARAM_READWRITE));
  
   g_object_class_install_property (gobject_class,
                                    PROP_DEFAULT_HEIGHT,
                                    g_param_spec_int ("default_height",
 						     _("Default Height"),
-						     _("The default height of the window, or 0 to use the size request."),
-						     0,
+						     _("The default height of the window, used when initially showing the window."),
+						     -1,
 						     G_MAXINT,
-						     0,
+						     -1,
 						     G_PARAM_READWRITE));
  
   g_object_class_install_property (gobject_class,
@@ -552,13 +569,13 @@ gtk_window_init (GtkWindow *window)
   window->type = GTK_WINDOW_TOPLEVEL;
   window->focus_widget = NULL;
   window->default_widget = NULL;
-  window->resize_count = 0;
+  window->configure_request_count = 0;
   window->allow_shrink = FALSE;
   window->allow_grow = TRUE;
-  window->auto_shrink = FALSE;
-  window->handling_resize = FALSE;
+  window->configure_notify_received = FALSE;
   window->position = GTK_WIN_POS_NONE;
-  window->use_uposition = TRUE;
+  window->need_default_size = TRUE;
+  window->need_default_position = TRUE;
   window->modal = FALSE;
   window->frame = NULL;
   window->has_frame = FALSE;
@@ -603,8 +620,6 @@ gtk_window_set_property (GObject      *o
       gtk_window_set_title (window, g_value_get_string (value));
       break;
     case PROP_AUTO_SHRINK:
-      window->auto_shrink = g_value_get_boolean (value);
-      gtk_widget_queue_resize (GTK_WIDGET (window));
       break;
     case PROP_ALLOW_SHRINK:
       window->allow_shrink = g_value_get_boolean (value);
@@ -627,10 +642,14 @@ gtk_window_set_property (GObject      *o
       gtk_window_set_position (window, g_value_get_enum (value));
       break;
     case PROP_DEFAULT_WIDTH:
-      gtk_window_set_default_size (window, g_value_get_int (value), -1);
+      gtk_window_set_default_size_internal (window,
+                                            TRUE, g_value_get_int (value),
+                                            FALSE, -1);
       break;
     case PROP_DEFAULT_HEIGHT:
-      gtk_window_set_default_size (window, -1, g_value_get_int (value));
+      gtk_window_set_default_size_internal (window,
+                                            FALSE, -1,
+                                            TRUE, g_value_get_int (value));
       break;
     case PROP_DESTROY_WITH_PARENT:
       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
@@ -660,7 +679,7 @@ gtk_window_get_property (GObject      *o
       g_value_set_string (value, window->title);
       break;
     case PROP_AUTO_SHRINK:
-      g_value_set_boolean (value, window->auto_shrink);
+      g_value_set_boolean (value, FALSE);
       break;
     case PROP_ALLOW_SHRINK:
       g_value_set_boolean (value, window->allow_shrink);
@@ -680,16 +699,16 @@ gtk_window_get_property (GObject      *o
     case PROP_DEFAULT_WIDTH:
       info = gtk_window_get_geometry_info (window, FALSE);
       if (!info)
-	g_value_set_int (value, 0);
+	g_value_set_int (value, -1);
       else
-	g_value_set_int (value, info->width);
+	g_value_set_int (value, info->default_width);
       break;
     case PROP_DEFAULT_HEIGHT:
       info = gtk_window_get_geometry_info (window, FALSE);
       if (!info)
-	g_value_set_int (value, 0);
+	g_value_set_int (value, -1);
       else
-	g_value_set_int (value, info->height);
+	g_value_set_int (value, info->default_height);
       break;
     case PROP_DESTROY_WITH_PARENT:
       g_value_set_boolean (value, window->destroy_with_parent);
@@ -955,12 +974,10 @@ gtk_window_set_policy (GtkWindow *window
 
   window->allow_shrink = (allow_shrink != FALSE);
   window->allow_grow = (allow_grow != FALSE);
-  window->auto_shrink = (auto_shrink != FALSE);
 
   g_object_notify (G_OBJECT (window), "allow_shrink");
   g_object_notify (G_OBJECT (window), "allow_grow");
   g_object_notify (G_OBJECT (window), "resizable");
-  g_object_notify (G_OBJECT (window), "auto_shrink");
   
   gtk_widget_queue_resize (GTK_WIDGET (window));
 }
@@ -1132,6 +1149,22 @@ gtk_window_set_position (GtkWindow      
 {
   g_return_if_fail (GTK_IS_WINDOW (window));
 
+  if (position == GTK_WIN_POS_CENTER_ALWAYS ||
+      window->position == GTK_WIN_POS_CENTER_ALWAYS)
+    {
+      GtkWindowGeometryInfo *info;
+
+      info = gtk_window_get_geometry_info (window, TRUE);
+
+      /* this flag causes us to re-request the CENTER_ALWAYS
+       * constraint in gtk_window_move_resize(), see
+       * comment in that function.
+       */
+      info->position_constraints_changed = TRUE;
+
+      gtk_widget_queue_resize (GTK_WIDGET (window));
+    }
+
   window->position = position;
 
   g_object_notify (G_OBJECT (window), "window_position");
@@ -1301,30 +1334,10 @@ _gtk_window_reposition (GtkWindow *windo
 			gint       x,
 			gint       y)
 {
-  GtkWindowGeometryInfo *info;
-  
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
-
-  /* keep this in sync with gtk_window_compute_reposition()
-   */
-  if (GTK_WIDGET_REALIZED (window))
-    {
-      info = gtk_window_get_geometry_info (window, TRUE);
-
-      if (!(info->last.flags & GDK_HINT_POS))
-	{
-	  info->last.flags |= GDK_HINT_POS;
-	  gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
-					 &info->last.geometry,
-					 info->last.flags);
-	}
 
-      if (window->frame)
-	gdk_window_move (window->frame,	 x - window->frame_left, y - window->frame_top);
-      else
-	gdk_window_move (GTK_WIDGET (window)->window, x, y);
-    }
+  gtk_window_move (window, x, y);
 }
 
 static void
@@ -1586,13 +1599,20 @@ gtk_window_get_geometry_info (GtkWindow 
     {
       info = g_new0 (GtkWindowGeometryInfo, 1);
 
-      info->width = 0;
-      info->height = 0;
-      info->last.width = -1;
-      info->last.height = -1;
+      info->default_width = -1;
+      info->default_height = -1;
+      info->resize_width = -1;
+      info->resize_height = -1;
+      info->initial_x = 0;
+      info->initial_y = 0;
+      info->initial_pos_set = FALSE;
+      info->position_constraints_changed = FALSE;
+      info->last.configure_request.x = 0;
+      info->last.configure_request.y = 0;
+      info->last.configure_request.width = -1;
+      info->last.configure_request.height = -1;
       info->widget = NULL;
       info->mask = 0;
-      info->may_shrink = FALSE;
       window->geometry_info = info;
     }
 
@@ -1637,8 +1657,14 @@ gtk_window_set_geometry_hints (GtkWindow
 
   if (geometry)
     info->geometry = *geometry;
+
+  /* We store gravity in window->gravity not in the hints. */
+  info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
 
-  info->mask = geom_mask;
+  if (geom_mask & GDK_HINT_WIN_GRAVITY)
+    {
+      gtk_window_set_gravity (window, geometry->win_gravity);
+    }
 
   gtk_widget_queue_resize (GTK_WIDGET (window));
 }
@@ -1694,21 +1720,73 @@ gtk_window_get_decorated (GtkWindow *win
   return window->decorated;
 }
 
+static void
+gtk_window_set_default_size_internal (GtkWindow    *window,
+                                      gboolean      change_width,
+                                      gint          width,
+                                      gboolean      change_height,
+                                      gint          height)
+{
+  GtkWindowGeometryInfo *info;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (change_width == FALSE || width >= -1);
+  g_return_if_fail (change_height == FALSE || height >= -1);
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+
+  g_object_freeze_notify (G_OBJECT (window));
+
+  if (change_width)
+    {
+      if (width == 0)
+        width = 1;
+
+      if (width < 0)
+        width = -1;
+
+      info->default_width = width;
+
+      g_object_notify (G_OBJECT (window), "default_width");
+    }
+
+  if (change_height)
+    {
+      if (height == 0)
+        height = 1;
+
+      if (height < 0)
+        height = -1;
+
+      info->default_height = height;
+      
+      g_object_notify (G_OBJECT (window), "default_height");
+    }
+  
+  g_object_thaw_notify (G_OBJECT (window));
+  
+  gtk_widget_queue_resize (GTK_WIDGET (window));
+}
+
 /**
  * gtk_window_set_default_size:
  * @window: a #GtkWindow
- * @width: width in pixels, 0 to unset, or -1 to leave the width unchanged
- * @height: height in pixels, 0 to unset, or -1 to leave the height unchanged
+ * @width: width in pixels, or -1 to unset the default width
+ * @height: height in pixels, or -1 to unset the default height
  *
  * Sets the default size of a window. If the window's "natural" size
  * (its size request) is larger than the default, the default will be
- * ignored. So the default size is a minimum initial size.  Unlike
- * gtk_widget_set_usize(), which sets a size request for a widget and
- * thus would keep users from shrinking the window, this function only
- * sets the initial size, just as if the user had resized the window
- * themselves. Users can still shrink the window again as they
- * normally would. Setting a default size of 0 means to use the
- * "natural" default size (the size request of the window).
+ * ignored. More generally, if the default size does not obey the
+ * geometry hints for the window (gtk_window_set_geometry_hints() can
+ * be used to set these explicitly), the default size will be clamped
+ * to the nearest permitted size.
+ * 
+ * Unlike gtk_widget_set_size_request(), which sets a size request for
+ * a widget and thus would keep users from shrinking the window, this
+ * function only sets the initial size, just as if the user had
+ * resized the window themselves. Users can still shrink the window
+ * again as they normally would. Setting a default size of -1 means to
+ * use the "natural" default size (the size request of the window).
  *
  * For more control over a window's initial size and how resizing works,
  * investigate gtk_window_set_geometry_hints().
@@ -1718,34 +1796,28 @@ gtk_window_get_decorated (GtkWindow *win
  * gtk_window_set_default_size() will be the default size of that
  * widget, not of the entire window.
  * 
+ * For some uses, gtk_window_resize() is a more appropriate function.
+ * gtk_window_resize() changes the current size of the window, rather
+ * than the size to be used on initial display. gtk_window_resize() always
+ * affects the window itself, not the geometry widget.
+ *
+ * The default size of a window only affects the first time a window is
+ * shown; if a window is hidden and re-shown, it will remember the size
+ * it had prior to hiding, rather than using the default size.
+ *
+ * Windows can't actually be 0x0 in size, they must be at least 1x1, but
+ * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
  **/
 void       
 gtk_window_set_default_size (GtkWindow   *window,
 			     gint         width,
 			     gint         height)
 {
-  GtkWindowGeometryInfo *info;
-
   g_return_if_fail (GTK_IS_WINDOW (window));
-
-  info = gtk_window_get_geometry_info (window, TRUE);
-
-  g_object_freeze_notify (G_OBJECT (window));
-  if (width >= 0)
-    {
-      info->width = width;
-      g_object_notify (G_OBJECT (window), "default_width");
-      info->may_shrink = TRUE;
-    }
-  if (height >= 0)
-    {
-      info->height = height;
-      g_object_notify (G_OBJECT (window), "default_height");
-      info->may_shrink = TRUE;
-    }
-  g_object_thaw_notify (G_OBJECT (window));
+  g_return_if_fail (width >= -1);
+  g_return_if_fail (height >= -1);
   
-  gtk_widget_queue_resize (GTK_WIDGET (window));
+  gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
 }
 
 /**
@@ -1754,10 +1826,11 @@ gtk_window_set_default_size (GtkWindow  
  * @width: location to store the default width, or %NULL
  * @height: location to store the default height, or %NULL
  *
- * Gets the default size of the window. A value of 0 for the
- * width or height indicates that a default size has not
- * been explicitely set for that dimension, so the value
- * will be computed from the requisition of the window.
+ * Gets the default size of the window. A value of -1 for the width or
+ * height indicates that a default size has not been explicitly set
+ * for that dimension, so the "natural" size of the window will be
+ * used.
+ * 
  **/
 void
 gtk_window_get_default_size (GtkWindow *window,
@@ -1771,138 +1844,557 @@ gtk_window_get_default_size (GtkWindow *
   info = gtk_window_get_geometry_info (window, FALSE);
 
   if (width)
-    *width = info ? info->width : 0;
+    *width = info->default_width;
 
   if (height)
-    *height = info ? info->height : 0;
+    *height = info->default_height;
 }
   
-static void
-gtk_window_destroy (GtkObject *object)
+/**
+ * gtk_window_resize:
+ * @window: a #GtkWindow
+ * @width: width to resize the window to
+ * @height: height to resize the window to
+ *
+ * Resizes the window as if the user had done so, obeying geometry
+ * constraints. The default geometry constraint is that windows may
+ * not be smaller than their size request; to override this
+ * constraint, call gtk_widget_set_size_request() to set the window's
+ * request to a smaller value.
+ *
+ * If gtk_window_resize() is called before showing a window for the
+ * first time, it overrides any default size set with
+ * gtk_window_set_default_size().
+ *
+ * Windows may not be resized smaller than 1 by 1 pixels.
+ * 
+ **/
+void
+gtk_window_resize (GtkWindow *window,
+                   gint       width,
+                   gint       height)
 {
-  GtkWindow *window;
-  
-  g_return_if_fail (GTK_IS_WINDOW (object));
-
-  window = GTK_WINDOW (object);
+  GtkWindowGeometryInfo *info;
 
-  if (window->transient_parent)
-    gtk_window_set_transient_for (window, NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (width > 0);
+  g_return_if_fail (height > 0);
 
-  if (window->has_user_ref_count)
-    {
-      window->has_user_ref_count = FALSE;
-      gtk_widget_unref (GTK_WIDGET (window));
-    }
+  info = gtk_window_get_geometry_info (window, TRUE);
 
-  if (window->group)
-    gtk_window_group_remove_window (window->group, window);
+  info->resize_width = width;
+  info->resize_height = height;
 
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+  gtk_widget_queue_resize (GTK_WIDGET (window));
 }
 
-static gboolean
-gtk_window_mnemonic_hash_remove (gpointer	key,
-				 gpointer	value,
-				 gpointer	user)
+/**
+ * gtk_window_get_size:
+ * @window: a #GtkWindow
+ * @width: return location for width, or %NULL
+ * @height: return location for height, or %NULL
+ *
+ * Obtains the current size of @window. If @window is not onscreen,
+ * returns the size GTK+ will suggest to the window manager for the
+ * initial window size (but this is not reliably the same as the size
+ * the window manager will actually select). The size obtained by
+ * gtk_window_get_size() is the last size received in a
+ * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
+ * rather than querying the X server for the size. As a result, if you
+ * call gtk_window_resize() then immediately call
+ * gtk_window_get_size(), the size won't have taken effect yet. After
+ * the window manager processes the resize request, GTK+ receives
+ * notification that the size has changed via a configure event, and
+ * the size of the window gets updated.
+ *
+ * Note #1: Nearly any use of this function creates a race condition,
+ * because the size of the window may change between the time that you
+ * get the size and the time that you perform some action assuming
+ * that size is the current size. To avoid race conditions, connect to
+ * "configure_event" on the window and adjust your size-dependent
+ * state to match the size delivered in the #GdkEventConfigure.
+ *
+ * Note #2: The returned size does NOT include the size of the window
+ * manager decorations (aka the window frame or border). Those
+ * are not drawn by GTK+ and GTK+ has no reliable method of
+ * determining their size.
+ *
+ * Note #3: If you are getting a window size in order to position
+ * the window onscreen, there may be a better way. The preferred
+ * way is to simply set the window's semantic type with
+ * gtk_window_set_type_hint(), which allows the window manager to
+ * e.g. center dialogs. Also, if you set the transient parent of
+ * dialogs with gtk_widget_set_transient_for() window managers
+ * will often center the dialog over its parent window. It's
+ * much preferred to let the window manager handle these
+ * things rather than doing it yourself, because all apps will
+ * behave consistently and according to user prefs if the window
+ * manager handles it. Also, the window manager can take the size
+ * of the window decorations/border into account, while your
+ * application cannot.
+ *
+ * In any case, if you insist on application-specified window
+ * positioning, there's STILL a better way than doing it yourself -
+ * gtk_window_set_position() will frequently handle the details
+ * for you.
+ * 
+ **/
+void
+gtk_window_get_size (GtkWindow *window,
+                     gint      *width,
+                     gint      *height)
 {
-  GtkWindowMnemonic *mnemonic = key;
-  GtkWindow *window = user;
+  gint w, h;
+  GtkWidget *widget;
 
-  if (mnemonic->window == window)
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  widget = GTK_WIDGET (window);
+  
+  if (width == NULL && height == NULL)
+    return;
+
+  if (GTK_WIDGET_MAPPED (window))
     {
-      if (mnemonic->targets)
+      gdk_drawable_get_size (GTK_WIDGET (window)->window,
+                             &w, &h);
+    }
+  else
 	{
-	  gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
+      GdkRectangle configure_request;
 
-	  g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
-		     name, mnemonic->targets->data);
-	  g_free (name);
-	}
-      g_slist_free (mnemonic->targets);
-      g_free (mnemonic);
+      gtk_window_compute_configure_request (window,
+                                            &configure_request,
+                                            NULL, NULL);
       
-      return TRUE;
+      w = configure_request.width;
+      h = configure_request.height;
     }
-  return FALSE;
+  
+  if (width)
+    *width = w;
+  if (height)
+    *height = h;
 }
 
-static void
-gtk_window_finalize (GObject *object)
+/**
+ * gtk_window_move:
+ * @window: a #GtkWindow
+ * @x: X coordinate to move window to
+ * @y: Y coordinate to move window to
+ *
+ * Asks the window manager to move @window to the given position.
+ * Window managers are free to ignore this; most window managers
+ * ignore requests for initial window positions (instead using a
+ * user-defined placement algorithm) and honor requests after the
+ * window has already been shown.
+ *
+ * Note: the position is the position of the gravity-determined
+ * reference point for the window. The gravity determines two things:
+ * first, the location of the reference point in root window
+ * coordinates; and second, which point on the window is positioned at
+ * the reference point.
+ *
+ * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
+ * point is simply the @x, @y supplied to gtk_window_move(). The
+ * top-left corner of the window decorations (aka window frame or
+ * border) will be placed at @x, @y.  Therefore, to position a window
+ * at the top left of the screen, you want to use the default gravity
+ * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
+ *
+ * To position a window at the bottom right corner of the screen, you
+ * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
+ * point is at @x + the window width and @y + the window height, and
+ * the bottom-right corner of the window border will be placed at that
+ * reference point. So, to place a window in the bottom right corner
+ * you would first set gravity to south east, then write:
+ * gtk_window_move (window, gdk_screen_width () - window_width,
+ * gdk_screen_height () - window_height).
+ *
+ * The extended window manager hints specification at
+ * http://www.freedesktop.org/standards/wm-spec.html has a nice table
+ * of gravities in the "implementation notes" section.
+ *
+ * The gtk_window_get_position() documentation may also be relevant.
+ * 
+ **/
+void
+gtk_window_move (GtkWindow *window,
+                 gint       x,
+                 gint       y)
 {
-  GtkWindow *window;
+  GtkWindowGeometryInfo *info;
+  GtkWidget *widget;
 
-  g_return_if_fail (GTK_IS_WINDOW (object));
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
-  window = GTK_WINDOW (object);
+  widget = GTK_WIDGET (window);
 
-  toplevel_list = g_slist_remove (toplevel_list, window);
+  info = gtk_window_get_geometry_info (window, TRUE);  
 
-  g_free (window->title);
-  g_free (window->wmclass_name);
-  g_free (window->wmclass_class);
-  g_free (window->wm_role);
+  if (GTK_WIDGET_MAPPED (window))
+    {
+      /* we have now sent a request with this position
+       * with currently-active constraints, so toggle flag.
+       */
+      info->position_constraints_changed = FALSE;
 
-  g_hash_table_foreach_remove (mnemonic_hash_table,
-			       gtk_window_mnemonic_hash_remove,
-			       window);
-  if (window->geometry_info)
+      /* we only constrain if mapped - if not mapped,
+       * then gtk_window_compute_configure_request()
+       * will apply the constraints later, and we
+       * don't want to lose information about
+       * what position the user set before then.
+       * i.e. if you do a move() then turn off POS_CENTER
+       * then show the window, your move() will work.
+       */
+      gtk_window_constrain_position (window,
+                                     widget->allocation.width,
+                                     widget->allocation.height,
+                                     &x, &y);
+      
+      /* Note that this request doesn't go through our standard request
+       * framework, e.g. doesn't increment configure_request_count,
+       * doesn't set info->last, etc.; that's because
+       * we don't save the info needed to arrive at this same request
+       * again.
+       *
+       * To gtk_window_move_resize(), this will end up looking exactly
+       * the same as the position being changed by the window
+       * manager.
+       */
+      
+      /* FIXME are we handling gravity properly for framed windows? */
+      if (window->frame)
+        gdk_window_move (window->frame,
+                         x - window->frame_left,
+                         y - window->frame_top);
+      else
+        gdk_window_move (GTK_WIDGET (window)->window,
+                         x, y);
+    }
+  else
     {
-      if (window->geometry_info->widget)
-	gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
-				       GTK_SIGNAL_FUNC (gtk_widget_destroyed),
-				       &window->geometry_info->widget);
-      g_free (window->geometry_info);
+      /* Save this position to apply on mapping */
+      info->initial_x = x;
+      info->initial_y = y;
+      info->initial_pos_set = TRUE;
     }
-  
-  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
-gtk_window_show (GtkWidget *widget)
+/**
+ * gtk_window_get_position:
+ * @window: a #GtkWindow
+ * @root_x: return location for X coordinate of gravity-determined reference p\oint
+ * @root_y: return location for Y coordinate of gravity-determined reference p\oint
+ *
+ * This function returns the position you need to pass to
+ * gtk_window_move() to keep @window in its current position.  This
+ * means that the meaning of the returned value varies with window
+ * gravity. See gtk_window_move() for more details.
+ * 
+ * If you haven't changed the window gravity, its gravity will be
+ * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
+ * returns the position of the top-left corner of the window
+ * manager frame for the window. gtk_window_move() sets the
+ * position of this same top-left corner.
+ *
+ * gtk_window_get_position() is not 100% reliable because the X Window System
+ * does not specify a way to obtain the geometry of the
+ * decorations placed on a window by the window manager.
+ * Thus GTK+ is using a "best guess" that works with most
+ * window managers.
+ *
+ * Moreover, nearly all window managers are broken with respect to
+ * their handling of window gravity. So moving a window to its current
+ * position as returned by gtk_window_get_position() tends to
+ * result in moving the window slightly.
+ *
+ * If a window has gravity #GDK_GRAVITY_STATIC the window manager
+ * frame is not relevant, and thus gtk_window_get_position() will
+ * always produce accurate results. However you can't use static
+ * gravity to do things like place a window in a corner of the screen,
+ * because static gravity ignores the window manager decorations.
+ *
+ * If you are saving and restoring your application's window
+ * positions, you should know that it's impossible for applications to
+ * do this without getting it somewhat wrong because applications do
+ * not have sufficient knowledge of window manager state. The Correct
+ * Mechanism is to support the session management protocol (see the
+ * "GnomeClient" object in the GNOME libraries for example) and allow
+ * the window manager to save your window sizes and positions.
+ * 
+ **/
+
+void
+gtk_window_get_position (GtkWindow *window,
+                         gint      *root_x,
+                         gint      *root_y)
 {
-  GtkWindow *window = GTK_WINDOW (widget);
-  GtkContainer *container = GTK_CONTAINER (window);
-  gboolean need_resize;
+  GtkWidget *widget;
   
-  GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
+  g_return_if_fail (GTK_IS_WINDOW (window));
   
-  need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
-  container->need_resize = FALSE;
+  widget = GTK_WIDGET (window);
   
-  if (need_resize)
+  if (window->gravity == GDK_GRAVITY_STATIC)
     {
-      GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
-      GtkAllocation allocation = { 0, 0 };
-      GdkGeometry new_geometry;
-      guint width, height, new_flags;
-      gboolean was_realized;
+      if (GTK_WIDGET_MAPPED (widget))
+        {
+          /* This does a server round-trip, which is
+           * sort of wrong; but a server round-trip
+           * is inevitable for gdk_window_get_frame_extents()
+           * in the usual NorthWestGravity case below,
+           * so not sure what else to do. We should likely
+           * be consistent.
+           */
+          gdk_window_get_origin (widget->window, root_x, root_y);
+        }
+      else
+        {
+          GdkRectangle configure_request;
       
-      /* determine default size to initially show the window with */
-      gtk_widget_size_request (widget, NULL);
-      gtk_window_compute_default_size (window, &width, &height);
+          gtk_window_compute_configure_request (window,
+                                                &configure_request,
+                                                NULL, NULL);
+          
+          *root_x = configure_request.x;
+          *root_y = configure_request.y;
+        }
+    }
+  else
+    {
+      GdkRectangle frame_extents;
       
-      /* save away the last default size for later comparisions */
-      info->last.width = width;
-      info->last.height = height;
+      gint x, y;
+      gint w, h;
 
-      /* constrain size to geometry */
-      gtk_window_compute_hints (window, &new_geometry, &new_flags);
-      gtk_window_constrain_size (window,
-				 &new_geometry, new_flags,
-				 width, height,
-				 &width, &height);
+      if (GTK_WIDGET_MAPPED (widget))
+        {
+          gdk_window_get_frame_extents (widget->window, &frame_extents);
+          x = frame_extents.x;
+          y = frame_extents.y;
+          gtk_window_get_size (window, &w, &h);
+        }
+      else
+        {
+          /* We just say the frame has 0 size on all sides.
+           * Not sure what else to do.
+           */             
+          gtk_window_compute_configure_request (window,
+                                                &frame_extents,
+                                                NULL, NULL);
+          x = frame_extents.x;
+          y = frame_extents.y;
+          w = frame_extents.width;
+          h = frame_extents.height;
+        }
+
+      switch (window->gravity)
+        {
+        case GDK_GRAVITY_NORTH:
+        case GDK_GRAVITY_CENTER:
+        case GDK_GRAVITY_SOUTH:
+          /* Find center of frame. */
+          x += frame_extents.width / 2;
+          /* Center client window on that point. */
+          x -= w / 2;
+          break;
+
+        case GDK_GRAVITY_SOUTH_EAST:
+        case GDK_GRAVITY_EAST:
+        case GDK_GRAVITY_NORTH_EAST:
+          /* Find right edge of frame */
+          x += frame_extents.width;
+          /* Align left edge of client at that point. */
+          x -= w;
+          break;
+        default:
+          break;
+        }
+
+      switch (window->gravity)
+        {
+        case GDK_GRAVITY_WEST:
+        case GDK_GRAVITY_CENTER:
+        case GDK_GRAVITY_EAST:
+          /* Find center of frame. */
+          y += frame_extents.height / 2;
+          /* Center client window there. */
+          y -= h / 2;
+          break;
+        case GDK_GRAVITY_SOUTH_WEST:
+        case GDK_GRAVITY_SOUTH:
+        case GDK_GRAVITY_SOUTH_EAST:
+          /* Find south edge of frame */
+          y += frame_extents.height;
+          /* Place bottom edge of client there */
+          y -= h;
+          break;
+        default:
+          break;
+        }
+
+      if (root_x)
+        *root_x = x;
+      if (root_y)
+        *root_y = y;
+    }
+}
+
+/**
+ * gtk_window_reshow_with_initial_size:
+ * @window: a #GtkWindow
+ * 
+ * Hides @window, then reshows it, resetting the
+ * default size and position of the window. Used
+ * by GUI builders only.
+ **/
+void
+gtk_window_reshow_with_initial_size (GtkWindow *window)
+{
+  GtkWidget *widget;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  widget = GTK_WIDGET (window);
+  
+  gtk_widget_hide (widget);
+  gtk_widget_unrealize (widget);
+  gtk_widget_show (widget);
+}
+
+static void
+gtk_window_destroy (GtkObject *object)
+{
+  GtkWindow *window;
+  
+  g_return_if_fail (GTK_IS_WINDOW (object));
+
+  window = GTK_WINDOW (object);
+
+  if (window->transient_parent)
+    gtk_window_set_transient_for (window, NULL);
+
+  if (window->has_user_ref_count)
+    {
+      window->has_user_ref_count = FALSE;
+      gtk_widget_unref (GTK_WIDGET (window));
+    }
+
+  if (window->group)
+    gtk_window_group_remove_window (window->group, window);
+
+  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static gboolean
+gtk_window_mnemonic_hash_remove (gpointer	key,
+				 gpointer	value,
+				 gpointer	user)
+{
+  GtkWindowMnemonic *mnemonic = key;
+  GtkWindow *window = user;
+
+  if (mnemonic->window == window)
+    {
+      if (mnemonic->targets)
+	{
+	  gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
+
+	  g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
+		     name, mnemonic->targets->data);
+	  g_free (name);
+	}
+      g_slist_free (mnemonic->targets);
+      g_free (mnemonic);
+      
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static void
+gtk_window_finalize (GObject *object)
+{
+  GtkWindow *window;
+
+  g_return_if_fail (GTK_IS_WINDOW (object));
+
+  window = GTK_WINDOW (object);
+
+  toplevel_list = g_slist_remove (toplevel_list, window);
+
+  g_free (window->title);
+  g_free (window->wmclass_name);
+  g_free (window->wmclass_class);
+  g_free (window->wm_role);
+
+  g_hash_table_foreach_remove (mnemonic_hash_table,
+			       gtk_window_mnemonic_hash_remove,
+			       window);
+  if (window->geometry_info)
+    {
+      if (window->geometry_info->widget)
+	gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
+				       GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+				       &window->geometry_info->widget);
+      g_free (window->geometry_info);
+    }
+  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gtk_window_show (GtkWidget *widget)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkContainer *container = GTK_CONTAINER (window);
+  gboolean need_resize;
       
-      /* and allocate the window */
-      allocation.width  = width;
-      allocation.height = height;
+  GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
+  
+  need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
+  container->need_resize = FALSE;
+  
+  if (need_resize)
+    {
+      GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
+      GtkAllocation allocation = { 0, 0 };
+      GdkRectangle configure_request;
+      GdkGeometry new_geometry;
+      guint new_flags;
+      gboolean was_realized;
+
+      /* We are going to go ahead and perform this configure request
+       * and then emulate a configure notify by going ahead and
+       * doing a size allocate. Sort of a synchronous
+       * mini-copy of gtk_window_move_resize() here.
+       */
+      gtk_window_compute_configure_request (window,
+                                            &configure_request,
+                                            &new_geometry,
+                                            &new_flags);
+      
+      /* We update this because we are going to go ahead
+       * and gdk_window_resize() below, rather than
+       * queuing it.
+       */
+      info->last.configure_request.width = configure_request.width;
+      info->last.configure_request.height = configure_request.height;
+      
+      /* and allocate the window - this is normally done
+       * in move_resize in response to configure notify
+       */
+      allocation.width  = configure_request.width;
+      allocation.height = configure_request.height;
       gtk_widget_size_allocate (widget, &allocation);
       
+      /* Then we guarantee we have a realize */
       was_realized = FALSE;
       if (!GTK_WIDGET_REALIZED (widget))
 	{
 	  gtk_widget_realize (widget);
-	  was_realized = TRUE;;
+	  was_realized = TRUE;
 	}
 
       /* Must be done after the windows are realized,
@@ -1910,8 +2402,14 @@ gtk_window_show (GtkWidget *widget)
        */
       gtk_decorated_window_calculate_frame_size (window);
       
+      /* We only send configure request if we didn't just finish
+       * creating the window; if we just created the window
+       * then we created it with widget->allocation anyhow.
+       */
       if (!was_realized)
-	gdk_window_resize (widget->window, width, height);
+	gdk_window_resize (widget->window,
+                           configure_request.width,
+                           configure_request.height);
     }
   
   gtk_container_check_resize (container);
@@ -1977,6 +2475,10 @@ gtk_window_map (GtkWidget *widget)
   else
     gdk_window_deiconify (toplevel);
   
+  /* No longer use the default settings */
+  window->need_default_size = FALSE;
+  window->need_default_position = FALSE;
+  
   gdk_window_show (widget->window);
 
   if (window->frame)
@@ -1987,6 +2489,7 @@ static void
 gtk_window_unmap (GtkWidget *widget)
 {
   GtkWindow *window;
+  GtkWindowGeometryInfo *info;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_WINDOW (widget));
@@ -1999,10 +2502,21 @@ gtk_window_unmap (GtkWidget *widget)
   else 
     gdk_window_withdraw (widget->window);
 
-  window->use_uposition = TRUE;
-  window->resize_count = 0;
-  window->handling_resize = FALSE;
+  window->configure_request_count = 0;
+  window->configure_notify_received = FALSE;
 
+  /* on unmap, we reset the default positioning of the window,
+   * so it's placed again, but we don't reset the default
+   * size of the window, so it's remembered.
+   */
+  window->need_default_position = TRUE;
+
+  info = gtk_window_get_geometry_info (window, FALSE);
+  if (info)
+    {
+      info->initial_pos_set = FALSE;
+      info->position_constraints_changed = FALSE;
+    }
 }
 
 static void
@@ -2144,12 +2658,33 @@ static void
 gtk_window_unrealize (GtkWidget *widget)
 {
   GtkWindow *window;
+  GtkWindowGeometryInfo *info;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_WINDOW (widget));
 
   window = GTK_WINDOW (widget);
 
+  /* On unrealize, we reset the size of the window such
+   * that we will re-apply the default sizing stuff
+   * next time we show the window.
+   *
+   * Default positioning is reset on unmap, instead of unrealize.
+   */
+  window->need_default_size = TRUE;
+  info = gtk_window_get_geometry_info (window, FALSE);
+  if (info)
+    {
+      info->resize_width = -1;
+      info->resize_height = -1;
+      info->last.configure_request.x = 0;
+      info->last.configure_request.y = 0;
+      info->last.configure_request.width = -1;
+      info->last.configure_request.height = -1;
+      /* be sure we reset geom hints on re-realize */
+      info->last.flags = 0;
+    }
+  
   if (window->frame)
     {
       gdk_window_set_user_data (window->frame, NULL);
@@ -2293,47 +2828,55 @@ gtk_window_configure_event (GtkWidget   
 {
   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);
   
   window = GTK_WINDOW (widget);
 
-  /* we got a configure event specifying the new window size and position,
-   * in principle we have to distinguish 4 cases here:
-   * 1) the size didn't change and resize_count == 0
-   *    -> the window was merely moved (sometimes not even that)
-   * 2) the size didn't change and resize_count > 0
-   *    -> we requested a new size, but didn't get it
-   * 3) the size changed and resize_count > 0
-   *    -> we asked for a new size and we got one
-   * 4) the size changed and resize_count == 0
-   *    -> we got resized from outside the toolkit, and have to
-   *    accept that size since we don't want to fight neither the
-   *    window manager nor the user
-   * in the three latter cases we have to reallocate the widget tree,
-   * which happens in gtk_window_move_resize(), so we set a flag for
-   * that function and assign the new size. if resize_count > 1,
-   * we simply do nothing and wait for more configure events.
-   */
-
-  if (window->resize_count > 0 ||
-      widget->allocation.width != event->width ||
-      widget->allocation.height != event->height)
-    {
-      if (window->resize_count > 0)
-	window->resize_count -= 1;
+  /* window->configure_request_count incremented for each 
+   * configure request, and decremented to a min of 0 for
+   * each configure notify.
+   *
+   * All it means is that we know we will get at least
+   * window->configure_request_count more configure notifies.
+   * We could get more configure notifies than that; some
+   * of the configure notifies we get may be unrelated to
+   * the configure requests. But we will get at least
+   * window->configure_request_count notifies.
+   */
 
-      if (window->resize_count == 0)
-	{
-	  window->handling_resize = TRUE;
+  if (window->configure_request_count > 0)
+    window->configure_request_count -= 1;
 	  
+  /* As an optimization, we avoid a resize when possible.
+   *
+   * The only times we can avoid a resize are:
+   *   - we know only the position changed, not the size
+   *   - we know we have made more requests and so will get more
+   *     notifies and can wait to resize when we get them
+   */
+  
+  if (window->configure_request_count > 0 ||
+      (widget->allocation.width == event->width &&
+       widget->allocation.height == event->height))
+    return TRUE;
+
+  /*
+   * If we do need to resize, we do that by:
+   *   - filling in widget->allocation with the new size
+   *   - setting configure_notify_received to TRUE
+   *     for use in gtk_window_move_resize()
+   *   - queueing a resize, leading to invocation of
+   *     gtk_window_move_resize() in an idle handler
+   *
+   */
+  
+  window->configure_notify_received = TRUE;
+  
 	  widget->allocation.width = event->width;
 	  widget->allocation.height = event->height;
 	  
 	  gtk_widget_queue_resize (widget);
-	}
-    }
 
   return TRUE;
 }
@@ -2670,129 +3213,477 @@ gtk_window_real_set_focus (GtkWindow *wi
     gtk_widget_queue_draw (window->default_widget);
 }
 
+/*********************************
+ * Functions related to resizing *
+ *********************************/
+
+/* This function doesn't constrain to geometry hints */
+static void 
+gtk_window_compute_configure_request_size (GtkWindow *window,
+                                           guint     *width,
+                                           guint     *height)
+{
+  GtkRequisition requisition;
+  GtkWindowGeometryInfo *info;
+  GtkWidget *widget;
+
+  /* Preconditions:
+   *  - we've done a size request
+   */
+  
+  widget = GTK_WIDGET (window);
+
+  info = gtk_window_get_geometry_info (window, FALSE);
+  
+  if (window->need_default_size)
+    {
+      gtk_widget_get_child_requisition (widget, &requisition);
+
+      /* Default to requisition */
+      *width = requisition.width;
+      *height = requisition.height;
+
+      /* If window is empty so requests 0, default to random nonzero size */
+       if (*width == 0 && *height == 0)
+         {
+           *width = 200;
+           *height = 200;
+         }
+
+       /* Override requisition with default size */
+
+       if (info)
+         {
+           if (info->default_width > 0)
+             *width = info->default_width;
+           
+           if (info->default_height > 0)
+             *height = info->default_height;
+         }
+    }
+  else
+    {
+      /* Default to keeping current size */
+      *width = widget->allocation.width;
+      *height = widget->allocation.height;
+    }
+
+  /* Override any size with gtk_window_resize() values */
+  if (info)
+    {
+      if (info->resize_width > 0)
+        *width = info->resize_width;
+
+      if (info->resize_height > 0)
+        *height = info->resize_height;
+    }
+}
+
+static void
+gtk_window_compute_configure_request (GtkWindow    *window,
+                                      GdkRectangle *request,
+                                      GdkGeometry  *geometry,
+                                      guint        *flags)
+{
+  GdkGeometry new_geometry;
+  guint new_flags;
+  int w, h;
+  GtkWidget *widget;
+  GtkWindowPosition pos;
+  GtkWidget *parent_widget;
+  GtkWindowGeometryInfo *info;
+  int x, y;
+  
+  widget = GTK_WIDGET (window);
+  
+  gtk_widget_size_request (widget, NULL);
+  gtk_window_compute_configure_request_size (window, &w, &h);
+  
+  gtk_window_compute_hints (window, &new_geometry, &new_flags);
+  gtk_window_constrain_size (window,
+                             &new_geometry, new_flags,
+                             w, h,
+                             &w, &h);
+
+  parent_widget = (GtkWidget*) window->transient_parent;
+  
+  pos = window->position;
+  if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
+      (parent_widget == NULL ||
+       !GTK_WIDGET_MAPPED (parent_widget)))
+    pos = GTK_WIN_POS_NONE;
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+
+  /* by default, don't change position requested */
+  x = info->last.configure_request.x;
+  y = info->last.configure_request.y;
+  
+  if (window->need_default_position)
+    {
+
+      /* FIXME this all interrelates with window gravity.
+       * For most of them I think we want to set GRAVITY_CENTER.
+       *
+       * Not sure how to go about that.
+       */
+      
+      switch (pos)
+        {
+          /* here we are only handling CENTER_ALWAYS
+           * as it relates to default positioning,
+           * where it's equivalent to simply CENTER
+           */
+        case GTK_WIN_POS_CENTER_ALWAYS:
+        case GTK_WIN_POS_CENTER:
+          {
+            gint screen_width = gdk_screen_width ();
+            gint screen_height = gdk_screen_height ();
+            
+            x = (screen_width - w) / 2;
+            y = (screen_height - h) / 2;
+          }
+          break;
+      
+        case GTK_WIN_POS_CENTER_ON_PARENT:
+          {
+            gint ox, oy;
+            
+            g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
+            
+            gdk_window_get_origin (parent_widget->window,
+                                   &ox, &oy);
+            
+            x = ox + (parent_widget->allocation.width - w) / 2;
+            y = oy + (parent_widget->allocation.height - h) / 2;
+          }
+          break;
+
+        case GTK_WIN_POS_MOUSE:
+          {
+            gint screen_width = gdk_screen_width ();
+            gint screen_height = gdk_screen_height ();
+            int px, py;
+            
+            gdk_window_get_pointer (NULL, &px, &py, NULL);
+            x = px - w / 2;
+            y = py - h / 2;
+            x = CLAMP (x, 0, screen_width - w);
+            y = CLAMP (y, 0, screen_height - h);
+          }
+          break;
+
+        default:
+          break;
+        }
+    } /* if (window->need_default_position) */
+
+  if (window->need_default_position &&
+      info->initial_pos_set)
+    {
+      x = info->initial_x;
+      y = info->initial_y;
+      gtk_window_constrain_position (window, w, h, &x, &y);
+    }
+  
+  request->x = x;
+  request->y = y;
+  request->width = w;
+  request->height = h;
+
+  if (geometry)
+    *geometry = new_geometry;
+  if (flags)
+    *flags = new_flags;
+}
+
+static void
+gtk_window_constrain_position (GtkWindow    *window,
+                               gint          new_width,
+                               gint          new_height,
+                               gint         *x,
+                               gint         *y)
+{
+  /* See long comments in gtk_window_move_resize()
+   * on when it's safe to call this function.
+   */
+  if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
+    {
+      gint center_x, center_y;
+      gint screen_width = gdk_screen_width ();
+      gint screen_height = gdk_screen_height ();
 
+      center_x = (screen_width - new_width) / 2;
+      center_y = (screen_height - new_height) / 2;
 
-/*********************************
- * Functions related to resizing *
- *********************************/
+      *x = center_x;
+      *y = center_y;
+    }
+}
 
 static void
 gtk_window_move_resize (GtkWindow *window)
 {
+  /* Overview:
+   *
+   * First we determine whether any information has changed that would
+   * cause us to revise our last configure request.  If we would send
+   * a different configure request from last time, then
+   * configure_request_size_changed = TRUE or
+   * configure_request_pos_changed = TRUE. configure_request_size_changed
+   * may be true due to new hints, a gtk_window_resize(), or whatever.
+   * configure_request_pos_changed may be true due to gtk_window_set_position()
+   * or gtk_window_move().
+   *
+   * If the configure request has changed, we send off a new one.  To
+   * ensure GTK invariants are maintained (resize queue does what it
+   * should), we go ahead and size_allocate the requested size in this
+   * function.
+   *
+   * If the configure request has not changed, we don't ever resend
+   * it, because it could mean fighting the user or window manager.
+   *
+   * 
+   *   To prepare the configure request, we come up with a base size/pos:
+   *      - the one from gtk_window_move()/gtk_window_resize()
+   *      - else default_width, default_height if we haven't ever
+   *        been mapped
+   *      - else the size request if we haven't ever been mapped,
+   *        as a substitute default size
+   *      - else the current size of the window, as received from
+   *        configure notifies (i.e. the current allocation)
+   *
+   *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
+   *   the position request to be centered.
+   */
   GtkWidget *widget;
   GtkContainer *container;
   GtkWindowGeometryInfo *info;
-  GtkWindowLastGeometryInfo saved_last_info;
   GdkGeometry new_geometry;
   guint new_flags;
-  gint x, y;
-  gint width, height;
-  gint new_width, new_height;
-  gboolean need_reposition;
-  gboolean default_size_changed = FALSE;
-  gboolean hints_changed = FALSE;
-  gboolean may_shrink = window->auto_shrink;
-
-  g_return_if_fail (GTK_WIDGET_REALIZED (window));
+  GdkRectangle new_request;
+  gboolean configure_request_size_changed;
+  gboolean configure_request_pos_changed;
+  gboolean hints_changed; /* do we need to send these again */
+  GtkWindowLastGeometryInfo saved_last_info;
 
   widget = GTK_WIDGET (window);
   container = GTK_CONTAINER (widget);
   info = gtk_window_get_geometry_info (window, TRUE);
-  saved_last_info = info->last;
 
-  gtk_widget_size_request (widget, NULL);
-  gtk_window_compute_default_size (window, &new_width, &new_height);
+  configure_request_size_changed = FALSE;
+  configure_request_pos_changed = FALSE;
   
-  if (info->last.width < 0 ||
-      info->last.width != new_width ||
-      info->last.height != new_height)
-    {
-      default_size_changed = TRUE;
-      may_shrink |= info->may_shrink;
-      info->last.width = new_width;
-      info->last.height = new_height;
+  gtk_window_compute_configure_request (window, &new_request,
+                                        &new_geometry, &new_flags);  
 
-      /* We need to force a reposition in this case
+  /* This check implies the invariant that we never set info->last
+   * without setting the hints and sending off a configure request.
+   *
+   * If we change info->last without sending the request, we may
+   * miss a request.
        */
-      if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
-	window->use_uposition = TRUE;
-    }
-  info->may_shrink = FALSE;
+  if (info->last.configure_request.x != new_request.x ||
+      info->last.configure_request.y != new_request.y)
+    configure_request_pos_changed = TRUE;
+
+  /* To change, we must be different from BOTH the last request, and
+   * also our current size as received from the most recent configure
+   * notify.
+   *
+   * If different from last request, it means some sizing
+   * parameters have changed; but one possible such sizing
+   * parameter could be the current size.
+   *
+   * We never want to re-request our current size, because that could
+   * lead to some strange infinite loops if a window manager did
+   * something insane but ICCCM-compliant such as add 2 to all
+   * requested sizes. (i.e. if the WM always assigned a size that
+   * was a function of the requested size, rather than a constraint
+   * applied to requested size - so that requesting current size
+   * did not result in getting that size back)
+   *
+   * So here we detect and prevent any attempt to set size
+   * to current size.
+   *
+   * (FIXME I think some race may be possible here, but
+   *  perhaps avoided by configure_request_count?)
+   */
+  if ((info->last.configure_request.width != new_request.width ||
+       info->last.configure_request.height != new_request.height) &&
+      (widget->allocation.width != new_request.width ||
+       widget->allocation.height != new_request.height))
+    configure_request_size_changed = TRUE;
   
-  /* Compute new set of hints for the window
+  /*
+   * Position Constraints
+   * ====================
+   * 
+   * POS_CENTER_ALWAYS is conceptually a constraint rather than
+   * a default. The other POS_ values are used only when the
+   * window is shown, not after that.
+   * 
+   * However, we can't implement a position constraint as
+   * "anytime the window size changes, center the window"
+   * because this may well end up fighting the WM or user.  In
+   * fact it gets in an infinite loop with at least one WM.
+   *
+   * Basically, applications are in no way in a position to
+   * constrain the position of a window, with one exception:
+   * override redirect windows. (Really the intended purpose
+   * of CENTER_ALWAYS anyhow, I would think.)
+   *
+   * So the way we implement this "constraint" is to say that when WE
+   * cause a move or resize, i.e. we make a configure request changing
+   * window size, we recompute the CENTER_ALWAYS position to reflect
+   * the new window size, and include it in our request.  Also, if we
+   * just turned on CENTER_ALWAYS we snap to center with a new
+   * request.  Otherwise, if we are just NOTIFIED of a move or resize
+   * done by someone else e.g. the window manager, we do NOT send a
+   * new configure request.
+   *
+   * For override redirect windows, this works fine; all window
+   * sizes are from our configure requests. For managed windows,
+   * it is at least semi-sane, though who knows what the
+   * app author is thinking.
    */
-  gtk_window_compute_hints (window, &new_geometry, &new_flags);
+
+  if (configure_request_pos_changed ||
+      configure_request_size_changed ||
+      info->position_constraints_changed)
+    {
+      /* We request the constrained position if:
+       *  - we were changing position, and need to clamp
+       *    the change to the constraint
+       *  - we're changing the size anyway
+       *  - set_position() was called to toggle CENTER_ALWAYS on
+       */
+
+      gtk_window_constrain_position (window,
+                                     new_request.width,
+                                     new_request.height,
+                                     &new_request.x,
+                                     &new_request.y);
+      
+      /* Update whether we need to request a move */
+      if (info->last.configure_request.x != new_request.x ||
+          info->last.configure_request.y != new_request.y)
+        configure_request_pos_changed = TRUE;
+      else
+        configure_request_pos_changed = FALSE;
+    }
+  
+  hints_changed = FALSE;
+  
   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
 				 &new_geometry, new_flags))
     {
       hints_changed = TRUE;
+    }
+
+#if 0
+  g_print ("--- %s ---\n"
+           "last : %d,%d\t%d x %d\n"
+           "this : %d,%d\t%d x %d\n"
+           "alloc: %d,%d\t%d x %d\n"
+           "req  :      \t%d x %d\n"
+           "size_changed: %d pos_changed: %d hints_changed: %d\n"
+           "configure_notify_received: %d\n"
+           "configure_request_count: %d\n"
+           "position_constraints_changed: %d\n",
+           window->title ? window->title : "(no title)",
+           info->last.configure_request.x,
+           info->last.configure_request.y,
+           info->last.configure_request.width,
+           info->last.configure_request.height,
+           new_request.x,
+           new_request.y,
+           new_request.width,
+           new_request.height,
+           widget->allocation.x,
+           widget->allocation.y,
+           widget->allocation.width,
+           widget->allocation.height,
+           widget->requisition.width,
+           widget->requisition.height,
+           configure_request_pos_changed,
+           configure_request_size_changed,
+           hints_changed,
+           window->configure_notify_received,
+           window->configure_request_count,
+           info->position_constraints_changed);
+#endif
+  
+  saved_last_info = info->last;
       info->last.geometry = new_geometry;
       info->last.flags = new_flags;
-    }
+  info->last.configure_request = new_request;
 
-  /* From the default size and the allocation, figure out the size
-   * the window should be.
+  /* need to set PPosition so the WM will look at our position,
+   * but we don't want to count PPosition coming and going as a hints
+   * change for future iterations. So we saved info->last prior to
+   * this.
    */
-  if (!default_size_changed ||
-      (!may_shrink &&
-       new_width <= widget->allocation.width &&
-       new_height <= widget->allocation.height))
-    {
-      new_width = widget->allocation.width;
-      new_height = widget->allocation.height;
-    }
 
-  /* constrain the window size to the specified geometry */
-  gtk_window_constrain_size (window,
-			     &new_geometry, new_flags,
-			     new_width, new_height,
-			     &new_width, &new_height);
+  /* Also, if the initial position was explicitly set, then we always
+   * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
+   * work.
+   */
 
-  /* compute new window position if a move is required
+  /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
+   * this is an initial map
    */
-  need_reposition = gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
-  if (need_reposition && !(new_flags & GDK_HINT_POS))
+  
+  if ((configure_request_pos_changed ||
+       info->initial_pos_set ||
+       (window->need_default_position &&
+        window->position != GTK_WIN_POS_NONE)) &&
+      (new_flags & GDK_HINT_POS) == 0)
     {
       new_flags |= GDK_HINT_POS;
       hints_changed = TRUE;
     }
-
 
-  /* handle actual resizing:
-   * - handle reallocations due to configure events
-   * - figure whether we need to request a new window size
-   * - handle simple resizes within our widget tree
-   * - reposition window if neccessary
+  /* Set hints if necessary
    */
-  width = widget->allocation.width;
-  height = widget->allocation.height;
+  if (hints_changed)
+    gdk_window_set_geometry_hints (widget->window,
+				   &new_geometry,
+				   new_flags);
 
-  if (window->handling_resize)
+  if (window->configure_notify_received)
     { 
       GtkAllocation allocation;
       
-      /* if we are just responding to a configure event, which
-       * might be due to a resize by the window manager, the
-       * user, or a response to a resizing request we made
-       * earlier, we go ahead, allocate the new size and we're done
+      /* If we have received a configure event since
+       * the last time in this function, we need to
+       * accept our new size and size_allocate child widgets.
        * (see gtk_window_configure_event() for more details).
+       *
+       * 1 or more configure notifies may have been received.
+       * Also, configure_notify_received will only be TRUE
+       * if all expected configure notifies have been received
+       * (one per configure request), as an optimization.
+       *
        */
       
-      window->handling_resize = FALSE;
+      window->configure_notify_received = FALSE;
       
+      /* gtk_window_configure_event() filled in widget->allocation */
       allocation = widget->allocation;
       
       gtk_widget_size_allocate (widget, &allocation);
       gtk_widget_queue_draw (widget);
 
-      if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
-	{
-	  /* We could be here for two reasons
-	   *  1) We coincidentally got a resize while handling
-	   *     another resize.
-	   *  2) Our computation of default_size_changed was completely
-	   *     screwed up, probably because one of our children
-	   *     is changed requisition during size allocation).
+      /* If the configure request changed, it means that
+       * we either:
+       *   1) coincidentally changed hints or widget properties
+       *      impacting the configure request before getting
+       *      a configure notify
+       *  or
+       *   2) some broken widget is changing its size request
+       *      during size allocation, resulting in
+       *      a false appearance of changed configure request.
 	   *
 	   * For 1), we could just go ahead and ask for the
 	   * new size right now, but doing that for 2)
@@ -2810,108 +3701,121 @@ gtk_window_move_resize (GtkWindow *windo
 	   * hurt us too badly, since it is what would have
 	   * happened if we had gotten the configure event before
 	   * the new size had been set.
+       * 
 	   */
 	  
-	  if (need_reposition)
+      if (configure_request_size_changed ||
+          configure_request_pos_changed)
 	    {
-	      if (window->frame)
-		gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
-	      else
-		gdk_window_move (GTK_WIDGET (window)->window, x, y);
-	    }
-
-	  /* we have to preserve the values and flags that are used
-	   * for computation of default_size_changed and hints_changed
+          /* Don't change the recorded last info after all, because we
+           * haven't actually updated to the new info yet - we decided
+           * to postpone our configure request until later.
 	   */
+          
 	  info->last = saved_last_info;
 	  
 	  gtk_widget_queue_resize (widget);
-
-	  return;
 	}
     }
-
-  /* Now set hints if necessary
-   */
-  if (hints_changed)
-    gdk_window_set_geometry_hints (widget->window,
-				   &new_geometry,
-				   new_flags);
-
-  if ((default_size_changed || hints_changed) &&
-      (width != new_width || height != new_height))
+  else if (configure_request_pos_changed ||
+           configure_request_size_changed ||
+           hints_changed)
     {
-      /* given that (width != new_width || height != new_height), we are in one
-       * of the following situations:
+      /* We are in one of the following situations with
+       * respect to the window size:
        * 
-       * default_size_changed
+       * A. configure_request_size_changed
        *   our requisition has changed and we need a different window size,
        *   so we request it from the window manager.
        *
-       * !default_size_changed
+       * B. !configure_request_size_changed
        *   the window manager wouldn't assign us the size we requested, in this
        *   case we don't try to request a new size with every resize.
        *
-       * !default_size_changed && hints_changed
+       * C. !configure_request_size_changed && hints_changed
        *   the window manager rejects our size, but we have just changed the
        *   window manager hints, so there's a certain chance our request will
        *   be honoured this time, so we try again.
        */
+
+      /* Compress case C into case A */
+      if (hints_changed)
+        configure_request_size_changed = TRUE;
       
-      /* request a new window size */
-      if (need_reposition)
+      g_assert (configure_request_size_changed ||
+                configure_request_pos_changed);
+      
+      /* Now send the configure request */
+
+      if (configure_request_pos_changed)
 	{
 	  if (window->frame)
 	    {
 	      gdk_window_move_resize (window->frame,
-				      x - window->frame_left, y - window->frame_top,
-				      new_width + window->frame_left + window->frame_right,
-				      new_height + window->frame_top + window->frame_bottom);
-	      gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+				      new_request.x - window->frame_left,
+                                      new_request.y - window->frame_top,
+				      new_request.width + window->frame_left + window->frame_right,
+				      new_request.height + window->frame_top + window->frame_bottom);
+	      gdk_window_resize (GTK_WIDGET (window)->window,
+                                 new_request.width, new_request.height);
 	    }
 	  else
-	    gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
+	    gdk_window_move_resize (widget->window,
+                                    new_request.x, new_request.y,
+                                    new_request.width, new_request.height);
 	}
       else
 	{
+          /* only size changed */
+          
 	  if (window->frame)
 	    gdk_window_resize (window->frame,
-			       new_width + window->frame_left + window->frame_right,
-			       new_height + window->frame_top + window->frame_bottom);
-	  gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+			       new_request.width + window->frame_left + window->frame_right,
+			       new_request.height + window->frame_top + window->frame_bottom);
+
+	  gdk_window_resize (widget->window,
+                             new_request.width, new_request.height);
 	}
-      window->resize_count += 1;
       
-      /* we are now awaiting the new configure event in response to our
+      /* Increment the number of have-not-yet-received-notify requests */
+      window->configure_request_count += 1;
+
+      /* We have now sent a request since the last position constraint
+       * change
+       */
+      info->position_constraints_changed = FALSE;
+      
+      /* we are now awaiting the new configure notify event in response to our
        * resizing request. the configure event will cause a new resize
-       * with ->handling_resize=TRUE.
+       * with ->configure_notify_received=TRUE.
        * until then, we want to
        * - discard expose events
        * - coalesce resizes for our children
        * - defer any window resizes until the configure event arrived
-       * to achive this, we queue a resize for the window, but remove its
+       * to achieve this, we queue a resize for the window, but remove its
        * resizing handler, so resizing will not be handled from the next
        * idle handler but when the configure event arrives.
        *
        * FIXME: we should also dequeue the pending redraws here, since
-       * we handle those ourselves in ->handling_resize==TRUE.
+       * we handle those ourselves in ->configure_notify_received==TRUE.
+       *
+       * FIXME: not sure the above FIXME is correct, because we only
+       * queue draw in size allocate if the size actually changes,
+       * so if the update area for the window contains stuff
+       * unrelated to sizing (should be rare actually) then we
+       * might lose that info.
        */
-      gtk_widget_queue_resize (GTK_WIDGET (container));
+      gtk_widget_queue_resize (widget);
       if (container->resize_mode == GTK_RESIZE_QUEUE)
 	_gtk_container_dequeue_resize_handler (container);
     }
   else
-    {
-      if (need_reposition)
 	{
-	  if (window->frame)
-	    gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
-	  else
-	    gdk_window_move (widget->window, x, y);
-	}
-
+      /* Not requesting anything new from WM, just had a queue resize
+       * for some reason, so handle the resize queue
+       */
       if (container->resize_widgets)
-	gtk_container_resize_children (GTK_CONTAINER (window));
+        gtk_container_resize_children (container);
     }
 }
 
@@ -2958,40 +3862,6 @@ gtk_window_compare_hints (GdkGeometry *g
   return TRUE;
 }
 
-/* Compute the default_size for a window. The result will
- * be stored in *width and *height. The default size is
- * the size the window should have when initially mapped.
- * This routine does not attempt to constrain the size
- * to obey the geometry hints - that must be done elsewhere.
- */
-static void 
-gtk_window_compute_default_size (GtkWindow       *window,
-				 guint           *width,
-				 guint           *height)
-{
-  GtkRequisition requisition;
-  GtkWindowGeometryInfo *info;
-  
-  gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
-  *width = requisition.width;
-  *height = requisition.height;
-
-  info = gtk_window_get_geometry_info (window, FALSE);
-  
-  if (*width == 0 && *height == 0)
-    {
-      /* empty window */
-      *width = 200;
-      *height = 200;
-    }
-  
-  if (info)
-    {
-      *width = info->width > 0 ? info->width : *width;
-      *height = info->height > 0 ? info->height : *height;
-    }
-}
-
 void
 _gtk_window_constrain_size (GtkWindow   *window,
 			    gint         width,
@@ -3043,8 +3913,6 @@ gtk_window_compute_hints (GtkWindow   *w
 			  guint       *new_flags)
 {
   GtkWidget *widget;
-  GtkWidgetAuxInfo *aux_info;
-  gint ux, uy;
   gint extra_width = 0;
   gint extra_height = 0;
   GtkWindowGeometryInfo *geometry_info;
@@ -3056,28 +3924,27 @@ gtk_window_compute_hints (GtkWindow   *w
   
   gtk_widget_get_child_requisition (widget, &requisition);
   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
-
-  g_return_if_fail (geometry_info != NULL);
   
+  if (geometry_info)
+    {
   *new_flags = geometry_info->mask;
   *new_geometry = geometry_info->geometry;
+    }
+  else
+    {
+      *new_flags = 0;
+    }
   
-  if (geometry_info->widget)
+  if (geometry_info && geometry_info->widget)
     {
       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;
-    }
+  /* We don't want to set GDK_HINT_POS in here, we just set it
+   * in gtk_window_move_resize() when we want the position
+   * honored.
+   */
   
   if (*new_flags & GDK_HINT_BASE_SIZE)
     {
@@ -3102,7 +3969,7 @@ gtk_window_compute_hints (GtkWindow   *w
 	new_geometry->min_width += extra_width;
 
       if (new_geometry->min_height < 0)
-	new_geometry->min_width = requisition.height;
+	new_geometry->min_height = requisition.height;
       else
 	new_geometry->min_height += extra_height;
     }
@@ -3138,106 +4005,6 @@ gtk_window_compute_hints (GtkWindow   *w
   new_geometry->win_gravity = window->gravity;
 }
 
-/* Compute a new position for the window based on a new
- * size. *x and *y will be set to the new coordinates. Returns
- * TRUE if the window needs to be moved (and thus x and y got
- * assigned)
- */
-static gint
-gtk_window_compute_reposition (GtkWindow *window,
-			       gint       new_width,
-			       gint       new_height,
-			       gint      *x,
-			       gint      *y)
-{
-  GtkWidget *widget = GTK_WIDGET (window);
-  GtkWindowPosition pos;
-  GtkWidget *parent_widget;
-  gboolean needs_move = FALSE;
-
-  parent_widget = (GtkWidget*) window->transient_parent;
-  
-  pos = window->position;
-  if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
-      (parent_widget == NULL ||
-       !GTK_WIDGET_MAPPED (parent_widget)))
-    pos = GTK_WIN_POS_NONE;
-  
-  switch (pos)
-  {
-    case GTK_WIN_POS_CENTER:
-    case GTK_WIN_POS_CENTER_ALWAYS:
-      if (window->use_uposition)
-	{
-	  gint screen_width = gdk_screen_width ();
-	  gint screen_height = gdk_screen_height ();
-	  
-	  *x = (screen_width - new_width) / 2;
-	  *y = (screen_height - new_height) / 2;
-	  needs_move = TRUE;
-	}
-      break;
-
-    case GTK_WIN_POS_CENTER_ON_PARENT:
-      if (window->use_uposition)
-        {
-          gint ox, oy;
-	  gdk_window_get_origin (parent_widget->window,
-				   &ox, &oy);
-                                 
-          *x = ox + (parent_widget->allocation.width - new_width) / 2;
-          *y = oy + (parent_widget->allocation.height - new_height) / 2;
-	  needs_move = TRUE;
-	}
-      break;
-
-    case GTK_WIN_POS_MOUSE:
-      if (window->use_uposition)
-	{
-	  gint screen_width = gdk_screen_width ();
-	  gint screen_height = gdk_screen_height ();
-	  
-	  gdk_window_get_pointer (NULL, x, y, NULL);
-	  *x -= new_width / 2;
-	  *y -= new_height / 2;
-	  *x = CLAMP (*x, 0, screen_width - new_width);
-	  *y = CLAMP (*y, 0, screen_height - new_height);
-	  needs_move = TRUE;
-	}
-      break;
-    default:
-      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;
-	    }
-	}
-      break;
-    }
-
-  if (needs_move)
-    {
-      GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE);
-
-      /* we handle necessary window positioning by hand here,
-       * so we can coalesce the window movement with possible
-       * resizes to get only one configure event.
-       */
-      aux_info->x_set = TRUE;
-      aux_info->y_set = TRUE;
-      aux_info->x = *x;
-      aux_info->y = *y;
-      window->use_uposition = FALSE;
-    }
-
-  return needs_move;
-}
-
 /***********************
  * Redrawing functions *
  ***********************/
@@ -3668,23 +4435,12 @@ gtk_window_get_resizable (GtkWindow *win
  * @window: a #GtkWindow
  * @gravity: window gravity
  *
- * Window gravity defines the "reference point" to be used when
- * positioning or resizing a window. Calls to
- * gtk_widget_set_uposition() will position a different point on the
- * window depending on the window gravity. When the window changes size
- * the reference point determined by the window's gravity will stay in
- * a fixed location.
- *
- * See #GdkGravity for full details. To briefly summarize,
- * #GDK_GRAVITY_NORTH_WEST means that the reference point is the
- * northwest (top left) corner of the window
- * frame. #GDK_GRAVITY_SOUTH_EAST would be the bottom right corner of
- * the frame, and so on. If you want to position the window contents,
- * rather than the window manager's frame, #GDK_GRAVITY_STATIC moves
- * the reference point to the northwest corner of the #GtkWindow
- * itself.
+ * Window gravity defines the meaning of coordinates passed to
+ * gtk_window_move(). See gtk_window_move() and #GdkGravity for
+ * more details.
  *
- * The default window gravity is #GDK_GRAVITY_NORTH_WEST.
+ * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
+ * typically "do what you mean."
  *
  **/
 void
@@ -3973,4 +4729,287 @@ _gtk_window_get_group (GtkWindow *window
 
       return default_group;
     }
+}
+
+
+/*
+  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
+
+/* Try not to reformat/modify, so we can compare/sync with X sources */
+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);
+}
+
+/**
+ * gtk_window_parse_geometry:
+ * @window: a #GtkWindow
+ * @geometry: geometry string
+ * 
+ * Parses a standard X Window System geometry string - see the
+ * manual page for X (type 'man X') for details on this.
+ * gtk_window_parse_geometry() does work on all GTK+ ports
+ * including Win32 but is primarily intended for an X environment.
+ *
+ * If either a size or a position can be extracted from the
+ * geometry string, gtk_window_parse_geometry() returns %TRUE
+ * and calls gtk_window_set_default_size() and/or gtk_window_move()
+ * to resize/move the window.
+ *
+ * If gtk_window_parse_geometry() returns %TRUE, it will also
+ * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
+ * indicating to the window manager that the size/position of
+ * the window was user-specified. This causes most window
+ * managers to honor the geometry.
+ * 
+ * Return value: %TRUE if string was parsed successfully
+ **/
+gboolean
+gtk_window_parse_geometry (GtkWindow   *window,
+                           const gchar *geometry)
+{
+  gint result, x, y;
+  guint w, h;
+  GdkGravity grav;
+  gboolean size_set, pos_set;
+  
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (geometry != NULL, FALSE);
+  
+  result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
+
+  if ((result & WidthValue) == 0 ||
+      w < 0)
+    w = -1;
+  if ((result & HeightValue) == 0 ||
+      h < 0)
+    h = -1;
+
+  size_set = FALSE;
+  if ((result & WidthValue) || (result & HeightValue))
+    {
+      gtk_window_set_default_size (window, w, h);
+      size_set = TRUE;
+    }
+
+  gtk_window_get_size (window, &w, &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;
+
+  if ((result & XValue) == 0)
+    x = 0;
+
+  if ((result & YValue) == 0)
+    y = 0;
+  
+  if (grav == GDK_GRAVITY_SOUTH_WEST ||
+      grav == GDK_GRAVITY_SOUTH_EAST)
+    y = gdk_screen_height () - h;
+
+  if (grav == GDK_GRAVITY_SOUTH_EAST ||
+      grav == GDK_GRAVITY_NORTH_EAST)
+    x = gdk_screen_width () - w;
+
+  if (y < 0)
+    y = 0;
+
+  if (x < 0)
+    x = 0;
+
+  pos_set = FALSE;
+  if ((result & XValue) || (result & YValue))
+    {
+      gtk_window_set_gravity (window, grav);
+      gtk_window_move (window, x, y);
+      pos_set = TRUE;
+    }
+
+  if (size_set || pos_set)
+    {
+      /* Set USSize, USPosition hints */
+      GtkWindowGeometryInfo *info;
+
+      info = gtk_window_get_geometry_info (window, TRUE);
+
+      if (pos_set)
+        info->mask |= GDK_HINT_USER_POS;
+      if (size_set)
+        info->mask |= GDK_HINT_USER_SIZE;
+    }
+  
+  return result != 0;
 }
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.45
diff -u -p -u -b -r1.45 gtkwindow.h
--- gtk/gtkwindow.h	2001/06/25 23:48:49	1.45
+++ gtk/gtkwindow.h	2001/07/04 18:29:32
@@ -69,24 +69,23 @@ struct _GtkWindow
   GdkWindow *frame;
   GtkWindowGroup *group;
 
-  guint16 resize_count;
-
-  GtkWindowType type : 4;
-  guint has_user_ref_count : 1;
-  guint has_focus : 1;
+  guint16 configure_request_count;
   guint allow_shrink : 1;
   guint allow_grow : 1;
-  guint auto_shrink : 1;
-  guint handling_resize : 1;
-  guint position : 2;
-
-  /* The following flag is initially TRUE when a window is mapped.
-   * and will be set to FALSE after it is first positioned.
-   * It is also temporarily reset when the window's size changes.
-   * 
-   * When TRUE, we move the window to the position the app set.
+  guint configure_notify_received : 1;
+  /* The following flags are initially TRUE (before a window is mapped).
+   * They cause us to compute a configure request that involves
+   * default-only parameters. Once mapped, we set them to FALSE.
+   * Then we set them to TRUE again on unmap (for position)
+   * and on unrealize (for size).
    */
-  guint use_uposition : 1;
+  guint need_default_position : 1;
+  guint need_default_size : 1;
+  guint position : 3;
+  GtkWindowType type : 4;
+  guint has_user_ref_count : 1;
+  guint has_focus : 1;
+
   guint modal : 1;
   guint destroy_with_parent : 1;
   
@@ -252,9 +251,9 @@ void       gtk_window_set_policy        
 						gint                 allow_grow,
 						gint                 auto_shrink);
 #endif
-/* The following differs from gtk_widget_set_usize, in that
- * gtk_widget_set_usize() overrides the requisition, so sets a minimum
- * size, while this only sets the size requested from the WM.
+
+/* Set initial default size of the window (does not constrain user
+ * resize operations)
  */
 void       gtk_window_set_default_size         (GtkWindow           *window,
 						gint                 width,
@@ -262,6 +261,23 @@ void       gtk_window_set_default_size  
 void       gtk_window_get_default_size         (GtkWindow           *window,
 						gint                *width,
 						gint                *height);
+void     gtk_window_resize           (GtkWindow   *window,
+                                      gint         width,
+                                      gint         height);
+void     gtk_window_get_size         (GtkWindow   *window,
+                                      gint        *width,
+                                      gint        *height);
+void     gtk_window_move             (GtkWindow   *window,
+                                      gint         x,
+                                      gint         y);
+void     gtk_window_get_position     (GtkWindow   *window,
+                                      gint        *x,
+                                      gint        *y);
+gboolean gtk_window_parse_geometry   (GtkWindow   *window,
+                                      const gchar *geometry);
+
+/* Ignore this unless you are writing a GUI builder */
+void     gtk_window_reshow_with_initial_size (GtkWindow *window);
 
 /* Window groups
  */
Index: tests/testgtk.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testgtk.c,v
retrieving revision 1.267
diff -u -p -u -b -r1.267 testgtk.c
--- tests/testgtk.c	2001/06/30 16:08:25	1.267
+++ tests/testgtk.c	2001/07/04 18:29:34
@@ -8339,16 +8339,10 @@ configure_event_callback (GtkWidget *wid
   gchar *msg;
   gint x, y;
   
-#if 0
-  /* FIXME */
-  gtk_window_get_location (GTK_WINDOW (widget), &x, &y);
-#else  
-  x = 0;
-  y = 0;
-#endif
+  gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
   
   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
-                         "location: %d, %d",
+                         "position: %d, %d",
                          event->x, event->y, event->width, event->height,
                          x, y);
   
@@ -8382,10 +8376,18 @@ set_size_callback (GtkWidget *widget,
   
   get_ints (data, &w, &h);
 
-  gtk_window_set_default_size (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
+  gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
 }
      
 static void
+unset_default_size_callback (GtkWidget *widget,
+                             gpointer   data)
+{
+  gtk_window_set_default_size (g_object_get_data (data, "target"),
+                               -1, -1);
+}
+
+static void
 set_default_size_callback (GtkWidget *widget,
                            gpointer   data)
 {
@@ -8398,6 +8400,14 @@ set_default_size_callback (GtkWidget *wi
 }
 
 static void
+unset_usize_callback (GtkWidget *widget,
+                      gpointer   data)
+{
+  gtk_widget_set_size_request (g_object_get_data (data, "target"),
+                               -1, -1);
+}
+
+static void
 set_usize_callback (GtkWidget *widget,
                     gpointer   data)
 {
@@ -8405,7 +8415,7 @@ set_usize_callback (GtkWidget *widget,
   
   get_ints (data, &w, &h);
 
-  gtk_widget_set_usize (g_object_get_data (data, "target"),
+  gtk_widget_set_size_request (g_object_get_data (data, "target"),
                         w, h);
 }
 
@@ -8417,10 +8427,24 @@ set_location_callback (GtkWidget *widget
   
   get_ints (data, &x, &y);
 
-  gtk_widget_set_uposition (g_object_get_data (data, "target"), x, y);
+  gtk_window_move (g_object_get_data (data, "target"), x, y);
 }
 
 static void
+move_to_position_callback (GtkWidget *widget,
+                           gpointer   data)
+{
+  gint x, y;
+  GtkWindow *window;
+
+  window = g_object_get_data (data, "target");
+  
+  gtk_window_get_position (window, &x, &y);
+
+  gtk_window_move (window, x, y);
+}
+
+static void
 set_geometry_callback (GtkWidget *entry,
                        gpointer   data)
 {
@@ -8431,11 +8455,8 @@ set_geometry_callback (GtkWidget *entry,
   
   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
 
-#if 0
-  /* FIXME */
   if (!gtk_window_parse_geometry (target, text))
     g_print ("Bad geometry string '%s'\n", text);
-#endif
   
   g_free (text);
 }
@@ -8478,6 +8499,157 @@ gravity_selected (GtkWidget *widget,
                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
 }
 
+static void
+pos_selected (GtkWidget *widget,
+              gpointer   data)
+{
+  gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
+                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
+}
+
+static void
+move_gravity_window_to_current_position (GtkWidget *widget,
+                                         gpointer   data)
+{
+  gint x, y;
+  GtkWindow *window;
+
+  window = GTK_WINDOW (data);    
+  
+  gtk_window_get_position (window, &x, &y);
+
+  gtk_window_move (window, x, y);
+}
+
+static GtkWidget*
+make_gravity_window (GtkWidget   *destroy_with,
+                     GdkGravity   gravity,
+                     const gchar *title)
+{
+  GtkWidget *window;
+  GtkWidget *button;
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  
+  button = gtk_button_new_with_mnemonic ("_Move to current position");
+
+  g_signal_connect (G_OBJECT (button), "clicked",
+                    G_CALLBACK (move_gravity_window_to_current_position),
+                    window);
+  
+  gtk_widget_show (button);  
+
+  gtk_container_add (GTK_CONTAINER (window), button);
+  gtk_window_set_title (GTK_WINDOW (window), title);
+  gtk_window_set_gravity (GTK_WINDOW (window), gravity);
+
+  gtk_signal_connect_object (GTK_OBJECT (destroy_with),
+                             "destroy",
+                             GTK_SIGNAL_FUNC (gtk_widget_destroy),
+                             GTK_OBJECT (window));
+
+  /* Pretend this is the result of --geometry.
+   * DO NOT COPY THIS CODE unless you are setting --geometry results,
+   * and in that case you probably should just use gtk_window_parse_geometry()
+   */
+  gtk_window_set_geometry_hints (GTK_WINDOW (window),
+                                 NULL, NULL,
+                                 GDK_HINT_USER_POS);
+
+  gtk_window_set_default_size (GTK_WINDOW (window),
+                               200, 200);
+  
+  return window;
+}
+
+static void
+do_gravity_test (GtkWidget *widget,
+                 gpointer   data)
+{
+  GtkWidget *destroy_with = data;
+  GtkWidget *window;
+  int w, h;
+  
+  /* We put a window at each gravity point on the screen. */
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
+                                "NorthWest");
+  gtk_window_move (GTK_WINDOW (window), 0, 0);
+  gtk_widget_show (window);
+  
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
+                                "SouthEast");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   gdk_screen_width () - w,
+                   gdk_screen_height () - h);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
+                                "NorthEast");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   gdk_screen_width () - w,
+                   0);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
+                                "SouthWest");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   0,
+                   gdk_screen_height () - h);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
+                                "South");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   (gdk_screen_width () - w) / 2,
+                   gdk_screen_height () - h);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
+                                "North");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   (gdk_screen_width () - w) / 2,
+                   0);
+  gtk_widget_show (window);
+
+  
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
+                                "West");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   0,
+                   (gdk_screen_height () - h) / 2);
+  gtk_widget_show (window);
+
+    
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
+                                "East");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   gdk_screen_width () - w,
+                   (gdk_screen_height () - h) / 2);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
+                                "Center");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   (gdk_screen_width () - w) / 2,
+                   (gdk_screen_height () - h) / 2);
+  gtk_widget_show (window);
+
+  window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
+                                "Static");
+  gtk_window_get_size (GTK_WINDOW (window), &w, &h);
+  gtk_window_move (GTK_WINDOW (window),
+                   400, 400);
+  gtk_widget_show (window);
+}
+
 static GtkWidget*
 window_controls (GtkWidget *window)
 {
@@ -8517,7 +8689,7 @@ window_controls (GtkWidget *window)
                       GTK_SIGNAL_FUNC (configure_event_callback),
                       label);
 
-  adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -3.0, 800.0, 1.0,
+  adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
                                               5.0, 0.0);
   spin = gtk_spin_button_new (adj, 0, 0);
 
@@ -8525,7 +8697,7 @@ window_controls (GtkWidget *window)
 
   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
 
-  adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -3.0, 800.0, 1.0,
+  adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
                                               5.0, 0.0);
   spin = gtk_spin_button_new (adj, 0, 0);
 
@@ -8540,14 +8712,28 @@ window_controls (GtkWidget *window)
                       GTK_SIGNAL_FUNC (set_geometry_callback),
                       control_window);
   
+  button = gtk_button_new_with_label ("Show gravity test windows");
+  gtk_signal_connect_object (GTK_OBJECT (button),
+                             "clicked",
+                             GTK_SIGNAL_FUNC (do_gravity_test),
+                             control_window);
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_label ("Reshow with initial size");
+  gtk_signal_connect_object (GTK_OBJECT (button),
+                             "clicked",
+                             GTK_SIGNAL_FUNC (gtk_window_reshow_with_initial_size),
+                             GTK_OBJECT (window));
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  
   button = gtk_button_new_with_label ("Queue resize");
   gtk_signal_connect_object (GTK_OBJECT (button),
                              "clicked",
                              GTK_SIGNAL_FUNC (gtk_widget_queue_resize),
-                             GTK_OBJECT (control_window));
+                             GTK_OBJECT (window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
   
-  button = gtk_button_new_with_label ("Set size");
+  button = gtk_button_new_with_label ("Resize");
   gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_size_callback),
@@ -8561,20 +8747,41 @@ window_controls (GtkWidget *window)
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
-  button = gtk_button_new_with_label ("Set usize");
+  button = gtk_button_new_with_label ("Unset default size");
   gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
+                      GTK_SIGNAL_FUNC (unset_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 size request");
+  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 ("Unset size request");
+  gtk_signal_connect (GTK_OBJECT (button),
+                      "clicked",
+                      GTK_SIGNAL_FUNC (unset_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");
+  button = gtk_button_new_with_label ("Move");
   gtk_signal_connect (GTK_OBJECT (button),
                       "clicked",
                       GTK_SIGNAL_FUNC (set_location_callback),
                       GTK_OBJECT (control_window));
   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
+  button = gtk_button_new_with_label ("Move to current position");
+  gtk_signal_connect (GTK_OBJECT (button),
+                      "clicked",
+                      GTK_SIGNAL_FUNC (move_to_position_callback),
+                      GTK_OBJECT (control_window));
+  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  
   button = gtk_check_button_new_with_label ("Allow shrink");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
   gtk_signal_connect (GTK_OBJECT (button),
@@ -8655,6 +8862,44 @@ window_controls (GtkWidget *window)
 
   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
   
+
+  menu = gtk_menu_new ();
+  
+  i = 0;
+  while (i < 5)
+    {
+      GtkWidget *mi;
+      static gchar *names[] = {
+        "GTK_WIN_POS_NONE",
+        "GTK_WIN_POS_CENTER",
+        "GTK_WIN_POS_MOUSE",
+        "GTK_WIN_POS_CENTER_ALWAYS",
+        "GTK_WIN_POS_CENTER_ON_PARENT",
+        NULL
+      };
+
+      g_assert (names[i]);
+      
+      mi = gtk_menu_item_new_with_label (names[i]);
+
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+
+      ++i;
+    }
+  
+  gtk_widget_show_all (menu);
+  
+  om = gtk_option_menu_new ();
+  gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
+  
+
+  gtk_signal_connect (GTK_OBJECT (om),
+                      "changed",
+                      GTK_SIGNAL_FUNC (pos_selected),
+                      control_window);
+
+  gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
+  
   gtk_widget_show_all (vbox);
   
   return control_window;
@@ -8664,27 +8909,36 @@ void
 create_window_sizing (void)
 {
   static GtkWidget *window = NULL;
+  static GtkWidget *target_window = NULL;
   
-  if (!window)
+  if (!target_window)
     {
       GtkWidget *label;
       
-      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
       label = gtk_label_new (NULL);
       gtk_label_set_markup (GTK_LABEL (label), "<span foreground=\"purple\"><big>Window being resized</big></span>\nBlah blah blah blah\nblah blah blah\nblah blah blah blah blah");
-      gtk_container_add (GTK_CONTAINER (window), label);
+      gtk_container_add (GTK_CONTAINER (target_window), label);
       gtk_widget_show (label);
       
+      gtk_signal_connect (GTK_OBJECT (target_window), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+			  &target_window);
+
+      window = window_controls (target_window);
+      
       gtk_signal_connect (GTK_OBJECT (window), "destroy",
-			  GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
 			  &window);
-
-      gtk_window_set_title (GTK_WINDOW (window), "Window to size");
 
-      gtk_widget_show (window_controls (window));
+      gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
     }
 
+  /* don't show target window by default, we want to allow testing
+   * of behavior on first show.
+   */
+  
   if (!GTK_WIDGET_VISIBLE (window))
     gtk_widget_show (window);
   else




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