This week in GTK+ – 36

In this last week, the master branch of GTK+ has seen 22 commits, with 1165 lines added and 904 lines removed.

Planning and status
Notable changes

On the master branch:

  • Robert Ancell updated the icon browser utility to improve the error messages when loading an icon failed
  • Matthias Clasen improve the newly added GtkCenterBox widget; you can follow along his work in the “Container Secrets” series of articles
Bugs fixed
  • 783552 – Translation interpretation
  • 759308 – Instant apply in printing dialog (number of copies)
  • 783445 – Incomplete documentation of gtk_widget_insert_after/before()
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 35

In this last week, the master branch of GTK+ has seen 33 commits, with 5011 lines added and 8140 lines removed.

Planning and status
  • The GTK+ road map is available on the wiki
  • Patrick Griffis is experimenting with a feature branch to deprecate and remove gtk_dialog_run(); see this comment on the pitfalls of nested main loops with regards to UI threads, IPC threads, and I/O threads
  • Matthias Clasen is experimenting with re-using the fuzzy search in libdazzle in the icon browser
Notable changes

On the master branch:

  • Matthias Clasen added the ability to copy the icon name to the clipboard to the icon browser utility
  • Matthias also made the GtkCenterBox widget public; this widget replaces the equivalent functionality of GtkBox to have a centered widget
  • Olivier Fourdan fixed various bugs in the Wayland backend, and backported the fixes to the gtk-3-22 stable branch
  • Chun-wei Fan pushed various fixes to ensure that GTK+ keeps building with MSVC on Windows
  • Emmanuele Bassi modified the Meson build to ensure that all the SASS-based themes are regenerated when building GTK+, if sassc is installed; Lapo Calamandrei removed the Gem file for Ruby/Sass, and thus GTK+ switched to sassc as the preferred SASS compiler
Bugs fixed
  • 770513 – MainToolbar in full-screen mode has rounded corners, which show video pixel bleed-thru underneath it
  • 783347 – gtkfilechoosernativewin32: Fix support for non-ASCII paths
  • 781945 – SIGSEGV dragging window on Wayland when toplevel window set_transient_for is set to another toplevel
  • 782283 – Wayland: Crash when dismissing a menu when a tooltip is visible
  • 781285 – Key repeat cancel under Wayland should depend on which key is repeating
  • 783397 – Remove unused code in gtktextdisplay.c
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 34

After quite a long break around the GNOME 3.24 release, we’re finally back. Sorry for the wait!

In this last week, the master branch of GTK+ has seen 103 commits, with 2355 lines added and 5482 lines removed.

Planning and status
  • The GTK+ road map is available on the wiki.
  • Matthias Clasen released GTK+ 3.91.0, the first snapshot of the development cycle that will lead to the 3.92 release. This is still part of the development cycle towards the API stable 4.0.
  • Timm Bäder is working on his drawing branch which aims to replace all the internal uses of CSS gadgets with real widgets. See this article on this blog for more information.
Notable changes

On the master branch:

  • Carlos Garnacho merged his event-delivery branch, which moves the event handling from the GDK window hierarchy to the GTK widget one; this is the first step towards the removal of all GdkWindow instances outside of the top level one, and which will ultimately lead to improved input handling.
Bugs fixed
  • 745289 – wayland: do not use g_error() on connection errors
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

Widget hierarchies in GTK+ 4.0

Today we’re going to have guest author Timm Bäder, maintainer of Corebird and a contributor of GTK+, talk about the changes in store for writing composite widgets in GTK+ 4.0.

(Note: Some of the information here is based on branches that have not been merged into master yet, but I’m confident that they will be in the near future)

In GTK+3, only GtkContainer subclasses can have child widgets. This makes a lot of sense for “public” container children like we know them, e.g. GtkBox — i.e. the developer can add, remove and reorder child widgets arbitrarily and the container just does layout.

However, there are more complicated widgets in GTK+3 which don’t inherit from GtkContainer, e.g. GtkSpinButton or GtkSwitch. These never have real GtkWidget children. Consider, for example, the two clickable areas in a GtkSpinButton. I’m not calling them “buttons” here for a reason, since in GTK+3, they are not actual GtkButton instances, as GtkSpinButton is not a GtkContainer. Instead, GtkSpinButton has to work around that fact, and create two GdkWindows for the up/down areas and then render two icons in there; care about hover and CSS states; various button up/down events; and the GdkWindow lifetime, etc. In order to work around the GtkContainer requirement, in GTK+3 we introduced gadgets (GtkCssGadget). On the styling side, a gadget corresponds to a CSS box and therefore represents one node in the CSS tree. On the widget side they were being used to have “widget-like”, CSS-stylable, children for non-container widgets.

GtkWidget Changes

Of course there were plenty of changes needed to support these use cases in GTK+4. I’m not going to list all of them here (in particular the more ugly ones like focus handling), but I think most of them are quire interesting and important for application developers and custom widget authors. Generally, we’re trying to get a away from special cases and go a more general way by re-using widgets wherever we can. So, instead of using a PangoLayout to display text, widgets should use a GtkLabel. If you have a clickable area with button-like semantics, try to use a GtkButton. If you want to lay out widgets in horizontal or vertical orientation, use a GtkBox. This way we have one widget tree that both input and rendering can operate on. In practice, this means mostly getting rid of all the gadgets used inside widgets, as well as standalone GtkCssNode instances.

Iterating over child widgets

While in GTK+3, every container had to implement GtkContainer::forall and one could easily iterate over all the child widgets using gtk_container_foreach() and gtk_container_forall(), in GTK+4, every GtkWidget can have child widgets, so every widget potentially has a list of children we need to draw, measure, size-allocate, etc. In the widget hierarchy, these children and sibling widgets can be accessed through:
  • gtk_widget_get_first_child()
  • gtk_widget_get_last_child()
  • gtk_widget_get_prev_sibling()
  • gtk_widget_get_next_sibling()
So, the easiest possible way of iterating over the child widgets of a given GtkWidget would be (in C):
GtkWidget *widget;
GtkWidget *child;
for (child = gtk_widget_get_first_child (widget);
     child != NULL;
     child = gtk_widget_get_next_sibling (child))
  {
    /* Do stuff with @child */
    g_assert (gtk_widget_get_parent (child) == widget);
  }

Adding widgets to a non-container parent

Every widget in GTK+ (both 3 and 4) saves a pointer to its parent widget. This parent can be set using gtk_widget_set_parent(), and all the GtkContainer::add implementations eventually had to use this function to set the parent of the given child widget.

In GTK+4, gtk_widget_set_parent() still works and adds the widget to the end of the child widget list of the parent. However, we clearly also want to manage the order of the child widgets, as well as where we add new children in the list, so we have:

  • gtk_widget_insert_before()
  • gtk_widget_insert_after()
to add new child widgets before or after a child widget that’s already in the parent’s list. These can also be used to reorder children child widgets by passing a child that already has the given parent set.
Since lots of widgets inside GTK+ currently use composite widget templates in XML form, GtkWidget now also has its very own GtkBuildable::add_child() implementation to support this use case. This is what e.g. GtkFileChooserWidget uses which is almost exclusively defined in XML.

Widget CSS names

Since we frequently need to use arbitrary CSS node names for arbitrary widgets, GtkWidget now has a construct-only property called GtkWidget:css-name that will be used as the css node name if specified. If not, the one passed to the widget’s gtk_widget_class_set_css_name() call will be used. If none of the 2 have been used, the CSS node will simply be called “widget”.

Examples of Converted Widgets

There are already a few widgets in current master (and side-branches) that were converted from using a variety of GtkCssGadgets, GdkWindows and PangoLayouts to using actual widgets. The end-goal being, of course, to re-use widgets as much as possible, therefore reducing code size and maintenance burden.

GtkSwitch

In GTK+3, GtkSwitch is a direct GtkWidget subclass (yay!) that uses a GdkWindow for the input (clicking on the switch will enable/disable it), one GtkCssGadget for the widget itself, two PangoLayouts for the ON/OFF text and another GtkCssGadget for the slider.
In GTK+ master, the switch still has its widget-level GtkCssGadget so it supports min-width/min-height CSS properties and CSS margins, but the slider gadget has been replaced by a GtkButton and the two PangoLayouts are replaced with GtkLabels. This way we can save roughly 300 lines in gtkswitch.c. Theoretically we also have more features and can e.g. use the limited support for the text-decoration CSS property that GtkLabel supports, but I’m just going to doubt that this is very useful.

GtkSpinButton

As noted earlier, GtkSpinButton could easily use actual GtkButtons for the up/down areas, and it does so in GTK+ master (which will become GTK+4 at some point). This gets rid of another 300 lines in gtkspinbutton.c. Through using GtkButtons, the old icon helper gadgets also become actual GtkImage instances. Unfortunately we have to implement some of the GtkGesture magic ourselves here since GtkSpinButton also supports middle and right clicks on its buttons while GtkButton::clicked only reacts to single, primary mouse button clicks.

GtkLevelBar

GtkLevelBar manages a set of blocks and assigns different style classes to them. In GTK+3, these blocks are all GtkCssGadget instances. All of them are “dumb” in the sense that they don’t do anything special — they are just CSS boxes and that’s it. That’s why converting it to use GtkWidgets for all blocks didn’t gain much of a reduction in file size.

 

GtkProgressBar

GtkProgressBar uses gadgets for the trough and the progress nodes. It also uses a PangoLayout to display the percentage or a user-given string.

In master, both trough and progress are widgets and the PangoLayout is a GtkLabel of course. Not having to listen to GtkWidget::style-changed (which gets done automatically for widgets) and not having to draw the PangoLayout ourselves (which the GtkLabel now takes care of) yields a nice code size saving of around 200 lines, however.

 

GtkExpander

GtkExpander is more complex than it looks like. In GTK+3, it consists of 2 GtkBoxGadgets (which is like a GtkBox, but not a widget…), one gadget for the arrow to the left of the title widget, the title widget and the actual content widget. In master, this is done using an actual GtkBox, and a GtkIcon (an internal widget) for the arrow. I’m not sure if this is the best way to express the GtkExpander functionality, e.g. we could also use a GtkButton for the arrow+title widget combination.
Since GtkBoxGadget is already almost a perfect GtkBox clone, the code savings here aren’t very interesting, but not having to listen to GtkWidget::direction-changed once again saves around 30 lines.

Accidental GtkBox & GtkButton subclasses

GTK+3 contains quit a lot of widgets that inherit from another widget for the sole purpose of looking and behaving like them. The problem here is that these widgets also inherit all the API of the parent class, which is only rarely wanted.
For GtkBox, almost all subclasses in GTK+3 are “accidental” in the sense that actually using them as a GtkBox doesn’t make any sense and people usually don’t do it, but they had to be GtkBox subclasses to satisfy GTK+’s GtkContainer requirement. One example of such a widget would be GtkFileChooserWidget. This is already one of the most complex widget to ever exist, but have you ever considered using gtk_container_add() or gtk_box_pack_{start,end}() to add widgets to it? It doesn’t make a lot of sense. It’s a closed entity with its own API. So, in GTK+4 it will be a direct GtkWidget subclass that contains a GtkBox. Or maybe not. That’s just an implementation detail you don’t have to care about. (Fun Fact on the side: GtkFileChooserButton is a GtkBox in GTK+3)
The same applies to GtkButton. In GTK+3, GtkButton has lots of subclasses that inherited all the GtkButton API without actually supporting it. What happens if you remove the child widget from a GtkLinkButton? What if you set the GtkButton:label property of a GtkFontButton? Again, these are closed entities that have their own API to set and get various data and change behavior and/or looks based on them, but that doesn’t mean they support all the GtkButton/GtkContainer shenanigans.

General Restructuring Rules and Future

For this refactoring work we try to keep the CSS node structure as it was in GTK+3, i.e. we try not to break the CSS node tests we currently have in testsuite/css/nodes.c.
A few of the more complex widgets inside GTK+ still heavily rely on gadgets and porting them away to use only actual widgets will be quite a lot of work. GtkRange is historically one of the most complex non-container widgets inside GTK+. It’s used both for scrollbars and scales so porting it to widgets might first need another round of refactoring.
Another interesting case is GtkNotebook, which combines gadget and widget usage. Here we could e.g. use a real GtkStack to switch between pages and effortlessly support page switching transitions.
Another exciting look into the future is of course Carlos’ wip/carlosg/event-delivery branch that gets rid of a ton of GdkWindow instances and makes widget input easier than ever before.

This week in GTK+ – 33

The past two weeks we’ve had DevConf and FOSDEM back to back, so the development slowed down a bit. Expect it to pick up again, now that we’re close to the GNOME 3.24 release.

In these last two weeks, the master branch of GTK+ has seen 34 commits, with 20973 lines added and 21593 lines removed.

Planning and status
Notable changes

On the master branch:

  • Timm Bäder removed gtk_widget_class_list_style_properties() in the continuing effort to deprecate the style properties inside GtkWidget and replace them with CSS properties
  • Timm also moved some of the state used only by GtkToggleButton subclasses into those types
  • William Hua improved the Mir GDK backend for proper positioning of menus
Bugs fixed
  • 777547 Notebook arrow icon wrong color after closing final tab
  • 773686 Software when launched shows in dash with wrong icon, name and menu
  • 775864 getting-started: typo tie->the
  • 778009 menu drawn on top of menubar in Fedora
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 32

In this last week, the master branch of GTK+ has seen 106 commits, with 7340 lines added and 12138 lines removed.

Planning and status
  • Matthias Clasen released GTK+ 3.89.3
  • The GTK+ road map is available on the wiki.
Notable changes

On the master branch:

  • Benjamin Otte simplified the clipping shaders for the Vulkan renderers
  • Benjamin also removed the “assume numbers without dimensions are pixels” fallback code from the CSS parser
  • Daniel Boles landed various fixes to the GtkMenuGtkComboBox and GtkScale widgets
  • Daniel also simplified the internals of GtkComboBox and moved most of its internal widgets to GtkBuilder UI files
  • Matthias Clasen removed command line argument handling from the GTK+ initialization functions; gtk_init() now takes no arguments. Additionally, gdk_init() has been removed, as GDK ceased to be a separate shared library. The recommended way to write GTK+ applications remains using GtkApplication, which handles library initialization and the main loop
  • Timm Bäder merged his branch that makes GtkWidget visible by default, except for the GtkWindow and GtkPopover classes; Timm also removed gtk_widget_show_all() from the API, as it’s not useful any more
  • Timm modified GtkShortcutsShortcut, GtkFileChooserButton, and GtkFontButton to inherit directly from GtkWidget, taking advantage of the new scene graph API inside the base GtkWidget class

On the gtk-3-22 stable branch:

  • Ruslan Izhbulatov fixed the Windows backend for GDK to ensure that it works with remote displays
Bugs fixed
  • 777527 GDK W32: Invisible drop-down menus in GTK apps when working via RDP
  • 770112 The documented <alt>left shortcut doesn’t work on Wayland
  • 776225 [wayland] dropdown placed somewhere in the screen
  • 777363 [PATCH] wayland: avoid an unnecessary g_list_length call
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 31

In this last week, the master branch of GTK+ has seen 52 commits, with 10254 lines added and 9466 lines removed.

Planning and status
  • Alex Larsson is working on two separate branches to optimize the memory allocation and fragmentation when building the GSK render tree, after profiling the tree building code
  • Timm Bäder is working on a topic branch to switch widgets to be visible by default
  • The GTK+ road map is available on the wiki.
Notable changes

On the master branch:

  • Rui Matos added support in the Wayland backend for the gtk-enable-primary-paste settings key; this requires a newer version of the gsettings-desktop-schemas
  • Matthias Clasen and Alex Larsson refactored some of the GSK,  GtkWidget, and CSS internals to avoid excessive type casting and type checking after profiling the rendering code
  • Matthias added a “system” tab to the GtkAboutDialog widget, for free-form, system-related information
  • Matthias also updated the porting documentation for -gtk-icon-filter
  • Benjamin Otte changed the X11 backend to always call XInitThreads() unconditionally, in order to safely use the Vulkan rendering API; this should be safe, but testing is encouraged
  • Benjamin updated the GtkSnapshot API to ensure that render nodes are available only after the snapshot is complete
  • Benjamin also fixed the handling of CSS images that have no explicit size but should be scaled according to their aspect ratio
  • Timm Bäder added a revealed property to the GtkInfoBar widget and ported the GtkActionBar code to use it

On the gtk-3-22 stable branch:

  • Ruslan Izhbulatov worked on fixing various cases of keyboard handling under Windows, including interaction with AeroSnap; Ruslan also fixed bug 165385, which was going to be 12 years old in 10 days
  • Carlos Garnacho changed the EGL handling inside the Wayland backend to disable swap interval, as the compositor is in charge of timing the rendering
  • Matthias Clasen deprecated additional API that has been removed from the development branch
Bugs fixed
  • 776031 W32: Winkey+down minimizes maximized window instead of restoring it
  • 165385 Win32 keyboard handling still incomplete
  • 769835 On Wayland, application containing GtkGLArea stops responding if it’s not on current workspace
  • 774726 GtkTreeView dnd: gtk_drag_finish remove row when reorder sinse 3.20
  • 769214 keyval field not filled correctly for Pause key
  • 776485 GDK W32: Impossible to restore maximized window via system menu
  • 776604 about dialog: Add a “system” tab
  • 775846 gdk/wayland: Add support for the gtk-enable-primary-paste gsetting
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 30

In this last week, the master branch of GTK+ has seen 81 commits, with 12205 lines added and 12625 lines removed.

Planning and status
  • Welcome back to This Week in GTK+ after the end of the year break
  • The GTK+ road map is available on the wiki.
Notable changes

On the master branch:

  • Timm Bädert merged his work on moving the scene graph of widgets directly into the GtkWidget class; this allows widgets to have internal children without necessarily subclassing GtkContainer
  • Timm also worked on porting widgets currently using the internal CSS gadget API to be composite widgets, like GtkSwitch
  • Benjamin Otte and Georges Basile Stavracas Neto have been working on making the Vulkan GSK renderer work on Wayland
  • Benjamin also worked on improving the efficiency of the Vulkan renderer
  • William Hua worked on improving the Mir backend of GDK with regards to clipboard support

On the gtk-3-22 stable branch:

  • Matthias Clasen released GTK+ 3.22.6
Bugs fixed
  • 776627 Correct PostScript capitalization
  • 776868 Improve the documentation of GtkEntry:attributes
  • 776560 icon-browser: window opens at very narrow size, only showing 1 column of icons
  • 775732 mir: clipboard support missing
  • 776736 build: Fix vulkan detection
  • 776807 GtkInspector doesn’t show up when Gtk is initialized through option group
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 29

In this last week, the master branch of GTK+ has seen 20 commits, with 883 lines added and 2740 lines removed.

Planning and status
  • Alex Larsson worked on a simplification of GdkWindow that removed native and foreign child windows; the long term plan is to have native windowing system surfaces only for top levels
  • Alex also sent a review on gtk-devel-list of Benjamin’s wip/otte/rendernode branch, with ideas on future work for the GSK rendering API
  • Chun-wei Fan updated the Windows backend to ensure that it continues to build and work on the master branch
  • Benjamin Otte implemented the snapshot() virtual function in more GtkWidget subclasses.
  • The GTK+ road map is available on the wiki.
Notable changes

On the master branch:

  • Olivier Fourdan updated the Wayland backend to ensure that empty input shapes are updated on sub-surfaces when needed; this allows other toolkits, like Clutter, to use the GDK sub-surface API
  • Alex Larsson removed gdk_window_reparent() from the GDK API, since it’s unused and allows for the goal of only having top level GDK windows
  • Benjamin Otte removed the ad hoc code from GdkCellView to modify its background, as the cell view can use CSS to achieve the same (or better) results
  • Benjamin also removed the border node from the GtkFrame CSS nodes, as it performed additional immediate mode clipping that complicates the rendering

On the gtk-3-22 stable branch:

  • Emmanuele pushed fixes for the GL rendering when using GtkGLArea with OpenGL ES 2.0 implementations that are missing the GL_EXT_framebuffer_blit extension
Bugs fixed
  • 776132 Mention the difference between gdk_window_create_similar_image_surface and cairo_surface_create_similar_image
  • 774534 [wayland] input shape and opaque region not applied without begin_paint()/end_paint()
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.

This week in GTK+ – 28

In this last week, the master branch of GTK+ has seen 103 commits, with 5986 lines added and 1896 lines removed.

Planning and status
  • Benjamin Otte is working on a refactoring of the GSK render node API
  • Emmanuele Bassi worked on a 3.x-specific branch that allows GDK to use EGL instead of GLX on X11 platforms
  • The GTK+ road map is available on the wiki.
Notable changes

On the master branch:

  • Benjamin merged the Vulkan renderer for GSK, as comparison point for the GL and Cairo renderers. The Vulkan renderer adds a new optional dependency on a working Vulkan implementation, as well as glslc
  • The Vulkan renderer also resulted in a large refactoring of the GL drawing code inside GDK, though this should not have caused any user-visible changes in the API
  • Benjamin also implemented support for the CSS border-spacing property following the CSS 2.1 specification

On the gtk-3-22 stable branch:

  • Matthias released GTK+ 3.22.5.
Bugs fixed
  • 775651 GdkX11-4.0.gir, GdkWin32-4.0.gir, and Gsk-4.0.gir are generated before Gdk-4.0.gir is ready
Getting involved

Interested in working on GTK+? Look at the list of bugs for newcomers and join the IRC channel #gtk+ on irc.gnome.org.