Category Archives: Uncategorized

Recipes for you and me

Since I’ve last written about recipes, we’ve started to figure out what we can achieve in time for GNOME 3.24, with an eye towards delivering a useful application. The result is this plan, which should be doable.

But: your help is needed. We need more recipe contributions from the GNOME community to have a well-populated initial experience. Everybody who contributes a recipe before 3.24 will get a little thank-you from us, so don’t delay…

The 0.8.0 release that I’ve just created already contains the first steps of this plan. One thing we decided is that we don’t have the time and resources to make the ingredients view useful by March, so the Ingredients tab is gone for now.

At the same time, there’s a new feature here, and that is the blue tile leading to the shopping list view:

The design for this page is still a bit up in the air, so you should expect this to change in the next releases. I decided to merge it already anyway, since I am impatient, and this view already provides useful functionality. You can print the shopping list:

Beyond this, I’ve spent some time on polishing and fixing bugs. One thing that I’ve discovered to my embarrassment earlier this week is that exporting recipes from the flatpak did not actually work. I had only ever tested this with an un-sandboxed local build.

Sorry to everyone who tried to export their recipe and was left wondering why it didn’t work!

We’ve now fixed all the bugs that were involved here, both in recipes and in the file chooser portal and in the portal infrastructure itself, and exporting recipes works fine with the current flatpak, which, as always, you can install from here:

https://alexlarsson.github.io/test-releases/gnome-recipes.flatpakref

One related issue that became apparent during this bug hunt is that things work less than perfectly if the portals are not present on the host system. Until that becomes less likely, I’ve added a bit of code to make the failure less mysterious, and give you some idea how to fix it:

I think recipes is proving its value as  a test bed and early adopter for flatpak and portals. At this point, it is using the file chooser portal, the account information portal, the print portal, the notification portal, the session inhibit portal, and it would also use the sharing portal, if we had that already.

I shouldn’t close this post without mentioning that you will have a chance to hear a bit from Elvin about the genesis of this application in the Fosdem design devroom. See you there!

GTK+ Happenings

I said that I would post regular updates on what is happening in GTK+ 4 land. This was a while ago, so an update is overdue.

So, whats new ?

Cleanup

Deprecation cleanup has continued, and is mostly done at this point. We have the beginning of a porting guide that mentions some of the required changes for early adopters who want to stick their toes into the GTK+ 4 waters. Sadly, I haven’t gotten the GTK+ 4 docs up on the website yet, so no link…

Among the things that have been dropped as part of our ongoing cleanup has been the pixel cache, which should no longer be needed. This is nice since the pixel cache was causing problems, in particular on connection with transparency and component alpha (in font rendering).

Not really a cleanup, but we also got rid of the split into multiple shared objects (libgtk, libgdk, libgsk). Now, we just install a single libgtk, which also provides the gdk and gsk APIs. This has some small performance benefits, but mainly, it makes it easier for us to have private APIs that cross the gtk/gdk boundary.

Widget APIs

Some of the core APIs that are important when you are creating your own widgets have been changed around a bit:

  • The five different virtual functions that are used for size requisition have been replaced by a single new vfunc, measure(). This is using the same approach that we are already using for gadgets, where it has worked well.
  • The draw() virtual function that lets widget render themselves onto a cairo surface has been replaced by the new snapshot() vfunc, which lets widget create render nodes. This is essentially the change from direct to indirect rendering. Most widgets and gadgets have been ported over to this new wayof doing things.

These changes are only important to you if you create your own widgets.

Window APIs

GdkWindow has gained a few new constructors to replace the old libX11-style gdk_window_new.  Their names should indicate what they are good for:

  • gdk_window_new_toplevel
  • gdk_window_new_popup
  • gdk_window_new_temp
  • gtk_window_new_child
  • gdk_window_new_input
  • gdk_wayland_window_new_subsurface
  • gdk_x11_window_foreign_new_for_display

The last two are worth mentioning as examples where we move backend-specific functionality to backend APIs.

In the medium term, we are moving towards a world with only toplevel windows. As a first step towards this, we no longer support native child windows, and gdk_window_reparent() is gone. This allowed us to considerably simply the GdkWindow code.

Renderers

When we initially merged GSK, it had a GL renderer and a software fallback (using cairo). Since then, Benjamin has created a Vulkan renderer. The renderer can be selected using the GSK_RENDERER environment variable.

So, for example, this is how to run gtk4-demo with the cairo renderer and the X11 backend:

GSK_RENDERER=cairo GDK_BACKEND=x11 gtk4-demo

After the GSK merge, we struggled a bit to come up with a working approach to converting all our widget and CSS rendering to render nodes. With the introduction of the snapshot() vfunc, we’ve been able to make progress on this front. As part of this effort, Benjamin changed the GSK API around a bit. There are now a bunch of special-purpose render node subclasses that let us effectively translate the CSS rendering, e.g.

  • gsk_linear_gradient_node_new
  • gsk_texture_node_new
  • gsk_color_node_new
  • gsk_border_node_new
  • gsk_transform_node_new

…and so on. More node types will be created as we discover the need for them.

New fun

As an example of new functionality that would be very hard to support adequately in GTK+ 3, Benjamin recently added gsk_color_matrix_node_new and used it to implement the CSS filter spec, which is good for a few screenshots:

Since this is all done on the GPU (unless you are using the software renderer), applying one of these filters does not affect performance much, as can be seen in this screencast of the fishbox demo:

Expect to see more uses of these new capabilities in GTK+ as things progress. Fun times ahead!

On recipes, one more time

I’m still not quite done with this project. And since it is vacation time, I had some time to spend on it, leading to a release with some improvements that I’d like to present briefly.

One thing I noticed missing right away when I started to transcribe one of my mothers recipes was a segmented ingredients list. What I mean by that is the typical cake recipe that will say “For the dough…” “For the frosting…”

So I had to add support for this before I could continue with the recipe. The result looks like this:

Another weak point that became apparent was editing the ingredients on the edit page.  Initially, the ingredients list was just a plain text field. The previous release changed this to a list view, but the editing support consisted just of a popover with plain entries to add a new row.

This turned out to be hard to get right, and I had to go back to the designers (thanks, Jakub and Elvin) to get some ideas.  I am reasonably happy with the end result. The popover now provides suggestions for both ingredients and units, while still allowing you to enter free-form text. And the same popover is now also available to edit existing ingredients:

Just in time for the Christmas release, I was reminded that we have a nice and simple solution for spell-checking in GTK+ applications now, with Sébastian Wilmet’s gspell library. So I quickly added spell-checking to the text fields in Recipes:

Lastly, not really a new feature or due to my efforts, but Recipes looks really good in dark as well.

Looking back at the goals that are listed on the design page for this application,  we are almost there:

  • Find delicious food recipes to cook from all over the world
  • Assist people with dietary restrictions
  • Allow defining ingredient constraints
  • Print recipes so I can pin them on my fridge
  • Share recipes with my friends using e-mail

The one thing that is not covered yet  is sharing recipes by email. For that, we need work on the Flatpak side, to create a sharing portal that lets applications send email.

And for the first goal we really need your support – if you have been thinking about writing up one of your favorite recipes, the holiday season is the perfect opportunity to cook it again, take some pictures of the result and contribute your recipe!

 

Another look at GNOME recipes

It has been a few weeks since I’ve first talked about this new app that I’ve started to work on, GNOME recipes.

Since then, a few things have changed. We have a new details page, which makes better use of the available space with a 2 column layout.

Among the improved details here is a more elaborate ingredients list. Also new is the image viewer, which lets you cycle through the available photos for the recipe without getting in the way too much.

We also use a 2 column layout when editing a recipe now.

Most importantly, as you can see in these screenshots, we have received some contributed recipes. Thanks to everybody who has sent us one! If you haven’t yet, please do. You may win a prize, if we can work out the logistics :-)

If you want to give recipes a try, the sources are here: https://git.gnome.org/browse/recipes/ and here is a recent Flatpak.

Update: With the just-released flatpak 0.8.0, installing the Flatpak from the .flatpakref file I linked above is as simple as this:

$ flatpak install --from https://raw.githubusercontent.com/alexlarsson/test-releases/master/gnome-recipes.flatpakref
read flatpak info from GTK_USE_PORTAL: network: 1 portal: 0
This application depends on runtimes from:
 http://sdk.gnome.org/repo/
Configure this as new remote 'gnome-1' [y/n]: y
Installing: org.gnome.Recipes/x86_64/master
Updating: org.gnome.Platform/x86_64/3.22 from gnome
No updates.
Updating: org.gnome.Platform.Locale/x86_64/3.22 from gnome
No updates.
Installing: org.gnome.Recipes/x86_64/master from org.gnome.Recipes-origin

1 delta parts, 5 loose fetched; 20053 KiB transferred in 8 seconds 
Installing: org.gnome.Recipes.Locale/x86_64/master from org.gnome.Recipes-origin

5 metadata, 1 content objects fetched; 1 KiB transferred in 0 seconds

GNOME loves to cook

GNOME needs a recipe app, since we all love to cook.org-gnome-recipesThis is not a new idea. Looking all the way back to 2007, the idea of a GNOME cook book already existed back then. For one reason or another, we never quite got there. But the idea has stuck around.

screenshot-from-2016-12-02-08-39-17

With the upcoming 20th birthday of GNOME next year, some of us thought that we should make another attempt at this application, maybe as a birthday gift to all of GNOME.

Shortly after GUADEC, I got my hands on some existing designs and started to toy around with implementing them over a few weekends and evenings. The screenshots in this post show how far I got since then.

screenshot-from-2016-12-02-08-39-33

Why did I start to write this app from scratch (instead of e.g. trying to give a face-lift to venerable gourmet)  ?

Beyond the obvious reason that I love to code as much as I love to cook, I wanted to give GNOME Builder a more serious test by starting an application from scratch. And I find it very useful to take a look at GTK+ from the application developer side, every now and then.  In both of these regards, the endeavor was already successful and has yielded improvements to both GNOME Builder and GTK+.  For the cooking part, you can judge that for yourself.

screenshot-from-2016-12-02-08-46-17

The main reason for writing this post is that we are at a point now where we need contributions to make progress. The idea is that we will include a decent set of recipes from GNOME contributors all over the world with the application.

Therefore, we need your recipes, ideally with good photos.

All the photos and text you see in the screenshots here are just test data that I’ve used during development, and need to be replaced with actual content.

So, how can you contribute your favorite recipes ?

Add your recipe to the app, and when you are satisfied with how it looks, you can use the Export button on the details page to create an archive with the recipe and related information, such as images. The archive also includes information about the author of the recipe (ie yourself), so make sure to provide some information for that in the Preferences dialog.

We just created a bugzilla project for recipes, so you can just attach the archive to a bug:

https://bugzilla.gnome.org/page.cgi?id=browse.html&product=recipes

Please make it clear in the bug that all the included images are your own and that we are allowed to ship it with the app.

screenshot-from-2016-12-02-08-44-40

Beyond recipes, there are plenty of other ways to contribute, of course. While I’ve tried hard to get many of the features in the initial design implemented, there is a lot more that can be done: for example, unit conversion, or a way to easily share recipes, or to print a shopping list.

screenshot-from-2016-12-02-08-39-43

Where do you get it ?

The project started out on github, but it is also available on git.gnome.org now. The design materials are collected on the GNOME wiki.

If you just want to try it out without building it yourself,  you can just use Flatpak:

flatpak install --from https://alexlarsson.github.io/test-releases/gnome-recipes.flatpakref

Of course, I did not get this far on my own. Thanks are due to several people. First and foremost, Emel Elvin Yıldız, for the designs and feedback on the implementation, Jakub Steiner for the icon and visuals, and Christian Hergert for keeping this idea alive and for making GNOME builder work great.

Help, my app icon is missing!

I was in this situation recently: An application icon would not show up in GNOME shell, even after I double- and triple-checked that I did all the right things:

  • Installed the desktop file with the right name in /usr/share/applications
  • Installed the icon with the right name in the hicolor icon theme
  • Make sure that Icon key in the desktop file has the right name
  • Restart GNOME shell (this is necessary due to a bug where GNOME shell will not reliably pick up  desktop file changes)

Still, I just get the generic executable icon: missing-icon1

GNOME shell to the rescue

I asked GNOME shell maintainer Florian Müllner for help. He said: GNOME shell is probably picking up a stale desktop file from somewhere.

But from where ? I checked all the locations listed in XDG_DATA_DIRS to no avail.  At this point, I was getting desperate,  so I went back to Florian. He said: Just use looking glass to find out! If you don’t remember, looking glass is a pretty handy debugging console that is built right into GNOME shell. You open it by typing the command

lg

Into the Alt-F2 run dialog.

missing-icon2This brings up the looking glass. Here is how it helped me solve my problem:

missing-icon3I switched to the window tab, then clicked on the application in question, and hit the ‘Insert’ button. That binds the object to a variable named r(x) (for some number x)  in the Javascript evaluator.

Going there, I then typed the command

r(3).app_info.get_filename()

And that showed the problematic desktop file:

missing-icon4I removed that file and restarted the shell once more, and now everything is working as it should:

missing-icon5Thanks, looking glass!

Another GTK+ update

The GTK+ 4 work is continuing at full speed, and today I want to show one of the first concrete benefits from  the GSK merge: We can now record and replay frames. If you ever wondered why your animation does not look quite right, this might be just the tool for you.

To try this new tool, find the Recorder tab in the GTK+ inspector, and use the record button. As you can see, we capture and save the render node tree for each frame that the application draws, as long as recording is enabled (you want to be a bit careful, this is quickly eating up a lot of memory).

The leftmost pane lets you select one of the recorded frames. The middle pane shows the render node tree, and if you select a node there, the rendering on the right is updated to show only that subtree’s effect on the frame.

This is pretty nifty, and will hopefully be very useful in improving the GSK integration in GTK+, as well as helpful for debugging rendering problems in applications.

GTK+ happenings

I haven’t written about GTK+ development in some time. But now there are some exciting things happening that are worth writing about.

Plans

Back in June, a good number of GTK+ developers came together for a hackfest in Toronto,  It was a very productive gathering. One of the topics we discussed there was the (lack of) stability of GTK+ 3 and versioning. We caused a bit of a firestorm by blogging about this right away… so we went back to the drawing board and had another long discussion about the pros and cons of various versioning schemes at GUADEC.

GTK+ BOF in Karlsruhe

The final, agreed-on plan was published on the GTK+ blog, and you can read it there.

Actions

Fast-forward to today, and we’ve made good progress on putting this plan into place.

GTK+ has been branched for 3.22, and all future GTK+ 3 releases will come from this branch. This is very similar to GTK+ 2, where we have the forever-stable 2.24 branch.  We plan to maintain the 3.22 branch for several years, so applications can rely on a stable GTK+ 3.

One activity that you can see in the branch currently is that we are deprecating APIs that will go away in GTK+ 4. Most deprecations have been in place for a while (some even from 3.0!),  but some functions have just been forgotten. Marking them as deprecated now will make it easier to port to GTK+ 4 in the future. Keep in mind that deprecations are an optional service – you don’t have to rush to act on them unless you want to port to the next version.

To avoid unnecessary heartburn and build breakage, we’ve switched  jhbuild, GNOME continuous and the flatpak runtimes over to using the 3.22 branch before opening the master branch for  new development, and did the necessary work to make the two branches parallel-installable.

With all these preparations in place, Benjamin and Timm went to work and did a big round of deprecation cleanup. Altogether,  this removed some 80.000 lines of code. Next, we’ve merged Emmanueles GSK work.  And there is a lot more work queued up, from modernizing the GDK layer, to redoing input handling, to building with meson.

The current git version of GTK+ calls itself 3.89, and we’re aiming to do a 3.90 release in spring, ideally keeping the usual 6 months cadence.

…and you

We hope that at least some of the core GNOME applications will switch to using 3.90 by next spring, since we need testing and validation. But… currently things are a still a bit rough in master. The GSK port will need some more time to shake out rendering issues and make it as fast as it should be.

Therefore, we recommend that you stick with the 3.22 branch until we do a 3.89.1 release. By that time, the documentation should also have a 3 → 4 migration guide to help you with porting.

If you are eager to get ready for GTK+ 4 now, you can prepare your application by eliminating the deprecations that show up when you build against the latest 3.22 release.

Summary

This is an exciting time for GTK+ ! We will post regular updates as things are landing, but just following the weekly updates on the GTK+ blog should give you a good idea of what is going on.

Using modern gettext

gettext has seen quite some enhancements in recent years, after Daiki Ueno started maintaining it. It can now extract (and merge back) strings from diverse file formats, including many of the formats that are important for desktop applications. With gettext 0.19.8, there is really no need  anymore to use intltool or GLib’s dated gettext glue (AM_GLIB_GNU_GETTEXT and glib-gettextize).

Since intltool still sticks around in quite a few projects, I thought that I should perhaps explain some of the dos and don’ts for how to get by with plain gettext. Javier Jardon has been tirelessly fighting a battle for using upstream gettext, maybe this will help him reaching the finish line with that project.

Extracting strings

xgettext is the tool used to extract strings from sources into .pot files.

In addition to programming languages such as C, C++, Java, Scheme, etc, it recognizes the following files by their typical file extensions (and it is smart enough to disregard a .in extension):

    • Desktop files: .desktop
    • GSettings schemas: .gschema.xml
    • GtkBuilder ui files: .ui
    • Appdata files: .appdata.xml and .metainfo.xml

You can just add these files to POTFILES.in, without the extra type hints that intltool requires.

One important advantage of xgettext’s xml support, compared to intltool, is that you can install .in files that are valid; no more tag mutilation like <_description> required.

Merging translations

The trickier part is merging translations back into the various file formats. Sometimes that is not necessary, since the file has a reference to the gettext domain, and consumers know to use gettext at runtime: that is the case for GSettings schemas and GtkBuilder ui files, for example.

But in other cases, the translations need to be merged back into  the original file before installing it. In these cases, the original file from which the strings are extracted often has an extra .in extension. The tool that is doing this task is msgfmt.

Intltool installs autotools glue which can define make rules for many of these cases, such as @INTLTOOL_DESKTOP_RULE@. Gettext does not provide this kind of glue, but the msgfmt tool is versatile enough that you can write your own rules fairly easily, for example:

%.desktop: %.desktop.in
        msgfmt --desktop -d $(top_srcdir)/po \
               --template $< -o $@

Extending gettext

Gettext can be extended to understand new xml formats. To do so, you install .its and .loc files. The syntax for these files is explained in detail in the gettext docs. Libraries are expected to install these files for ‘their’ formats (GLib and GTK+ already do, and  PolicyKit will do the same soon.

If you don’t want to wait for your favorite format to come with built-in its support, you can also include its files with your application; gettext will look for such files in $XDG_DATA_DIRS/gettext/its/.

 

Portals: Using GTK+ in a Flatpak

The time is ripe for new ways to distribute and deploy desktop applications: between snappy, Flatpak, AppImage and others there are quite a few projects in this area.

Sandboxing

Most of these projects involve some notion of sandboxing: isolating the application from the rest of the system.

Snappy does this by setting environment variables like XDG_DATA_DIRS, PATH, etc,  to tell apps where to find their ‘stuff’ and using app-armor to not let them access things they shouldn’t.

Flatpak takes a somewhat different approach: it uses bind mounts and namespaces to construct a separate view of the world for the app in which it can only see what it is supposed to access.

Regardless which approach you take to sandboxing, desktop applications are not very useful without access to the rest of the system.  So, clearly, we need to poke some holes in the walls of the sandbox, since we want apps to interact with the rest of the system.

The important thing to keep in mind is that we always want to give the user control over these interactions and in particular, control over the data that goes in and out of the sandbox.

Portals

The flatpak story for this has been portals. To quickly summarize: Portals are high-level (in the sense that they talk about concepts that are relevant to users) APIs that let sandboxed applications request access to resources outside. Portal calls will (almost) always involve user interaction (basically, a dialog).

We have talked about portals for quite a while, see for example this post by Allan from two years ago. Therefore,  I am very happy to announce that we now have first release of the portal infrastructure :

Note that the portal APIs themselves are desktop-neutral, and we have separated the implementation using GTK+ dialogs into their own module. We are also working on a qt/KDE  implementation.

The  APIs included in these releases cover a lot of basic things:

  • opening files
  • opening uris
  • printing
  • taking screenshots
  • notifications
  • inhibiting screen lock
  • network status
  • proxy information

Using portals in apps

The good news is that most of these will just work transparently in GTK+ applications, since GTK+ and GLib have suitable APIs that can be made to use the portals without any changes required from the sandboxed application. This support is already in place in the master branches; and will be in the 3.22 releases. We are working on a similar level of support for qt/KDE.

In detail, for opening files, you can use GtkFileChooserNative (a file chooser implementation that will also use a native Windows filechooser if you are on that platform). GtkFileChooserButton will do this for you, unless you manually set its dialog to something else. Certain things will not work with the portal, such as previews, or adding extra custom widgets.

For printing, use GtkPrintOperation (again a long-standing GTK+ api that will use a native Windows print dialog if you are on that platform).

For opening uris, use gtk_show_uri or g_app_info_launch_default_for_uri. We also added a new function that works slightly better in this context, gtk_show_uri_on_window().

Testing

As I said, most of the portals will just be transparently used by sandboxed GTK+ applications (provided they use GTK+ from git), but I’ve also written a portal-test application to try all the available portals.

portal-test

All of the tests use the regular GTK+ APIs, with the exception of the Screenshot button. Since we don’t have a screenshooting API in GTK+, that button makes a direct D-Bus call to the portal. Here is how it looks in action:

portal-test2

Whats next ?

For the first release, we’ve focused on portals for toolkit-level functionality. There is obvously a long list of other system integration points that will need to be covered. High up on our list for the near future are access to devices like webcams and microphones, and pulseaudio. If you are interested, the list of issues has some more information.

Update: I’ve been asked: Why do I need a portal, the file chooser in the libreoffice flatpak seems to work just fine ?! Most of the current flatpaks are shipping with a relatively open sandbox configuration that allows the application full access to the host filesystem, or at least to your entire home directory. Portals enable applications to  function in a constrained sandbox that does not have this.