sizing policy



Hi,

Posting this (again), outstanding issues are at the end.  Can we
please resolve these ASAP so I can implement it in the next couple
days?

Havoc

Goals of this API revision
===

The idea here is to have functions that do what people expect, and do
things people actually want to do. The current mish-mash of "usizes"
and "upositions" and so on is difficult to use and document, and
causes a lot of FAQs. Also, sometimes it's necessary to access
widget->window to get the effects people want, and most code doing
that is broken in some way.

As a side goal, we want to rationalize some of the "magic numbers"
present in the current API. The basic idea here is that only -1 (never
0) can be a magic number, and -1 always means "unset."

Proposed API overview
===

Widget sizing and positioning are left entirely to the GTK container
system. The only thing you can set explicitly is the size request of a
widget. This is done with gtk_widget_set_size_request() (which renames
gtk_widget_set_usize()).

For toplevel windows, you can set three sizes:

 - the size request, which determines the default minimum size hint
   for the window
 - the current size, which is what changes as the user resizes 
   the window; setter is gtk_window_resize(), getter is 
   gtk_window_get_size().
 - the default size, which is used when initially mapping the 
   window

Setting the current size before mapping a window overrides any default
size; the rationale is that a user resize also overrides the default
size, and emulating a user resize before mapping the window is
analagous.

Thus gtk_window_resize() can always be used to set window sizes.  The
reason to set the default size is that it applies to the geometry
widget rather than the whole window, and that it can be set from a GUI
builder. The "current size" (from gtk_window_resize()) is not exposed
via properties or put in a GUI builder because resizing is an "action"
which isn't guaranteed to work.

gtk_window_move() is a similar action for positioning a window. 
gtk_window_get_position() gets the current actual position.

Properties have "_set" variants, because "-1" magic values can't be
implemented consistently for all properties, and because they create a
bad UI in the GUI builder. However the magic -1 values still exist for
convenience if you know about them.

Proposed API in detail
===

gtk_widget_set_size_request ():
 - Sets the size that a widget will request, overriding its usual
   request. (Renaming of set_usize().)
   
   Passing -1 for width/height unsets that value.
   Passing 0 is equivalent to passing 1, because GTK always 
    allocates at least 1x1 despite a requisition of 0x0; 
    however we should allow 0 since it's an intuitive number
    to pass here.
   
   The magic -1 is only for the function, not the properties.

gtk_window_resize ():
 - Resizes the window as if the user had done so, obeying geometry 
   constraints. Before mapping, overrides (but does not set) the
   default size.

   Sizes <= 0 g_return_if_fail().

gtk_window_set_default_size (): 
 - Sets the size of the window to be used on mapping; size will be
   clamped to obey geometry constraints. If there's a geometry widget,
   specified size is for the geometry widget. Same as default_width, 
   default_height. Has no effect if gtk_window_resize() has been
   called, because gtk_window_resize() emulates a user resize and 
   thus overrules the default size.

   Right now, passing 0 for default size args means to unset that arg,
   and -1 means not to modify it. Propose changing this to: size of -1
   unsets the size, size of 0 does g_return_if_fail().

   This is 99% of the time backward compatible, because almost no one
   is using "0" as an arg, and when using "-1" most people are
   actually trying to say "do not set the size in that dimension," 
   rather than "do not modify whether the size has been set."

   The magic -1 is only for the function, not the properties.

gtk_window_get_default_size ():
 - Gets the default size values, including -1 if they are unset.

gtk_window_move ():
 - Moves the window as if the user had done so, obeying 
   constraints of e.g. GTK_WIN_POS_CENTER_ALWAYS. 
   Position is given as the position of the gravity-determined 
   reference point.

   Position can be negative to move windows offscreen.

   Position is in root window coordinates, but allowing
   E's virtual root hack to work (we don't try to compensate
   for how E will offset our configure request, i.e. we ignore
   E)
  
   If called before mapping, sets the uposition on the window.

gtk_window_get_size ():
 - If mapped, gets actual current size of widget->window

   Prior to mapping, tries to predict the window size (looks
   at size request, window_resize() values, and geometry constraints)

gtk_window_get_position ():
 - Gets the gravity-determined reference point location, 
   if unmapped, tries to predict window position (looks at 
   GTK_WIN_POS_*, gtk_window_move() values, falls back 
   to 0,0 or something)

   Position is normally in root window coordinates. (We could offset
   it to compensate for E's virtual root hack so that setting the
   position from get_position() will give the expected result.)

gtk_window_parse_geometry ():
 - Parses a geometry string and sets window position and default size.

GtkWidget::width_request, GtkWidget::height_request:
 - Read-write properties, equivalent to set_size_request. 

   May not be < 0. i.e. the range of the properties is 
   the same as for gtk_window_set_size_request().

   Auto-toggles-on the _set property when written.

GtkWidget::width_request_set, GtkWidget::height_request_set:
 - Read-write properties, whether the size request value 
   is used or not.

GtkWindow::default_width, GtkWindow::default_height:

 - still needed so you can set default size in a GUI builder.
   equivalent to gtk_window_set_default_size().

   These values are only used if default_width_set, default_height_set
   are TRUE. The values are never allowed to be less than 1.

   For backward compatibility, in the _set_property implementation, we
   special-case -1 and 0 and toggle default_width_set,
   default_height_set to FALSE instead of modifying the properties
   themselves. However reading the property will never return 
   a value less than 1.

   Auto-toggles-on the _set property when written.

GtkWindow::default_width_set, GtkWindow::default_height_set:
 - whether default w/h are set                             

Deprecations:
  - gtk_widget_set_uposition() - use gtk_window_move() or
               gtk_fixed_move()/gtk_layout_move() instead
  - gtk_widget_set_usize() - use widget_set_size_request()
               or gtk_window_resize() or set_default_size()
  - x/y/width/height properties on GtkWidget
  - gtk_window_set_policy() - this is already deprecated in 
    CVS, we continue with that deprecation, it's replaced
    by set_resizable() (allow_grow) and setting size request to 0
    (allow_shrink)
  - the set_policy() properties are deprecated along with 
    gtk_window_set_policy(), replaced by the size request properties
    and a "resizable" property

General changes:

  Size calculation (internal function gtk_window_move_resize()) is
  done simply as:

    - compute geometry hints.
    - set initial size hint (before mapping window) to:
       - gtk_window_resize() values if set
       - otherwise default_width, default_height if set
       - otherwise size request
      In all cases, constraining to geometry hints.
    - after the window is onscreen, clamp current size to geometry
      hints, don't affect current size otherwise.
      (Do we need to send a configure request or will the WM 
      handle the clamping?)

  No "hysteresis" - current size has a fixed relationship to the
  parameters that have been set and actions users have taken.

  allow_shrink is equivalent to calling
  gtk_widget_set_size_request (widget, 0, 0). 

  allow_grow is now the flag set by gtk_window_set_resizeable().  If
  TRUE, max size is infinite by default. If FALSE, max size is equal
  to the min size by default.

  auto_shrink is now ignored. This is reasonably backward
  compatible. If the legacy code using the new set_policy() didn't set
  allow_grow, then auto_shrink would do nothing, since we now clamp
  within min/max size in all cases. with allow_grow=false this means
  the window is always shrunk already. if legacy code did set
  allow_grow, then the behavior before just made no sense, but
  probably they wanted a resizable window.

  Geometry hints set with gtk_window_set_geometry_hints() simply
  override anything calculated in any other way, e.g. if you set the
  min size with geometry hints, it overrides the min size based on the
  window's size request.

Notes
===

 There's no way to get GtkWidget size/position because there is no
 real reason to get those things unless you understand size_allocate
 and widget->allocation

 Instead of having set_position() not compensate for E and
 get_position() compensate for E, we could have get_position() not
 compensate for E but set_position() does compensate for E.
 In this case, you would call set_position() with root window
 coordinates, and internally we would translate those so that E
 positions the window properly.

 If we did things like this, we'd need a function
 gdk_workspace_get_extents() which should be used for the screen
 extents instead of (0,0) gdk_screen_width () x gdk_screen_height ()

 My bias toward compensating for E in get_position() rather than
 set_position() is that it's simpler and doesn't changing apps.
 The argument for gdk_workspace_get_extents() would be that 
 it's a better abstraction than forcing the workspace to 
 always be (0,0) gdk_screen_width () x gdk_screen_height ()

Outstanding Issues that Impact the Core Proposal
===

A. Is there a "resizable" property or do we just leave it called
   "allow_grow" with the function called gtk_window_set_resizable().

   I think this is really obvious but Tim asked to have this issue
   open. Tim what is the rationale for keeping allow_grow when
   set_policy() is already deprecated (as discussed a long time ago
   and already in CVS)?
 
B. Should we have _set properties, or just use magic -1 flags.

   The argument for _set is:
     - magic values can't be used in all situations
     - the same magic value can't be used in all situations
     - thus sometimes you need _set properties
     - thus you MUST have a working solution where no magic value
       is possible
     - we should have a consistent solution throughout GTK
     - magic values can't always be used, and are always 
       inconsistent anyway (may be -1, NULL, 0, etc., depending
       on context)
     - text widget crucially depends on _set properties anyway
     - thus magic values are not a candidate for a consistent solution
     - thus we should standardize on _set properties. 

   The argument against was:
     - it's broken to auto-toggle-on the _set property when writing
       the property
     - if you don't auto-toggle-on, then it's inconvenient to write:
         g_object_set (object, "foo", 10, "foo_set", TRUE, NULL)
    
   My argument is that both solutions have problems, but auto-toggled
   _set properties are optimal for application developers, and also
   fairly easy for GUI builders to handle generically by simply
   assuming a boolean property "foo_set" is conventionally a toggle
   for another property "foo". If just using a convention is too
   annoying, we could trivially add a flag to GParamSpec.
   
   In any case, I consider the magic values a non-starter non-solution
   because it does not address all the cases where you need the
   concept of an "unset" property - it only happens to work by
   accident for some properties that have a reasonable unused 
   magic value.

C. Does setting default size work post-mapping?

   The argument is that if you edit the default size in a GUI builder
   you might want to see results immediately.

   I think this is just conceptually broken; changing the _default_ 
   size doesn't change the _current_ size. So to me this makes
   the API more confusing.
  
D. Does window_resize() modify geometry widget size or window size?

   I've amended the proposal to have gtk_window_resize() affect the 
   window size.

   This required re-adding gtk_window_set_default_size() and having
   the default size affect the geometry widget, not the window. 
   This is needed to implement --geometry.

   The idea is that most uses of gtk_window_resize() will either be by 
   people who don't understand geometry widgets anyway, or who are
   trying to get exact pixel effects such as filling the whole screen.

E. Should we just remove all special handling of Enlightenment?

   I don't really have any objection to this.

F. auto_shrink behavior

   Tim said he had to think about this topic, I don't know what the 
   issue is.

Outstanding Issues that Add Extra API to Core Proposal
===

I believe we can just ignore these until we implement the proposal,
and add them later if people want them.

G. Whether to add a function to get_size_request(). 
   
   I'm not sure who wanted this. What would this function do? 
   does it actually gtk_widget_size_request() the child, or does 
   it look at current widget->requisition?

   One problem is that widgets must be associated with a screen before 
   being size requested, since they need font metrics etc. Which is 
   just one reason among many that apps calling get_size_request() for 
   a widget are probably doing something broken.

   It would be useful to have example use-cases for when you would do this.

H. Whether to have readonly "x" and "y" properties for GtkWidget
  
   These return widget->allocation.x and widget->allocation.y I
   assume?

   My question here is again what the use cases are. When do you want
   this information? (aside from widget implementations that can just 
   look at widget->allocation)
 









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