Re: partial window position/size patch
- From: Tim Janik <timj gtk org>
- To: Havoc Pennington <hp redhat com>
- Cc: Gtk+ Developers <gtk-devel-list gnome org>
- Subject: Re: partial window position/size patch
- Date: Thu, 22 Mar 2001 17:12:26 +0100 (CET)
On 14 Mar 2001, Havoc Pennington wrote:
>
> Hi,
>
> Here's an initial cut at this patch.
>
> gtk_window_set_default_size() is changed to a) always work after
> mapping the window and b) have a new name, gtk_window_set_size(). The
> old name still exists for backward compat.
>
> gtk_window_set_policy() is also deprecated, in favor of
> gtk_window_set_resizeable(), because only 2 of the 8 possible policies
> made any sense.
i'm not sure which 2 possibilities you mean. granted, not all possibilities
are usable on a day-to-day basis, but that doesn't mean we should get
completely rid of them. that said, i don't really object to not recommend
usage of this function (at least for normal dialogs) but i'm definitely
opposed to deprecate it in the sense of "this function is scheduled for
removal in a future version".
> The rest of the rationale is in my previous mail on this topic.
>
> I haven't yet implemented gtk_window_set_frame_size(),
> gtk_window_get_frame_size(), or the functions to get desktop/workspace
> extents.
>
> Havoc
>
> +/**
> + * gdk_window_get_origin:
> + * @window: a #GdkWindow
> + * @x: return location for X coordinate
> + * @y: return location for Y coordinate
> + *
> + * Obtains the position of a window in root window coordinates.
> + * (Compare with gdk_window_get_position() and
> + * gdk_window_get_geometry() which return the position of a window
> + * relative to its parent window.)
> + *
> + * Return value: not meaningful, ignore
> + **/
> gint
> gdk_window_get_origin (GdkWindow *window,
> gint *x,
> @@ -1641,6 +1655,21 @@
> return return_val;
> }
>
> +/**
> + * gdk_window_get_deskrelative_origin:
> + * @window: a #GdkWindow
> + * @x: return location for X coordinate
> + * @y: return location for Y coordinate
> + *
> + * This gets the origin of a #GdkWindow relative to
> + * an Enlightenment-window-manager desktop. As long as you don't
> + * assume that the user's desktop/workspace covers the entire
> + * root window (i.e. you don't assume that the desktop begins
> + * at root window coordinate 0,0) this function is not necessary.
> + * It's deprecated for that reason.
i'd go to the extend to fully remove this. for 1.2 we left it in place
because we had no wm-spec back then, and ENLIGHTENMENT_DESKTOP was the
only property that could indicate a virtual root window.
with the new wm-spec at hand, that logic should move into
gdk_window_get_root_origin() (unfortunately the new wm-spec doesn't
specify a _NET_VIRTUAL_ROOT property on those windows, but it comes
with a _NET_VIRTUAL_ROOTS list of virtual root window IDs that can be
used instead).
> +/**
> + * gdk_window_get_frame_extents:
> + * @window: a #GdkWindow
> + * @rect: rectangle to fill with bounding box of the window frame
> + *
> + * Obtains the bounding box of the window, including window manager
> + * titlebar/borders if any. The frame position is given in root window
> + * coordinates. To get the position of the window itself (rather than
> + * the frame) in root window coordinates, use gdk_window_get_origin().
> + *
> + **/
> +void
> +gdk_window_get_frame_extents (GdkWindow *window,
> + GdkRectangle *rect)
> +{
> GdkWindowObject *private;
> Window xwindow;
> Window xparent;
> @@ -1717,15 +1784,16 @@
> Window *children;
> unsigned int nchildren;
>
> - g_return_if_fail (window != NULL);
> g_return_if_fail (GDK_IS_WINDOW (window));
> + g_return_if_fail (rect != NULL);
>
> private = (GdkWindowObject*) window;
> - if (x)
> - *x = 0;
> - if (y)
> - *y = 0;
> -
> +
> + rect->x = 0;
> + rect->y = 0;
> + rect->width = 1;
> + rect->height = 1;
> +
> if (GDK_WINDOW_DESTROYED (window))
> return;
>
> @@ -1755,10 +1823,10 @@
>
> if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
> {
> - if (x)
> - *x = wx;
> - if (y)
> - *y = wy;
> + rect->x = wx;
> + rect->y = wy;
> + rect->width = ww;
> + rect->height = wh;
without evaluating _NET_VIRTUAL_ROOTS this will yield bogus
results for window managers using virtual root windows.
> }
> }
> }
> Index: gtk/gtkwindow.c
> ===================================================================
> RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
> retrieving revision 1.104
> diff -u -u -r1.104 gtkwindow.c
> --- gtk/gtkwindow.c 2001/03/12 21:01:53 1.104
> +++ gtk/gtkwindow.c 2001/03/14 21:19:48
> @@ -76,7 +76,7 @@
> PROP_DEFAULT_WIDTH,
> PROP_DEFAULT_HEIGHT,
> PROP_DESTROY_WITH_PARENT,
> -
> +
> LAST_ARG
> };
>
> @@ -93,7 +93,7 @@
> GdkGeometry geometry; /* Geometry hints */
> GdkWindowHints mask;
> GtkWidget *widget; /* subwidget to which hints apply */
> - gint width; /* Default size */
> + gint width; /* gtk_window_set_default_size () */
> gint height;
>
> GtkWindowLastGeometryInfo last;
> @@ -406,6 +406,7 @@
> window->frame_top = 0;
> window->frame_bottom = 0;
> window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
> + window->gravity = GDK_GRAVITY_NORTH_WEST;
> window->decorated = TRUE;
>
> gtk_widget_ref (GTK_WIDGET (window));
> @@ -1334,7 +1335,23 @@
> if (height >= 0)
> g_object_notify (G_OBJECT (window), "height");
>
> - gtk_widget_queue_resize (GTK_WIDGET (window));
> + if (GTK_WIDGET_REALIZED (window) && window->allow_grow)
> + {
> + /* Resize as if the user had resized */
> + GdkGeometry new_geometry;
> + GdkWindowHints new_flags;
> +
> + gtk_window_compute_hints (window, &new_geometry, &new_flags);
> + gtk_window_constrain_size (window,
> + &new_geometry, new_flags,
> + width, height,
> + &width, &height);
> +
> + gdk_window_resize (GTK_WIDGET (window)->window,
> + width, height);
> + }
> + else
> + gtk_widget_queue_resize (GTK_WIDGET (window));
you shouldn't change the window size behind gtk_window_move_resize()'
back, the default size and changes thereof are taken care of by that
function, so just leave gtk_widget_queue_resize() here.
> }
>
> static void
> @@ -2324,10 +2341,10 @@
> /* From the default size and the allocation, figure out the size
> * the window should be.
> */
> - if (!default_size_changed ||
> - (!window->auto_shrink &&
> - new_width <= widget->allocation.width &&
> - new_height <= widget->allocation.height))
> + if (!window->auto_shrink &&
> + (!default_size_changed ||
> + (new_width <= widget->allocation.width &&
> + new_height <= widget->allocation.height)))
> {
> new_width = widget->allocation.width;
> new_height = widget->allocation.height;
what? this is completely bogus, with your code auto_shrink means
to always keep the old size. you break auto_shrink with this.
there's nothing wrong with the old version, so leave it.
> @@ -2546,6 +2563,10 @@
> geometry_a->height_inc != geometry_b->height_inc))
> return FALSE;
>
> + if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
> + (geometry_a->win_gravity != geometry_b->win_gravity))
> + return FALSE;
> +
> return TRUE;
> }
>
> @@ -2830,6 +2851,9 @@
> new_geometry->max_width = requisition.width;
> new_geometry->max_height = requisition.height;
> }
> +
> + *new_flags |= GDK_HINT_WIN_GRAVITY;
> + new_geometry->win_gravity = window->gravity;
> }
>
> /* Compute a new position for the window based on a new
> @@ -3306,7 +3330,352 @@
> }
>
>
> +/**
> + * gtk_window_set_resizeable:
> + * @window: a #GtkWindow
> + * @setting: %TRUE if the user can resize this window
> + *
> + * Toggles whether the user can resize a window. Windows are user resizeable
> + * by default.
> + *
> + **/
> +void
> +gtk_window_set_resizeable (GtkWindow *window,
> + gboolean setting)
> +{
> + g_return_if_fail (GTK_IS_WINDOW (window));
> +
> + if (setting)
> + gtk_window_set_policy (window, FALSE, TRUE, FALSE);
> + else
> + gtk_window_set_policy (window, FALSE, FALSE, TRUE);
i don't think auto_shrink=TRUE is a good policy for non-resizable
windows. unless you have a temporary grab assisting dialog that the
user can't get a handle of any way, auto_shrink is pretty bogus.
but then, since you broke actuall auto_shrink behaviour in
gtk_window_move_resize(), i'm not sure how you intended things here.
anyways, i'd have expected something like:
if (allow_resizes)
gtk_window_set_policy (window, FALSE, TRUE, FALSE);
else
gtk_window_set_policy (window, FALSE, FALSE, FALSE);
> +}
> +
> +/**
> + * gtk_window_get_resizeable:
> + * @window: a #GtkWindow
> + *
> + * Gets the value set by gtk_window_set_resizeable().
> + *
> + * Return value: %TRUE if the user can resize the window
> + **/
> +gboolean
> +gtk_window_get_resizeable (GtkWindow *window)
> +{
> + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
> +
> + /* allow_grow is most likely to indicate the semantic concept we
> + * mean by "resizeable" (and will be a reliable indicator if
> + * set_policy() hasn't been called)
> + */
> + return window->allow_grow;
> +}
> +/**
> + * gtk_window_set_size:
> + * @window: a #GtkWindow
> + * @width: width, or -1 to use the default width
> + * @height: height, or -1 to use the default height
> + *
> + * Sets the size of @window, but only works for resizeable windows
> + * (see gtk_window_set_resizeable()). Setting the size emulates a user
> + * resize operation. Therefore, setting the size less than the minimum
> + * size for the window will simply make the window its minimum size,
> + * and the user will be able to change the size that's set.
> + *
> + * This call also sets the default size of the window, so replaces
> + * gtk_window_set_default_size().
> + *
> + * To set a minimum size, or to set the size of a non-resizeable window,
> + * use gtk_widget_set_usize() on the window. Though normally it makes
> + * more sense to instead call gtk_widget_set_usize() on a child widget inside
> + * the window, rather than the window itself.
> + *
> + * Under the X Window System, window managers are allowed to ignore GTK+'s
> + * request to change a window's size. So your program should not rely on
> + * getting a specific size. (And, as noted in gtk_window_get_size(),
> + * a program that crucially relies on a specific size will generally have
> + * race conditions and be buggy anyway - rather than assuming a
> + * call to gtk_window_set_size() has taken effect, you should react
> + * to configure_event signals on your #GtkWindow.)
> + *
> + * If you set a geometry widget for the window with
> + * gtk_window_set_geometry_hints(), the size applies to the geometry
> + * widget, not the window itself.
> + *
> + * If you've called the deprecated gtk_window_set_policy() function,
> + * gtk_window_set_size() may not behave as expected, due to interaction
> + * with window policies.
> + **/
> +void
> +gtk_window_set_size (GtkWindow *window,
> + gint width,
> + gint height)
> +{
> + g_return_if_fail (GTK_IS_WINDOW (window));
> + g_return_if_fail (width != 0);
> + g_return_if_fail (height != 0);
> +
> + /* set_default_size() uses "0" to mean "unset", but we allow "-1"
> + * for that in this newer function
> + */
> + if (width < 0)
> + width = 0;
> + if (height < 0)
> + height = 0;
> +
> + gtk_window_set_default_size (window, width, height);
> +}
> +
> +/**
> + * gtk_window_get_size:
> + * @window: a #GtkWindow
> + * @width: return location for current width, or %NULL
> + * @height: return location for current height, or %NULL
> + *
> + * Obtains the current size of @window. If the window is not onscreen
> + * (i.e. has not been received its first configure_event after being
> + * shown with gtk_widget_show()), the size will be the size GTK+ will
> + * request for this window when it's shown. The window manager may
> + * not choose to give the window exactly this requested size.
> + *
> + * In general, code which depends on window size should be written in
> + * a signal handler connected to configure_event on the window, and
> + * use the size stored in the #GdkEventConfigure. This way you can
> + * respond to changes in size caused by the user or by the window
> + * manager, in addition to changes in size created by your program. If
> + * you call gtk_window_get_size() and then assume that size is
> + * accurate, you have a race condition, because the user or window
> + * manager may resize the window between your call to
> + * gtk_window_get_size() and your assumption of accuracy.
> + *
> + * If you set a geometry widget for the window with gtk_window_set_geometry_hints(),
> + * the size applies to the geometry widget, not the window itself.
> + *
> + **/
> +void
> +gtk_window_get_size (GtkWindow *window,
> + gint *width,
> + gint *height)
> +{
> + g_return_if_fail (GTK_IS_WINDOW (window));
> +
> + if (GTK_WIDGET_REALIZED (window))
> + {
> + gdk_window_get_size (GTK_WIDGET (window)->window,
> + width, height);
> + }
> + else
> + {
> + GdkGeometry new_geometry;
> + GdkWindowHints new_flags;
> + gint w, h;
> +
> + gtk_window_compute_default_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);
> +
> + if (width)
> + *width = w;
> + if (height)
> + *height = h;
> + }
> +}
> +
> +/**
> + * gtk_window_set_location:
> + * @window: a #GtkWindow
> + * @root_x: X position of gravity-determined reference point in root window coordinates
> + * @root_y: Y position of gravity-determined reference point in root window coordinates
> + *
> + * Requests a new position for a #GtkWindow. The position is given in
> + * root window coordinates, and is the position of the window's
> + * "reference point" as determined by the window gravity (see
> + * gtk_window_set_gravity()). By default, the reference point is the
> + * northwest (top left) corner of the window's titlebar. So if you
> + * set the window position to (0,0), the window's titlebar will end up
> + * in the top left corner of the root window. Note that the root
> + * window does not always correspond to the user's desktop area, so
> + * you may want to call gdk_workspace_get_extents() or
> + * gdk_desktop_get_extents() to decide where to place a window. The
> + * extents of the root window can be obtained using gdk_screen_width()
> + * and gdk_screen_height().
> + *
> + **/
> +void
> +gtk_window_set_location (GtkWindow *window,
> + gint root_x,
> + gint root_y)
> +{
> + g_return_if_fail (GTK_IS_WINDOW (window));
> +
> + gtk_widget_set_uposition (GTK_WIDGET (window), root_x, root_y);
> +}
i'm not sure there's much point in having this fucntion if it does
just the same as gtk_widget_set_uposition()...
> +/**
> + * gtk_window_set_gravity:
> + * @window: a #GtkWindow
> + * @gravity: window gravity
> + *
> + * Window gravity defines the "reference point" to be used when
> + * positioning or resizing a window. Calls to
> + * gtk_window_set_position() will position a different point on the
> + * window depending on the window gravity. When the user resizes a window,
> + * the reference point determined by the window's gravity will stay in
> + * a fixed location as the window is resized.
> + *
> + * 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.
> + *
> + * The default window gravity is #GDK_GRAVITY_NORTH_WEST.
> + *
> + **/
> +void
> +gtk_window_set_gravity (GtkWindow *window,
> + GdkGravity gravity)
> +{
> + g_return_if_fail (GTK_IS_WINDOW (window));
>
> + if (gravity != window->gravity)
> + {
> + window->gravity = gravity;
>
> + /* This is sort of odd, but it keeps the hints recomputation
> + * in one place. Otherwise we're likely to mess up the
> + * recording of the last hints, etc.
> + */
i don't think this is odd ;)
gtkwindow resizing has always been quite complex so
gtk_widget_queue_resize() is the preferred way to say
"something sizewise changed" like for all other widgets.
that's why you shouldn't manually resize the window
in set_default_size either.
> + gtk_widget_queue_resize (GTK_WIDGET (window));
> + }
> +}
> +/**
> + * gtk_window_get_gravity:
> + * @window: a #GtkWindow
> + *
> + * Gets the value set by gtk_window_set_gravity().
> + *
> + * Return value: window gravity
> + **/
> +GdkGravity
> +gtk_window_get_gravity (GtkWindow *window)
> +{
> + g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
>
> + return window->gravity;
> +}
> Index: gtk/gtkwindow.h
> ===================================================================
> RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
> retrieving revision 1.29
> diff -u -u -r1.29 gtkwindow.h
> --- gtk/gtkwindow.h 2001/03/09 16:43:19 1.29
> +++ gtk/gtkwindow.h 2001/03/14 21:19:48
> @@ -93,7 +93,9 @@
>
> guint decorated : 1;
>
> - GdkWindowTypeHint type_hint : 2;
> + GdkWindowTypeHint type_hint : 3;
> +
> + GdkGravity gravity : 5;
>
> guint frame_left;
> guint frame_top;
> @@ -121,10 +123,6 @@
> const gchar *wmclass_class);
> void gtk_window_set_role (GtkWindow *window,
> const gchar *role);
> -void gtk_window_set_policy (GtkWindow *window,
> - gint allow_shrink,
> - gint allow_grow,
> - gint auto_shrink);
> void gtk_window_add_accel_group (GtkWindow *window,
> GtkAccelGroup *accel_group);
> void gtk_window_remove_accel_group (GtkWindow *window,
> @@ -140,22 +138,41 @@
> GdkWindowTypeHint hint);
> void gtk_window_set_destroy_with_parent (GtkWindow *window,
> gboolean setting);
> -void gtk_window_set_geometry_hints (GtkWindow *window,
> - GtkWidget *geometry_widget,
> - GdkGeometry *geometry,
> - GdkWindowHints geom_mask);
> void gtk_window_set_decorations_hint (GtkWindow *window,
> GdkWMDecoration decorations);
> void gtk_window_set_functions_hint (GtkWindow *window,
> GdkWMFunction functions);
>
> -/* 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.
> - */
> -void gtk_window_set_default_size (GtkWindow *window,
> - gint width,
> - gint height);
> +
> +void gtk_window_set_resizeable (GtkWindow *window,
> + gboolean setting);
> +gboolean gtk_window_get_resizeable (GtkWindow *window);
> +
> +
> +void gtk_window_set_size (GtkWindow *window,
> + gint width,
> + gint height);
> +void gtk_window_get_size (GtkWindow *window,
> + gint *width,
> + gint *height);
> +
> +void gtk_window_set_location (GtkWindow *window,
> + gint root_x,
> + gint root_y);
> +void gtk_window_get_location (GtkWindow *window,
> + gint *root_x,
> + gint *root_y);
> +
> +void gtk_window_set_gravity (GtkWindow *window,
> + GdkGravity gravity);
> +GdkGravity gtk_window_get_gravity (GtkWindow *window);
> +
> +
> +void gtk_window_set_geometry_hints (GtkWindow *window,
> + GtkWidget *geometry_widget,
> + GdkGeometry *geometry,
> + GdkWindowHints geom_mask);
> +
> /* gtk_window_set_has_frame () must be called before realizing the window_*/
> void gtk_window_set_has_frame (GtkWindow *window);
> void gtk_window_set_frame_dimensions (GtkWindow *window,
> @@ -183,6 +200,20 @@
> void gtk_window_maximize (GtkWindow *window);
> void gtk_window_unmaximize (GtkWindow *window);
>
> +
> +#ifndef GTK_DISABLE_DEPRECATED
> +void gtk_window_set_policy (GtkWindow *window,
> + gint allow_shrink,
> + gint allow_grow,
> + gint auto_shrink);
> +/* 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.
> + */
> +void gtk_window_set_default_size (GtkWindow *window,
> + gint width,
> + gint height);
> +#endif
i don't think #ifndef GTK_DISABLE_DEPRECATED is apprpriate here
at all.
also this doesn't account for our -2/-1/0 magic problems in
set_uposition/set_usize/set_default_size, i'd first like to see
a rationalized API intention discussion for all these before we
actually touch the resizing code.
---
ciaoTJ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]