window sizing patch
- From: Havoc Pennington <hp redhat com>
- To: gtk-devel-list gnome org
- Cc: timj gtk org
- Subject: window sizing patch
- Date: 06 Aug 2001 14:58:32 -0400
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]