Re: Units and resolution independence for gtk+



Hi David!

I'll write a detailed reply later, but this already looks fantastic.

I was also reading how Apple solved this problem.  May be interesting:

http://developer.apple.com/releasenotes/GraphicsImaging/RN-ResolutionIndependentUI/index.html

Their three scaling modes may very well apply to us:

  - Magnify using offscreen rendering and/or compositing manager

  - Magnify by setting a default cairo scale matrix (may need new cairo
API to not use CTM here)

  - Magnify by having application cooperate with the toolkit in RI mode


Also, my only quick feedback is that you are hooking up on the font
size, while you should instead hook on screen dpi.  Think of screen dpi
as a global scaling factor, and font size is relative size of the fonts
to the other elements.


behdad


On Wed, 2008-08-06 at 17:07 -0400, David Zeuthen wrote:
> Hey,
> 
> Many years ago jrb did a writeup about units
> 
> http://mail.gnome.org/archives/gtk-devel-list/2003-February/msg00009.html
> 
> e.g. to make apps avoid using hard coded pixel values. The past few days
> I've been working on implementing something similar to this in GTK+. 
> 
> MOTIVATION
> 
> My main motivation was primarily the need to scratch an itch - one of
> the laptops I own (incidentally mclasen has a similar one) has a 17"
> panel with 1920x1200 resolution. While it's nice with high resolution,
> everything is so tiny. Just bumping up the font size won't work; then
> all my scrollbars and other widgets look out of place; they're too small
> compared to the font. In the future we're going to see more high-DPI
> displays.
> 
> Another motivation is that I think resolution independence ("RI") should
> be default in the next major version of gtk+ (see below for reasons why
> we can't turn it on by default in gtk 2.x) - having a shiny feature like
> RI sounds to me like an excellent selling point for gtk 3.0 [1].
> 
> HOW IT WORKS
> 
> A new macro GTK_UNIT_EM (and it's companion GTK_UNIT_ONE_TWELFTH_EM) is
> introduced. This allows application to do e.g.
> 
>  hbox = gtk_hbox_new (FALSE, GDK_UNIT_EM (1));
> 
> instead of
> 
>  hbox = gtk_hbox_new (FALSE, 12);
> 
> Also, a new type GdkUnit (and it's unsigned companion GdkUUnit) is
> introduced. It's typedef'ed to gint. Like jrb proposed some high bits
> are cannibalized to tag that the given value is an em and not a pixel
> value. Also, some users of pixel values are already using -1 and
> G_MAXINT as sentinels so bit 31 is off the table. Thus, bit 30 is used
> to specify it's an em and if so, bit 29 is used to specify the sign. A
> little convoluted but it works. Down the road one can add
> 
>  GDK_UNIT_MM
>  GDK_UNIT_INCH
> 
> etc. though I've yet to seen a valid use case for physical units. I
> think we should just avoid them.
> 
> Then there's a new macro GDK_UNIT_TO_PIXEL that will convert a GdkUnit
> to pixel sizes [2]. The main idea is that widget implementations store
> GdkUnit's instead of gint's and use GDK_UNIT_TO_PIXEL in it's
> implementation (size_request, expose etc.). Now, to preserve backwards
> compatibility, all getters should return pixel values. This is achieved
> with using GDK_UNIT_TO_PIXEL in the getter. For property getters,
> gdk_value_set_unit() does the appropriate magic to ensure this.
> 
> In addition, all widgets that provide C getters, an additional _unit()
> function is added, e.g. in addition to 
> 
>  gtk_expander_get_spacing()
> 
> there's also
> 
>  gtk_expander_get_spacing_unit()
> 
> and so forth. For properties, there's
> 
>  gtk_widget_get_style_unit()
> 
> and
> 
>  gtk_object_get_unit()
> 
> where the latter is a pendant to g_object_get(). All setters are also
> changed to use GdkUnit instead of gint.
> 
> There's also a new type GdkParamSpecUnit type, the use is typically
> 
>     gtk_widget_class_install_style_property (widget_class,
>  -                                           g_param_spec_int ("xspacing",
>  -                                                             P_("XSpacing"),
>  -                                                             P_("Extra spacing applied to the width of a progress bar."),
>  -                                                             0, G_MAXINT, 7,
>  -                                                             G_PARAM_READWRITE));
>  +                                           gdk_param_spec_unit ("xspacing",
>  +                                                                P_("XSpacing"),
>  +                                                                P_("Extra spacing applied to the width of a progress bar."),
>  +                                                                GDK_UNIT_ONE_TWELFTH_EM (7),
>  +                                                                G_PARAM_READWRITE));
> 
> 
> So far so good. It get's complicated because parts of gtk+ has poor data
> hiding, e.g. GtkContainer exposes border_width as a public member. Also,
> some of these fields are 16-bit quantities. The solution here is twofold
> 
>  1. for 16-bit quantities store the GdkUnit in private data and
>     store the pixel value in public field
>     - but we need to update this pixel value value when units change,
>       hence a new ::unit_changed signal
> 
>  2. audit all users of public fields and make them use units if
>     appropriate (not a lot of these)
> 
> Now, because of 2. we can't unfortunately turn this on by default (can't
> really audit/change all users of gtk+). So for gtk 2.x the application
> will need to turn the RI feature on [3] - it's an opt-in feature. 
> 
> Thus if RI is not turned on the GDK_UNIT_EM and friends will assume
> 1em=12px and return the pixel value directly. Thus, *everything* will be
> stored in pixel values and effectively there's no change whatsoever. So
> it's safe to commit something like this to stable gtk 2.x.
> 
> PATCH
> 
> There's a patch against trunk (revision 21025 from around 1pm eastern
> today) here
> 
> http://people.freedesktop.org/~david/gtk-resolution-indepence-r21025-20080806-1315EDT.patch
> 
> Notes on the patch
> 
>  - It's huge!
> 
>     151 files changed, 4498 insertions(+), 1777 deletions(-)
> 
>    It weighs 518K. However, most changes are of the form [4]
> 
>     -  range->min_slider_size = 1;
>     +  range->min_slider_size = GDK_UNIT_ONE_TWELFTH_EM (1);
> 
>    + usage of GDK_UNIT_TO_PIXEL to resolve to pixels + conversion
>    to use gdk_param_spec_unit. E.g. most of the patch is trivial.
> 
>  - Part of of the patch deals with storing units in private data. For
>    GtkTable and GtkBox this was really unpleasant; had to mirror all
>    the childs etc. as private structures. Ugh. But we need something
>    like this work anyway as part of the gtk3 plan for sealing off
>    access to private data.
> 
>  - The gtkrc parser integration is lame; it currently uses ! as a 
>    prefix to mean em. It should accept e.g. "0.8em" instead of "!0.8".
>    Shouldn't be too hard, I just didn't like hacking the rc parser
>    right now.
> 
>    Here's some version of Gilouche's gtkrc ported
> 
>     http://people.freedesktop.org/~david/Gilouche-RI-gtkrc
> 
>    but note that the clearlooks theme engine got a bug with drawing
>    radio buttons. The Raleigh engine is fine.
> 
>  - I have a small patch to gtk-doc to print out e.g.
> 
>     Default value: 0.2 em
> 
>    instead of 
> 
>     Default value: 2474784784
> 
>  - GdkScreen grew a "unit-changed" signal
> 
>  - docs
>    - need to add docs for all new symbols
>    - need a porting guide
> 
> DEMO
> 
> Here's a screencast showing the feature
> 
>  - http://people.freedesktop.org/~david/gtk-resolution-indepence.ogg
> 
> Here are some screenshots
> 
>  - http://people.freedesktop.org/~david/file-chooser-em5.png
>  - http://people.freedesktop.org/~david/file-chooser-em10.png
>  - http://people.freedesktop.org/~david/file-chooser-em20.png
> 
> PROPOSAL
> 
> My proposal is to merge something like this for gtk 2.x in the near
> future and make it mandatory in gtk 3.0.
> 
> Flames, praises, thoughts?
> 
> Thanks,
> David
> 
> [1] : FWIW, I'm firmly in the "gtk 3.0 without compelling features is
> suicide" camp. But this is not the thread to discuss politics. Thanks.
> 
> [2] : GDK_UNIT_TO_PIXEL probably needs to take a GdkScreen (and maybe
> even a position given multiple monitors) as well.
> 
> [3] : Using gdk_unit_enable_resolution_independence() before gtk_init().
> In fact apps probably only want this if they've ported to using RI
> themselves too.
> 
> [4] : Interesting factoid: Pixel sizes are hardcoded some 400-500 places
> in the gtk+ source tree.
> 
> 
> _______________________________________________
> gtk-devel-list mailing list
> gtk-devel-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-devel-list
-- 
behdad
http://behdad.org/

"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759



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