Crosswords 0.3.12: Two-toned Editor

Happy 2024! It’s time for the first GNOME Crosswords update of the year. A ton of work happened since the last release — primarily in the Editor. I’ll try to keep this update short and sweet. Packages will be available in flathub momentarily.

Move to libadwaita-1.4

The biggest visual change is that we moved away from libpanel in the Editor window. I found I was fighting with that library constantly due to the mode changes in the Editor, and I wasn’t able to take advantage of many of libpanel’s cooler features. Ultimately, libpanel wasn’t designed for workspaces and it looked like it would be a prohibitive amount of work to add them. Instead, I’m using an AdwOverlaySplitView, custom paned widget, and a lot of GtkStacks. This results in a cleaner appearance at the cost of a lot of flexibility. As an additional plus, it gives the Editor the snazzy two-toned look that’s currently in vogue:

The plan for the bottom of the content section is to provide some useful information for whatever operation was being shown. I put in some rudimentary statistics about the grid, as well as some basic support for authoring clues. I added three simple sections just to get something up and running: Anagrams, Odds, and Evens. The anagram calculations was based on work done by Pratham for his GSoC project. I was able to finish it and incorporate it into the UI.

Also, note that the histogram bars are rendered via GtkLabels with repeated block characters (U+2588). Thanks to Christian for that great suggestion — it was a quick way to get something visible.

Stateless Apps

For this release, we fully embraced a stateless control flow for the Editor. Federico and I have been talking about this for a while and it took some experimenting to find a model that works well. But given the complexity of the app (data and flow), it ended up simplifying the codebase substantially.

A neat example of why this is useful: there are three distinct grids in the main content section for each stage (GRID, CLUES, and STYLE). Instead of using the traditional GtkStack to swap between them, I’m able to simply swap out the state to render the correct one.

What’s next?

Word data

It’s become clear that the most important feature needed for the editor to be competitive is to improve the word list and the clue authoring section. Both the data and the filtering code need to be revisited. The word list code was originally written just for the autofill dialog and had to be fast for that. But as it’s progressed we’ve needed a lot more flexibility with the filtering. I don’t want to implement full regexp support as it won’t be fast enough, but something like nutrimatic might be more warranted (though it can be slow as well).

The data, too, needs attention. The Broda word-list is serviceable, but provides options that aren’t appropriate for all puzzles. A co-worker pointed me to the free wordnik wordlist, which I was able to add as a compile-time alternative. Libreoffice also has its own wordlists, though they aren’t designed for puzzle writing. But beyond the words, I’m going to need:

  • Definitions of words
  • Synonyms of words
  • Multi-word combos (along with punctuation)
  • Word frequency counts, to give prioritization to words/phrases
  • Offline support. As much as possible, not requiring network access is preferred

In addition, to the extent there’s interest, I’d love to support this in other languages beyond English.

I know there are a number of options for these already for free desktops. If you work in this space (or are interested in seeing GNOME’s options improved here) drop me a line.


I also want to highlight that Tanmay has continued to work hard on Acrostic support long after his GSoC internship ended. Not content with just adding acrostic support to the game, he has been adding acrostics to the Editor as well. It’s turned out to be quite a hard problem, with a lot of algorithmic complexity involved with auto-generating the grid in a reasonable amount of time. It has also required him to fix issues all over the codebase (including in glib!) Great work, Tanmay!


  • Christian for libpanel advice and that cute histogram trick
  • Federico for helping me reason about complexity, CI fixes, and translations
  • Tanmay for tests and charset work (and future Acrostic work)
  • Pratham for anagram support (GSoC)
  • Rosanna for wording and UX suggestions
  • Davide for doc fixes and translations

Crosswords 0.3.11: Acrostic Panels

Long time, no release.

When I last blogged about GNOME Crosswords, I had a design plan to improve the editing API. It’s been a busy summer since then. The crosswords team rewrote large chunks of code to implement and use this new API:

crosswords: 146 files changed, 10545 insertions(+), 4915 deletions(-)
libipuz:  53 files changed, 8224 insertions(+), 961 deletions(-)

There’s now over 38KLOC between the two codebases — this is starting to look like a real application!

Editor and libpanel

The biggest change this cycle is the implementation of the new editing interface. I started changing the code five months ago, but it took a while to land. We now use libpanel from GNOME Builder to manage the information panels. Libpanel has a lot of the functionality I want, though unfortunately I’m fighting its geometry handling.

New grid editor panel
New grid editor panel
New clues editor panel
New clues editor panel

I really struggled getting the UI design for this to work, and I had a number of regrettable paths along the way. Fortunately, Niko agreed to help out with this, and showed up with some fabulous design work! I’m so much happier with the current approach, and am getting ready to implement more of his designs for the next cycle.

Behind the scenes, implementing this was a challenge. I blogged about those challenges previously, but in a nutshell, mutating a puzzle has a lot of side-effects which can leave you in an invalid state. For example, something simple like adding a block could completely change the numbering of the grid.

Federico and I fixed this by adding a number of functions to enforce heuristics and conventions. I also added ipuz_puzzle_fix_all() which will  get a fully well-formed puzzle regardless of the state. It’s turned out to be a really nice design pattern.

I have now released the Editor as a separate application in flathub. You can download it here.


Another major feature this release is Acrostic Puzzle support. Tanmay worked on that for his GSOC project and did fabulously (details in his blog post.) The end result is gorgeous:

Animation of an Acrostic puzzle being solved
Animation of an Acrostic puzzle being solved

I had a great time mentoring Tanmay for the summer, and we’re already making plans on how to add acrostic support to the Editor.


GUADEC in Latvia was a blast. Riga was fun, the countryside was surprisingly interesting, and the overall feel of the conference was lovely. As always, it was great to meet so many people, new and old.

Stone statue looking like a goomba
A wild Goomba in Riga

GNOME Superstar Martin came to my Crosswords BOF in Riga and got it running on an actual mobile device. The end result was.. actually usable! It seems like all the work we did on adaptive sizing paid dividends. There are some rough corners (and Martin filed a number of bugs) but it worked surprisingly well out of the box.

I also got to meet with my other GSOC student Pratham. His work on anagrams will land next release, so we’ll have more to talk about then.

The final thing mentioning is that I bought the domain for the library. Unfortunately the main site has been down all summer, I put a mirror of the ipuz spec up there so people can read it.

I also managed to reach Roy Leban by phone. He’s the original author of the ipuz spec, and was able to clarify some questions I had when interpreting it. This led me down a deep rabbit hole around the part of the spec regarding clue directions, as it required a substantial rewrite to avoid hardcoding Across/Down directions everywhere.

Finally, Pranjal showed up completely out of nowhere with an MR to add ipuz_puzzle_equal(). This was a tricky function to write, and one I’ve wanted for a really long time. This has been making all our tests so much better. Hero! Pranjal is interested in adding a sudoku loader/saver to libipuz — maybe there will be more in this space in the future.


  • Niko, for massive help with the designs for the Editor
  • Tanmay, for Acrostic support
  • Martin, for testing Crosswords on mobile
  • Pranjal, for ipuz_puzzle_equal()
  • Federico, for testing fixes and overall support
  • Rosanna, for continued advice and crossword support
  • Pratham, for initial anagram support
  • Bart, for whatever magic he did to make work
  • The translators, for keeping us multi-lingual

Until next time!

Crosswords 0.3.8: Change Management

It’s time for another Crosswords release. This is a somewhat quieter release on the surface as it doesn’t have as many user-visible changes. But like the last release, a lot happened under the hood in preparation for the next phase.

This release marks a change in focus. I’ve shifted my work to the editor instead of the game. I hadn’t given the editor much attention over the past year and it’s overdue for updates. I have a lot of features planned for it; it’s time to make progress on them.

Crosswords Editor

The first change I made was to give a revamp to the workflow for creating a new puzzle. The old editor would let you change the puzzle type while editing it — something that was technically neat but not actually useful to setters. I have different editing sections planned based on the puzzle type, which means that restricting a window to one type. For example, editing an acrostic grid is totally different from editing a crossword grid.

The new greeter also cleans up a  weird flow where the first tab would lock once you’d picked your initial values.

New greeter dialog for the Crossword Editor
New puzzle greeter

To do this, I added a greeter that lets you select the type of puzzle right from the outset. We also took advantage of the fact that we added a separate GType for each puzzle type. It’s very loosely inspired by the new project greeter from GNOME Builder.

The second thing I spent time on wasn’t actually a code change, but a design plan. An implementation challenge I’ve had is balancing letting people use all the crazy features that the ipuz spec allows, and adding guardrails to let people write standard puzzles without thinking about those extra features. The problem with those features is that you can easily end up in a legal-but-weird puzzle file. As an example, imagine a crossword where the numbering of all the clues are out-of-order. That’s a legal .ipuz file and possibly valid in fringe circumstances, but rarely what any puzzle designer actually wants.

There is a new design doc for how to handle intermediate states. The details are complicated, but the overall approach involves adding lint() and fixup() functions to the puzzle types. This will let us make the changes we want, but then let the editor get the puzzle back to a reasonable state.

Many thanks to Federico, who very kindly let me call him on the weekends to talk through the issues and iterate to a proposal. I’ve started updating libipuz to implement this new design.

Crosswords: Adaptive Layout

This is the third release that I will have blogged about the adaptive layout, and it’s the first time I feel good about the results. It has been incredibly challenging to get Crosswords to work well at a variety of sizes. This cycle, I introduced the concept of a both a natural size and a minimum size to the game. This results in a mixture of user control and screen-driven sizing. Here is an example of a crossword scaling to the very small and to the very large.

I hope I can put this feature down for now!

Misc fixes and thanks

There were a number of other fixes this release. Most excitingly, we have a number of new contributors too! Crosswords is a potential GNOME GSOC program and some perspective students spent time trying to learn the code base. Here are the improvements and credits.

Puzzle Set tagging dialog

  • First, we now render the puzzle set description labels to look more like tags. Thanks to Pratham for working on this.
  • Thanks to Tanmay for fixing a bug where horizontal clue enumerations weren’t rendering correctly. He also contributed fixes to keyboard layout dialog, and started a promising thumbnailer (targeting next release)
  • Thanks to Philip for layout fixes, a new icon, and for having a preternatural ability to find bugs in my code as soon as I declare them “done.”
  • I fixed an issue where we didn’t lock down the puzzle correctly after winning the game. I’ve been trying to track this down for six months.
  • Thanks as always to the  translators for translations.

Until next time!

Crosswords 0.3.7: Adaptive Layout, Animations, and Arrows

Howdy folks,

It’s GNOME Crosswords release time again! This is a big release with a lot of changes. Most importantly, I was able to find some time over the holidays to do some long-overdue refactoring of the core game code.

crosswords: 143 files changed, 12619 insertions(+), 5834 deletions(-)
libipuz:     41 files changed,  2345 insertions(+),  736 deletions(-)

A number of early design decisions haven’t panned out, and these decisions  held us back from doing some very basic things with the code. While not directly impactful on the user, this refactoring unlocked some long-overdue features. In addition, loading puzzles and puzzle sets are noticeably faster now.

In this post, I’m going to cover the mobile work, Arrowwords, the hackfest, and the new preferences dialog. Let’s take a look at what’s new:

Adaptive Layout and Animations

In the previous release, I tried to make Crosswords adapt to different screen sizes. It wasn’t all that usable, so I worked more on it this cycle.

First, the good news: I cleaned up a lot of the layout bugs, and (thanks to Carlos) got some form of touch screen keyboard input working. The end result is that I changed the appinfo file to indicate we supported all screen sizes and inputs, which means it should be available on all platforms.

I also had to put all the parts of the game into a custom container widget to get the spacing right. Once that was done, it was trivial to add some animations to it. It turns out AdwAnimation is really cool — and much easier to use then I had expected. I added animations to keep the puzzle centered and to align it vertically as appropriate. Here’s how resizing  now looks:

I’m pretty impressed with how easy it was to do things like this with GTK4.

Unfortunately, despite these changes, it’s not all good news. I don’t think the final results are compelling enough for mobile devices. The touchscreen input is flaky, and the onscreen keyboard isn’t great for crossword puzzles (and is so big!) I never really figured out how input was supposed to work together, and ended up just guessing until it mostly worked. I could really use better documentation on the onscreen keyboard! Or if someone explains it to me, I’m happy to write documentation for future users.

As I don’t actually have a mobile device that runs GNOME and I don’t have a touch screen, I’ve reached the limits of what I can do without additional help. I’d love feedback or advice from anyone who knows more about this space.


As part of the refactoring focus, I added a bunch of new puzzle types to libipuz (more on this in a future post!) One of these puzzle types was Arrowword puzzles — a crossword style more popular in northern Europe. This had been a semi-regular request and turned out to be easier to implement than expected. We were able to get something going relatively quickly.

I wrote the cell code, Federico helped with the svg overlay arrow rendering, and Philip helped with the testing and downloader. The end result is attractive:

Arrowword Crossword

Puzzle Sets

Due to the big holiday refactor, I was able to add a few small features I’ve wanted to add for a while. First, I changed Puzzle Sets to be opt-in. We’ve ended up accruing so many of them that it makes sense for people to choose the ones they want to play.

Along the way, I added extensions  to the puzzle sets to tag them so users can see more information before trying them. Here’s the dialog to select them.

Puzzle Set selection dialog

Additionally, I added an option to let you hide puzzles that have already been solved. This was another requested feature as the list of puzzles can get quite long.

Finally we show how many puzzles remain unsolved in the main screen. This should have been a simple feature to add, but the old code base made it surprisingly hard to implement. With the rewrite, this was only a few lines of code:

New Main screeen
The new main screen

You can also see an “Add More Puzzles” button in that screenshot.


We held a virtual hackfest a few weekends ago! Four people showed up, and we focused on getting this release out the door. We got most of the last release blockers done during it. Davide added Italian puzzle sets and translations, and fixed the packit CI. Rosanna finished the GNOME Mini Crosswords set and started a new, alphabetically-themed one. Federico documented how to run crosswords out of podman and got the Arrowword SVG overlay themed and working. I landed the final fixes for the tagging, and landed a bunch of build fixes to the puzzle sets.

It was a lot of fun. I will try to hold another one at the end of the next release cycle.

GNOME Mini Crosswords

What’s next?

  • We’ve wanted to add autodownload-on-start for a while, and it should be possible to do that now.
  • I don’t love the current preferences dialog. It could use some design attention and tweaks.
  • And finally, I plan to switch back to work more on the Crossword Editor. It’s overdue for some love.

Until next time!

Crosswords: Puzzle update

Happy New Year, Crossword-lovers!

This is a minor update in preparation for a bigger release in the next few weeks. We’ve done a lot of exciting work on Crosswords over the past few months that’s almost ready for release. However, there are a few things available already that I wanted to highlight early.


There are two updates to the puzzle sets. First, George Ho kindly agreed to add his puzzles to the contrib puzzle-set. He’s written ten fun puzzles with the promise of more in the future! I really enjoyed solving them. There are also a few additional not-for-distribution ones available at his site.

loplop puzzle set

George has put together a truly impressive dataset of cryptic crossword clues. He’s gathered and categorized half-a-million clues over twelve years of puzzle data. I’m really impressed with this work and I’m looking to integrate some of that data into the Crossword Editor this coming year.

Second, I updated the xword-dl plugin to work with latest version of that app. Those folks have been really busy the past few months, and over ten more puzzle sets were added to it, including our first German source (Hint: a German translation would be appreciated). Our launch screen has gotten a lot fuller with both downloaders and shipped puzzles: we now have over 50 possible puzzle sets for playing across three languages.

Despite the ritual pain and suffering  with pip to get it building in a flatpak (NB: still relevant), I managed to get it updated. I’m really impressed at how that project grew in 2022. Great work!

These are available at flathub.

Developer Documentation

Federico gave me an early Christmas gift this year! He set up a developer guide for Crosswords to be built automatically from CI. It’s gorgeous, and hopefully will entice folks to join the rest of us working on the app.

A major goal I’ve had while writing this is to keep it well documented. A few weeks ago, Federico wrote beautifully about the power of documentation. As the game has grown past 30KLOC I’ve found it super valuable to reread what I wrote when revisiting older code sections. Writing the design docs has had a clarifying effect too: I had to write the WordList docs before I could finish that code, and I refresh my memory from it every time I have to touch it.

However, one thing I didn’t have was a good way to tie it all together. Now that we have this site, it’s possible to explain how things fit together. I spent some time this vacation putting together some introductory docs to make it easier to get started with the code base. If you have any interest in contributing, check them out.

What’s next?

We are gearing up for a big release in a few weeks with a lot of changes. They’re mostly internal cleanups, but these changes are already making some new features much easier to write. Here’s a preview of one them that’s in progress:

Can you guess what this will be?

The other thing I’d like to do is to hold a virtual hackfest this weekend. The exact time and date is still TBD pending some availability, but I’ve been meaning to get together with a few folks to work on some of the code together. I don’t know how well this will work virtually, but its worth a shot to open it up to a wider audience.

If you’re interested at all in word games and free software, feel free to drop by #crosswords. While there, let us know if you’re interested in the hackfest. All people are welcome. Come add a feature, add a translation, or try your hand at writing a puzzle. Or just hang out and tell us your favorite clues.

Until next time!

Download on FLATHUB

Crosswords 0.3.6: “The Man from G.N.O.M.E”

Note: a half-written version of this blog post was accidentally published earlier, and was briefly picked up by The [Publish] and [Preview] buttons are unfortunately right next to each other 🙁


It’s time for another GNOME Crosswords release! This one is particularly exciting to me as it brings a lot of new content. The major highlights include new puzzles, a new distribution channel, and the start of adaptive behavior with an eye to working on mobile. It’s available for download in flathub.

New Puzzles

First — and most important — is the addition of new puzzles. We added three more puzzle sets from different sources. I wrote to a number of crossword creators in the local FOSS community and asked if I could include their puzzles in this release. Thanks to Bob, Carl, and dew.mountain for kindly agreeing to add their puzzles to the distribution.

Next, Rosanna and I sat down and together wrote some quick mini-puzzles. These were pretty  fun to create, so hopefully we can build a good collection over time. Let us know if you’re interested in helping us.

Finally, I wrote to Māyā of Auckland to ask if they minded if I included their puzzles. Māyā writes cryptic crosswords that are of a very high quality — and that are a lot of fun to solve. They very kindly agreed to let me distribute them, so I’ve included ~90 cryptics.

This adds up to over 100 new puzzles available in this version.

Adding these puzzles took a surprising amount of time. They ended up highlighting a half-dozen or so bugs in the code base, and lead to substantial rewriting of a number of sections. In detail:

  • One of Bob’s puzzles came in puz format and used circled letters, so I added circle support to the puz importer. This is used fairly commonly. Now that we support it, I’m noticing circles a lot more in the wild.
  • Some of Māyā’s puzzles were made available in JPZ format. As a result, I finally wrote a convertor for this format. I also refactored the convertor to make it possible to add other formats in the future.
    NOTE: I did not have a lot of jpz puzzles to test while writing this. If you have some, please try this feature out and let me know if it doesn’t load correctly.
  • Māyā’s puzzles also thoroughly broke the enumeration code. The old regex-based parser wasn’t good enough to handle them, so I wrote a state-machine-based parser to handle this properly. There were really cute enumerations in those puzzles like:

    After first first exchange, 10 relates to blood vessels (7-)
    Solo star of this? Yes and no (3,3,4, couldn’t be parsed with the old approach.
  • These puzzles also forced me to get much more strict about the text handling. The ipuz spec allows a subset of html in certain tags, and you certainly run into puzzles with this in the wild. Complicating matters, you also come across random ampersands (&) that weren’t escaped, as well as other random entities.I wrote a simple html_to_markup() function that parses html (as best as I can) and converts it to valid GMarkup tags to pass to labels. This is mostly a matter of handling entities and escaping unknown tags, but there were definitely some subtleties involved. If someone has a better version of this functionality, let me know. On the other hand, maybe this implementation is helpful to someone else out there.

Thanks again to these puzzle authors!

Adaptive layout

The next big feature we added is making Crosswords work well at different screen sizes. I had a couple requests to make this work on mobile devices and Sam did a great design, so we tried to make this plausible. Unfortunately, there’s not a lot of formal guidance as to what’s needed here, other than to support small screens. I’d love if the GNOME Mobile folks would put together a checklist of things to support, as well as instructions as how best to test / simulate that environment without having dedicated hardware.

Nevertheless, we now support smaller screens! Here’s a video of it in action.

To make this work proved to be pretty tricky, as that packing is impossible to do with a standard GtkBox layout. The challenge is that that scrolled window holding the grid needs to have vexpand=TRUE set, but also have a maximum size so that the clue at the bottom doesn’t extend beyond the grid. I finally gave up and wrote a custom widget to do this sizing:

Note: I got a lot closer to a working solution with constraints, and was really impressed with how well they worked. Emmanuele has done a fantastic job with them. There’s a bit of a learning curve to get started, but they’re definitely worth a second look if you haven’t tried using them before. They’re more powerful than regular box-based solutions, and ended up being easier to maintain and experiment with.

For the sizing behavior to feel right, I also wrote code to restore the window size on restart. Fortunately, there’s a great example of how to do this in the tutorial. Unfortunately, the example doesn’t work correctly. After figuring out why, I wrote an MR to fix the documentation. Unfortunately I don’t know vala well enough to update that example, maybe someone who does can help me update it?


One more fantastic contribution arrived  towards the end of the release cycle: Davide and Michel packaged Crosswords for Fedora. I had never actually tried to install the game locally, but meson magically worked and they got it built. Now, running ‘sudo dnf install crosswords‘ works with f36/f37. As it’s Fedora, I may have to spend some time next cycle to straighten out all the licenses across the code base and puzzles, but that’s time worth spending.

One spooky Halloween-themed bug came with this work: word-list-tests test failure on s390x. That’s a category of bug I never expected to have to deal with ever again in my life!

In general, I’m really excited about the future of flatpak and what it means to the larger Linux ecosystem. I will continue to focus my efforts on that. But having it on Fedora is nice validation, and hopefully will lead to more people solving crosswords. I’d love it if other distros follow suit and ship this as well.

Odds and Ends

Other fixes this cycle include:

  • Massive cleanup to event code (Federico). This was huge, and moves us to a simpler event system. Really appreciated!
  • Also, Federico let me call him a couple Saturdays to get general design advice
  • New setting to avoid changing crossword direction when arrowing through the grid (Jonathan and Rosanna)
  • Mime types defined for ipuz, jpz, and puz files (Davide)
  • Cleanup of the color and contrast of shapes in cells (Jonathan)
  • New Italian translation (Davide)
  • MacOS fixes and testing (Vinson)
  • Loads of bug fixes (all)

Until next time!

Crosswords 0.3.5: Border Styles

It’s time for another GNOME Crosswords update. We’ve been busy since GUADEC and have managed to add quite a few user-visible features. We also fixed a bad bug where undo would break autosaving and added French translations. Buckle up, as this release goes to eleven!

As always, this is available on flathub.

Border Style

The first big feature in this release is recoloring the borders between cells. We previously had a single color (black) between the cells no matter what cell type it was. The recoloring is a subtle change, but I think it makes the puzzle look a lot smoother. We go with light borders between open cells, darker borders between blocks, and a really dark border around the outside. We also interpolate colors between cells with a background color explicitly set and to emphasize the cursor. Getting the details right took a good number of iterations but I’m happy with the ultimate effect.

This also validates the decision to create a widget for each border segment, as it made this a lot easier to implement. We use CSS styles to manage all the color combinations.

Border style comparison: new (upper-left) vs old (lower-right)
Highlight of border colors
Border styles with colored backgrounds
Acrostic puzzles also look cleaner

SVG Overlay

The next big feature we added was an SVG overlay over the puzzle. This lets us add graphics that extend beyond the borders of the existing widgets. Doing this lets us finally support enumerations in puzzles.

What’s an enumeration? Some crosswords let you know how many words follow a clue. It does this by putting hints in parentheses. It can also indicate punctuation where appropriate. As an example, (2-6,7) matches “GO-FASTER STRIPES” in 7dn in the puzzle below. In paper crosswords, solvers will often mark these hints in the grid with a pencil. We now do that on their behalf.

Enumerations rendered in the grid

We can also use the svg overlay to support barred crosswords. These puzzles look really cool – though are notoriously difficult to create and solve. I don’t know if we’ll get a good source for these until we seriously improve the editor, but I ported an existing one to .ipuz for testing purposes.

Barred crossword

Multi-character Support

I wasn’t fully happy with the state of editing when the IJ digraph support landed a few releases ago. The input method ended up being pretty obscure. As a result, I added generic multi-character functionality to the game. This feature will let you enter an arbitrary number of characters in a single cell. This is necessary for rebus-style crosswords which you occasionally find in the wild. It can also be used for the Dutch IJ as a more standard entry. You can enable this mode this by typing Ctrl-<period> or Escape.

Rebus-style crossword

This adds exciting functionality for fellow, faux, heavy-metal enthusiasts! We can now enter multi-character glyph. Behold:

Not the real answer, but close!

I’ve always wanted to do a puzzle with “SPıN̈ALTAP” as an answer. The N-diaresis doesn’t have its own unicode glyph and requires a combining character to work (u308). This feature lets you type it into the puzzle.

Keyboard Preferences

I’ve been involved with GNOME long enough to have a healthy suspicion of preference dialogs, and I resisted adding one for a long time. Unfortunately, there’s one preference that I’ve found I can’t avoid. Some people really like their online crossword widget to skip over letters when entering and some like them to overwrite letters — and there’s not a lot of compromise between the two sides. This has been the biggest behavior request I’ve received since releasing this game.

One of the goals this cycle was to refactor the internal state mechanism to make it cleaner (design doc). Along the way, it made this behavior change a lot easier to write.

This concept is so hard to explain! Anyone have suggestions for better text?

GNOME Contributor’s Puzzle Set

One last thing worth mentioning is a new puzzle-set (repo here). Since starting this project, I’ve had a few people send me puzzles to include, and we haven’t had a good place to put them. I created this as a place to ship puzzles from the wider GNOME-community. To start with, we’re including a handful of mini-puzzles and have started adding some standard ones. As soon as we get a bit more critical mass I’ll ship it via flathub.

If you’re interested in trying your hand at writing a crossword, this is a good way to make it available. Let me know if you’re interested.


Thanks to Federico for massive help and advise with the PlayState refactor, and for providing an SVG widget for the overlay. Hopefully GtkImage will get scalable SVG support in the future.

Thanks to Bob for finding and fixing a number of memleaks, and to the translators for language support.

Thanks to Zana and Carl for contributing puzzles.

And thanks to you for reading this far!

Download on FLATHUB


GNOME Birthday Cake

It was really lovely to get back to GUADEC. I loved being around old friends and meeting the new faces within the project. The venue was stellar and I thoroughly enjoyed a lot of the talks this year.

For me, my favorite talks were the progressive webapps talk by Phaedrus Leeds, Federico’s meme-filled talk on accessibility, and Rob’s talk about the Endless deployment to Oaxaca, Mexico.

[Note: I hope someone goes back to the youtube videos and adds timestamps / links to all the talks. It would be easier to find and browse  them. ]

On my part, I gave a talk on GNOME Crosswords and participated on a panel on how to get a Job with Free Software. The crosswords talk in particular seemed pretty successful. It had a great article written about it in (thanks Jake!), which lead to an increase in bug reports and crossword contributions.

One observation: it felt that attendance was down this year. I don’t know if it was Covid or Mexico, but some combination led to a smaller crowd than usual. I saw that there was a mini-GUADEC in Berlin as well (which I’ll assume was a lagging indicator of the above and not a cause.)

If we continue to have remote GUADECs in the future, I hope we can find a way to do a better way of connecting people across the conferences. One of the real advantages of GUADEC is it is a place for the project to unify and decide on big things collectively, and I’d hate for us to develop schisms in direction. I didn’t feel particularly connected to the folks in Berlin, which is a shame. I’d love to see them again.

Hopefully a few more of us can get together in Riga next year! But if we can’t, I hope we can find better ways to be more inclusive for remote events and individuals.

Crosswords Bof

Crosswords BoF
Crosswords BoF at GUADEC

There was enough interest from the Crosswords talk that we were able to hold an impromptu BoF on Saturday. Seven people showed up to work on various aspects of the game. We tested the existing puzzles, wrote some new puzzles, and added some additional features. Great progress was made towards UTF-8 support for the WordList, and some initial Printing support was coded.

More importantly, we were able to clean up a bunch of small papercuts. We tweaked the colors and controls, and also added acrostic support. The end result is a lot of visual tweaks to the game that improves the playability and appearance.

Acrostic puzzle featuring the new colors and crossed-out clues

I took a bunch of these improvements and packaged it up into a new release. It’s now available on Flathub.

Thanks to Rosanna, Neil, Federico, Heather, Jess, Dave, and Caroline for their contributions!
Download on FLATHUB


Mexico was lovely as always. I’ve always  wanted to visit Guadalajara, and it definitely met my (already high) expectations. It was a walkable city with lots of hidden spots and surprises in store. I’d love to go back sometime with a bit more time, and really explore it more thoroughly.

Guadalajara Cathedral and environs
Guadalajara Cathedral and environs
Arcos Vallarta near the venue
Arcos Vallarta, near the venue
Agave field in Tequila, Jalisco
Agave field in Tequila, Jalisco
GNOME Birthday party at Bariachi – a mariachi bar extrordinaire!
GNOME Birthday party at Bariachi – an amazing mariachi bar!
Cozy little bookstore
A cozy little bookstore
Guadalajara at night
Guadalajara at night

Crosswords 0.3.3: Double Dutch

It’s time for another GNOME Crosswords release! This time we had a focus on I18N support. I also got patches from another new contributor – Philip – who added some nice improvements, dutch-language support, and a downloader.

New features include:

  • A preferences dialog to let you filter puzzle sets by language. This gives us a way to only show puzzles either in your current language or in all languages. It opens the door for puzzle sets and downloaders in different languages.
  • Translation support. We have Dutch and Spanish translations now. It would be great to see more languages available for the next release.
  • Don’t grab focus when clicking on a clue. This was a small change that had a big impact on playability.
  • Copy/Paste support for the grid.
  • Undo/Redo support for the game.
  • Use the shiny new libadwaita AboutWindow.
  • Input now works on MacOS, making it fully playable on that platform.
  • Dutch-language crosswords work with the ‘IJ’ cell.

Wait, what’s that last one???

Amazingly enough, it turns out that Dutch crosswords allow an ‘IJ’ digraph in the same cell. This is an interesting twist on the crossword, as you can add an ‘I’ and ‘J’ character independently, as well as together.

Dutch puzzle showing IJ cell
Dutch puzzle showing an ‘IJ’ cell

To support this, I added a Quirks object that can be used to modify the behavior of the game. Beyond Dutch support, I started adding support for rebus-style crosswords as a second quirk. I imagine having to add more as we add additional language support.

Fortunately, we already supported strings within answers so this wasn’t too hard to implement. However, I’m not 100% sure I got the input controls correct. If you’re a Dutch crossword solver, I’d love to hear from you. I also hooked up the quirks to the help overlay so it only shows the special input mode when you have a puzzle that needs it (or are running it in Dutch).

I also added another extension to the .ipuz implementation to specify the locale of puzzles. We use that to filter puzzles, and add the quirks.

Lessons learned:

I thought I’d write down the things that I got stuck on this cycle in the hopes it saves other people time in the future:

Recoloring SVGs

GtkImage has the really convenient ability to recolor images when the appearance changes from light to dark. As far as I can tell, that functionality isn’t exported, so to use it you have to load the svg as a symbolic icon. Despite the documentation, it’s pretty finicky to get that correct so make sure to read all the documentation carefully. In addition, GtkImage really wants the image to be icon sized. You can override that with gtk_image_set_pixel_size().

recolored locked puzzles
Thanks to Sam for the new icons, shown here recolored.

Translating keyfiles with meson

We use keyfiles (aka, .desktop files) as a config file format to define the puzzle sets. These config files have user-visible strings added to them them, and then are compiled into a gresource file. This was surprisingly hard to get translated. Some notes:

  • xgettext supports –keyword=Keyword and -kKeyword to define custom keywords to translate. Unfortunately, despite being documented otherwise, msgfmt only supports –keyword=Keyword. Don’t use -k.
  • Meson doesn’t allow you to pass the language type to xgettext for an arbitrary file. In order to force it to use the correct type, I had to name my config file, and rename it to puzzle.config post-translation.
  • There’s no way for meson to have a compile-time dependency on the po files for i18n.merge_file(). In order to test it, I had to remove the translated desktop file in order to force rebuild it after every translation change. Meson 0.64 is supposed to fix this.

What’s next?

  • I’m giving a talk at GUADEC! Come hear the details of how this game was built and some interesting facts about crosswords. Sadly, I’m scheduled at the same time as the always-popular gnome shell update, but hopefully a few people will be interested in what I have to say.
  • To fully support internationalization, we need to support other languages for the wordlist. There’s an open bug for it. The work here shouldn’t be too hard, but will require a decent amount of work to make sure we’re multi-byte clean.
  • And as always, if you are interested in writing and publishing crosswords, let me know!

Download on FLATHUB


Crosswords 0.3

I’m pleased to announce Crosswords 0.3. This is the first version that feels ready for public consumption. Unlike the version I announced five months ago, it is much more robust and has some key new features.

New in this version:

  • Available on flathub: After working on it out of the source tree for a long while, I finally got the flatpaks working. Download it and try it out—let me know what you think! I’d really appreciate any sort of feedback, positive or negative.

  • Puzzle Downloaders: This is a big addition. We now support external downloaders and puzzle sets. This means it’s possible to have a tool that downloads puzzles from the internet. It also lets us ship sets of puzzles for the user to solve. With a good set of puzzles, we could even host them on These can be distributed externally, or they can be distributed via flatpak extensions (if not installing locally). I wrapped xword-dl and puzzlepull with a downloader to add some newspaper downloaders, and I’m looking to add more original puzzles shortly.

  • Dark mode: I thought that this was the neatest feature in GNOME 42. We now support both light and dark mode and honor the system setting. CSS is also heavily used to style the app allowing for future visual modifications and customizations. I’m interested in allowing  css customization on a per-puzzle set basis.

  • Hint Button: This is a late addition. It can be used to suggest a random word that fits in the current row. It’s not super convenient, but I also don’t want to make the game too easy! We use Peter Broda’s wordlist as the basis for this.
  • .puz support: Internally we use the unencumbered .ipuz format. This is a pretty decent format and supports a wide-variety of crossword features. But there’s a lot of crosswords out there that use the .puz format and a I know people have large collections of puzzles in that format. I wrote a simple convertor to load these.

Next steps

I hope to release this a bit more frequently now that we have gotten to this stage. Next on my immediate list:

  • Revisit clue formats; empirically crossword files in the wild play a little fast-and-loose with escaping and formatting (eg. random entities and underline-escaping).
  • Write a Puzzle Set manager that will let you decide which downloaders/puzzles to show, as well as launch gnome-software to search for more.
  • Document the external Puzzle Set format to allow others to package up games.
  • Fix any bugs that are found.

I also plan to work on the Crossword editor and get that ready for a release on flathub. The amazing-looking AdwEntryRow should make parts of the design a lot cleaner.

But, no game is good without being fun! I am looking to expand the list of puzzles available. Let me know if you write crosswords and want to include them in a puzzle set.


I couldn’t have gotten this release out without lots of help. In particular:

  • Federico, for helping to  refactor the main code and lots of great advice
  • Nick, for explaining how to get apps into flathub
  • Alexander, for his help with getting toasts working with a new behavior
  • Parker, for patiently explaining to me how the world of Crosswords worked
  • The folks on #gtk for answering questions and producing an excellent toolkit
  • And most importantly Rosanna, for testing everything and for her consistent cheering and support

Download on FLATHUB