Extending the month to infinity

Greetings! It’s been a long time since my last article.

I’d like to share some recent developments in GNOME Calendar that got some people really excited about: the infinitely scrolling month view.

The Now

Before GNOME 45, Calendar offers two views – week and month – as well as a sidebar with a list of events.

The headerbar offers controls to navigate back and forth in time. The effect of these controls depends on the current view: if you’re in the week view, going forward in time moves you a week ahead; in the month view, it moves you a month.

Both views have evolved to be strictly about their respective time ranges. That means the month view, for example, strictly deals with the current month. Days from other months that sneak into the view are not interactive, and it doesn’t show events on them. This has been a long-standing feature request in GNOME Calendar.

GNOME Calendar 44 (screenshot by @TheEvilSkeleton)

The week view doesn’t really suffer from the same problem, even though it has the same constraint, since weeks are not variable in length like months.

While this approach has served us well enough for more than a decade, it had significant usability issues. One of the primary goals of a calendaring application is to facilitate planning ahead. The static month view made harmed the usability of the application, in particular when in the last days of the month, since you could not see ahead without chaging the month entirely.

Another shortcoming of the static month view was scrolling. Because the view was bound to a particular month, there was no way to transition between months smoothly. I eventually added mouse & touchpad scroll support to it, but it has been a source of bugs and confusion since the view abruptly switches after an apparently random amount of scrolling.

Overall, despite the constant efforts to improve it, it felt like we were hitting the limitations of the current design. To the drawing board we needed to go.

New possibilities with GTK4?

GTK4 introduces a family of data-oriented widgets (GtkListView, GtkGridView, GtkColumnView) that are able to handle virtually endless datasets, we had a promising start with rethinking the month view. We could just stuff weeks into a GtkListView, or days into a GtkGridView, and be done with it, right?

Well, not quite.

There is a fundamental difference between datasets and timelines, which very directly informs the architecture of these GTK widgets: timelines are infinite, datasets are bounded.

No matter how many entries you add to a dataset, or how large you make that dataset, it will still have a countable number of items. Timelines are uncountably infinite, both towards the past and the future. ¹

This, by itself, directly affects the user interface we can present, and prevents us from using GtkListView, or pretty much anything that uses a GtkAdjustment as the underlying controller of position. I originally assumed that the number of workarounds to make a new month work with adjustment would be manageable, but after some weeks of experimentation, it became abundantly clear that this approach cannot work without either a massive number of hacks, and at the cost of maintainability and my own sanity.

Eventually I bowed to the fate, and wrote a completely custom layout for the new month.

Extending the month to infinity

As it happens so often in computing, we don’t necessarily have to implement material infinity to give people the impression of infinity.

The ultimate goal here is to make the month view smoothly scroll between weeks. In principle, the smallest way to create the illusion of infinity is to show current weeks, plus one or more offscreen rows above and below.

Due to the way calendars are stored by evolution-data-server, where data transfers happen over D-Bus, we have to be particularly careful to prefetch more events than visible onscreen, and keep them cached. Scrolling still changes the date range in which the month view operates – every time a week is moved up or down, we need to discard events of weeks that went out of range, and request events of week that are now within range.

All these range changes needs to be carefully managed so that we don’t blow evolution-data-server too much with range changes.

Fundamentally, the architecture of the new month view is based on a row recycling mechanism. Conceptually, the month view is just a list of rows, each row representing a week, laid out vertically given the available width. It’s as if the month view is a partial circular buffer of time. Moving the bottom row to the top, and vice versa, during scroll, allows the month view to keep a static number of row widgets allocated at all times,

After experimenting with different ranges and caching a bit, I’ve arrived at the wonderful number of 10 weeks of wiggle room – so in addition to the 5 visible week rows, there’s 10 weeks above them, and 10 weeks below them. This completely arbitrary value seems enough to cache just enough events for the transitions not to be noticeable.

The new month view can now anchor itself against any particular week, and is no more limited to a single month. On months that take precisely 5 rows, you’ll be able to see events from the previous and next month as well – something that’s been requested over and over for a long time now.

Most of the expected features – dragging events around, creating events, etc – continue to work exactly as they used to.

Touching the limits of infinity

Of course, being able to fetch, cache, layout, and render 25 weeks worth of events pushed Calendar’s backend to its limits. We had to make things fast, real fast, in order to keep up with e.g. scrolling at 60 FPS.

This was a good opportunity to revisit how the month view calculates the layout and overflow of each week. The layout algorithm had to be reworked almost from scratch, and I eventually figured out that it was still violating GTK4 layout rules during the layout phase – it was changing visibility of events during layout, which causes a relayout inside a relayout. These days, GTK4 has some tolerance for that, but after increasing the number of events by a factor of 5x, not even GTK4 could be so complacent with Calendar.

Now we pre-calculate the event layout while building up the list of events, and keep it cached in a size-agnostic way. During layout, it only resolves overflow, and it does so by carefully changing child visibility of the widgetry.

This not only enables the month view to actually render its contents, but we also don’t do any significant calculation at layout time, which makes Calendar smoother overall. Nice.

While developing this new month view, every single potential threading issue in Calendar showed up as a nasty crash as well. Most of them should be fixed now.

This, at last, allows us to have this nice, beautiful, smooth Calendar app:

The new month view in all its glory (credits to @TheEvilSkeleton again)

A story of ups and downs

It is not a secret that calendars aren’t the most exciting applications humankind has ever conceived. In an era where we have to look at hands to detect whether a picture is generated by AI; an era where we watch the dusk of both the eleventh and the 45-billion-dollar Xs; an era where we Linux has become a mainstream gaming platform, and all the problems that come with that; who on actual Earth gives a damn about a niche-of-a-niche calendar app?!

I do.

During the development of GNOME 45, I finally could squeeze some dry drops of free time to dedicate some love to Calendar again. It took some serious effort to make the new month view a reality, but looking at it now, I think it was worth it.

After the original maintainer and the main designer left the project and the community, around 2016, it felt a tad bit lonely. Motivation to continue working on was eroding at a slow but constant pace. Calendar’s issue tracker was out of control. The IRC and Matrix channels were dead. Attempts to get some funding for Calendar development led nowhere – who would be willing to pay people to work on such an uninteresting, unmarketable component of the desktop?! – and of course, there was no reason for day job to give me work time to dedicate to Calendar. The project was, by all measurements, a dying project. This was not healthy.

But lurking in the darkest corners of Canada, silent, and always on the watch, a night elf with personal investment in the project noticed the situation. And acted. Over the last couple of months, Jeff single-handedly tamed the issue tracker again; triaged and labeled every single issue; closed almost 300 issues; made everything actionable again; helped building up a roadmap; and, the most important to me, offered a friendly hand and brought back the fun of developing an open source app.

It made me realize that, contrary to what I believed for too many years, and despite not being exactly what’s advertised as free software culture, it really is all about people. The whole thing. Just being there, talking and discussing and having fun and eventually doing some contribution – that’s the sweet spot of free software culture to me. The reason I’m still involved with other GNOME projects? The people. The reason Calendar didn’t just die? The people.

I’m pretty attached to Calendar as it was the first project I contributed with code on GNOME, and it makes me happy to see that the project is slowly getting back to track, and a community is gathering around once again.

Join us in making this nice calendaring app at Matrix!


¹ – GNOME Calendar is resonably far from dealing with the granularity of Planck time!


12 responses to “Extending the month to infinity”

  1. This looks great; Google Calendar had free-scrolling months for a brief amount of time but sadly went back to paged view a few months later (…so its up/down hotkeys now page left/right), and I haven’t seen anything else implement this since then.

    Out of curiosity, does the infinite scroll remember selections even for recycled rows? Our workplace’s mail system has a webmail app that aggressively recycles list rows in such a way that it’s impossible to select more than 10-20 messages at a time (as soon as something scrolls away it gets deselected), and ever since I’ve become wary of such features…

  2. […] Georges Basile Stavracas Neto ☛ Georges Basile Stavracas Neto: Extending the month to infinity […]

  3. Watching the video at the bottom of the article, the new UI actually looks really confusing to me and seems like a downgrade. Hard to tell which specific month I’m looking at, or which cells go with which month.

    While I’m not necessarily against the infinite scrolling idea, I’d prefer the months to be separated into their own tables, instead of it just being one giant endless table of cells. For example, you have the heading “September” with a table below it; then as you scroll down the table ends, there’s another heading “October”, and a new table below that one.

    1. You can still use the Previous/Next month switching buttons, this doesn’t aim to take anything away from that.

      As for being able to visually tell month boundaries apart within the view itself, that was a problem before and remains a problem now, with some paths for potential design solutions being discussed in various tickets:

      https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/962
      https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1074
      https://gitlab.gnome.org/Teams/Design/whiteboards/-/issues/202

      1. Thanks for those links, Jeff!

        I, too, have been feeling confused with the new month view, and this could help a bit.

  4. Thank for your long work on Calendar. The first calendar application I enjoy to use 🙂
    Just my opinion, Calendar improved more than other applications in recent years.

    1. Thank you for your kind words 🙂

  5. Just want to second this – I hate calendar UIs universally. I love Gnome Calendar. Using it has gotten to be smooth, intuitive and pleasurable, in part due to some serious effort in good design, and in part due to the (also serious) effort in improving and polishing, and this looks to be yet another great improvement. Thanks for your work!

    1. Thank you for sharing some kind words too 🙂 I’m still unhappy with the poor legibility of the month view, and the poor accessibility of Calendar, but at least there’s people interested in helping with that now. Let’s see how things go.

  6. Just wanted to say Calendar is one of the apps I always use and I also quite enjoy the simple-looking UI. Of course there is a lot of room for improvements, but that can be said about everything….

    As a side note, about funding, I was wondering whether it might be a more realistic solution to gather funding for the Core GNOME apps as a whole rather than individual applications. Of course it will come with its own challenges but as for actually finding sponsors it might be a better option as “sponsoring Core desktop apps” definitely seems to have more weight than “sponsoring yet another calendar app”, especially in corporate settings.

  7. Thank you both for your work in this app! Thanks to it I’m able to see and edit calendars from Google and Nextcloud in one place, and in an app that looks awesome and feels integrated in GNOME.

    The UI has gotten much better in general, although the new month view has been very confusing for me. I guess I’ll have to relearn years of navigating monthly calendars as fixed pages. The open tickets about making the jump between months more clear will help a lot!

  8. Jeff Smith Avatar
    Jeff Smith

    It’s now difficult to tell which days go with which month. This is a big step backwards in terms of visual clarity.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.