Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to GTK4 and libadwaita for Linux #3069

Open
danyeaw opened this issue Jan 3, 2025 · 5 comments
Open

Upgrade to GTK4 and libadwaita for Linux #3069

danyeaw opened this issue Jan 3, 2025 · 5 comments
Labels
enhancement New features, or improvements to existing features. linux The issue relates Linux support.

Comments

@danyeaw
Copy link
Member

danyeaw commented Jan 3, 2025

What is the problem or limitation you are having?

The current implementation backend for Linux uses GTK3. While this was a great choice when Toga was first created, it is now in maintenance only mode. Apps written in GTK3 now look out of place on a new GNOME desktop and no longer have the modern feel that users are expecting when creating a new app. GTK4 and libadwaita have the following advantages:

  1. More modern looking including accent colors, window decorations, and dialogs
  2. Adaptability for different screen sizes and orientations (including Linux phones)
  3. Better performance with rendering done with render nodes and GPU offloading instead of frame rendering
  4. Event controllers
  5. Easier support for Composite Widgets

GTK4 was initially released 4 years ago, and it is in all distros at this point (even Debian stable). Libadwaita 1.0 is also everywhere, although some of the newer dialogs and widgets are supported up to version 1.6 which is the latest.

Describe the solution you'd like

Unfortunately, the GTK3 to GTK4 change is a breaking change and it would be a large project to upgrade all the Toga widgets. One approach to work on this would be to slowly transition by supporting both, and then remove the GTK3 calls once it has reached feature parity:

if Gtk.get_major_version() == 3:
    ...  # GTK3 calls
else:
    ...  # GTK4 equivalent

We could also set an environmental variable for development, and then load the right library version based on it:

import gi

gtk_version = "4.0" if os.getenv("TOGA_UPGRADE_GTK") == "4" else "3.0"

gi.require_version("Gtk", gtk_version)
gi.require_version("Gdk", gtk_version)

Describe alternatives you've considered

We could keep GTK3, maybe even theme it to make it look more modern like https://github.com/rafaelmardojai/firefox-gnome-theme.

Additional context

GTK3 Toga Hello World:
image
image

GTK4 and libadwaita Hello World:
image
image

@danyeaw danyeaw added the enhancement New features, or improvements to existing features. label Jan 3, 2025
@freakboy3742
Copy link
Member

Completely agreed that a migration to GTK4 is desirable, and ultimately inevitable; see #1935 for some previous discussion of this topic (and potential migration paths), and #1978 for an incomplete attempt at a port. That PR hasn't been updated in over a year.

There were a couple of impediments preventing completion of that PR - see the PR comments for details, but the biggest was that we couldn't run CI with GTK4 because we were using Ubuntu 20.04 for CI testing, and there was no GTK4 libraries for Ubuntu 20.04. We've since updated to use Ubuntu 24.04, so GTK4 testing is at least plausible now - although we'd need to keep an eye on compatibility with Ubuntu 22.04, as it provides GTK 4.6, which has a number of APIs that were deprecated before GTK 4.10.

@freakboy3742 freakboy3742 added the linux The issue relates Linux support. label Jan 4, 2025
@danyeaw
Copy link
Member Author

danyeaw commented Jan 4, 2025

Wow, it looks like @MuhammadMuradG got a great start on this, nice!

As you mentioned, the timing may be right with the latest Ubuntu LTS have a pretty new version of GTK4 (4.10) and libadwaita at 1.5.0. Are we constrained to support Ubuntu 22.04 as well?

Since it is very difficult for so many changes on a branch to come home, I would recommend an incremental approach like I discussed above. If there aren't objections to trying that, I could work on a minimal example with something like the widgets needed for Hello World and their tests to be runnable with GTK3 and GTK4. I'm sure it would be pretty quick especially by cherry picking some of the work on #1978.

@freakboy3742
Copy link
Member

Are we constrained to support Ubuntu 22.04 as well?

Toga needs to work on 22.04, as it is still under active maintenance for another 2 years. However, I'd be OK with that being GTK3-based support, with ongoing development focusing on GTK4, as soon as we have the testbed passing on GTK4.

Since it is very difficult for so many changes on a branch to come home, I would recommend an incremental approach like I discussed above. If there aren't objections to trying that, I could work on a minimal example with something like the widgets needed for Hello World and their tests to be runnable with GTK3 and GTK4. I'm sure it would be pretty quick especially by cherry picking some of the work on #1978.

I definitely don't have any objections to working on a GTK4 migration. It hasn't been a high personal priority, but that's mostly because of my list of high priority projects is already too long :-)

My recollection is that #1978 was pretty far along, with CI testing being the biggest sticking point. There's obviously 12 months worth of merging to be done, which won't be a small task - but I suspect the size of that merge task would be about the same as a "cherry pick changes into new branch" approach.

As for an "incremental" approach - I'm not sure I completely follow what that would involve (at least, in terms of being able to offer gtk4 as an end-user solution). Would it be plausible to run the existing code under GTK4 and have the testbed pass, just with a whole lot of deprecated API warnings which we could then tackle using an incremental approach? If that's the case - I guess a "add a GTK4 CI config and see what explodes" PR would be worthwhile.

@danyeaw
Copy link
Member Author

danyeaw commented Jan 5, 2025

Would it be plausible to run the existing code under GTK4 and have the testbed pass, just with a whole lot of deprecated API warnings which we could then tackle using an incremental approach?

No, unfortunately, GTK4 is not backwards compatible. To make use of GTK4, the app would have to be created with GTK4 and all Widgets that need changes would have to be upgraded.

So to work on this as a longer term project, we can support both with if Gtk.get_major_version() == 3 checks and an environmental variable to change which version of GTK to load. In CI, we can run tests with both versions. The benefit of this is then we don't have to big bang change everything at once, we can upgrade widgets to support GTK4 without replacing GTK3.

Longer term, we may need something like this anyway to support two separate use cases:

  1. Higher compatibility version of GTK that supports users on older LTS distros who have packaged their app using a system package
  2. The latest version of GTK that is packaged with Flatpak and integrates with the latest version of GNOME.

@freakboy3742
Copy link
Member

Would it be plausible to run the existing code under GTK4 and have the testbed pass, just with a whole lot of deprecated API warnings which we could then tackle using an incremental approach?

No, unfortunately, GTK4 is not backwards compatible. To make use of GTK4, the app would have to be created with GTK4 and all Widgets that need changes would have to be upgraded.

My apologies - I was aware that GTK3 and GTK4 couldn't co-exist in the same app; my question was more about what the "minimum viable GTK4 port" would look like. How many breaking API changes do we need to accomodate (i.e., GTK3 APIs that don't exist at all in GTK4) just to get something working at all? Is there a world where "mostly GTK3 API code" runs on GTK4 (accepting that it might raise a whole lot of GTK API deprecation warnings)?

So to work on this as a longer term project, we can support both with if Gtk.get_major_version() == 3 checks and an environmental variable to change which version of GTK to load. In CI, we can run tests with both versions. The benefit of this is then we don't have to big bang change everything at once, we can upgrade widgets to support GTK4 without replacing GTK3.

Agreed. I'm envisaging a general approach that looks something like:

  1. A PR that adds a CI configuration and the minimum number of changes to allow the testbed to run at all on GTK4, with GTK3 remaining the default unless the user opts-in.
  2. A PR to get the testbed tests passing, accepting that the current GTK3-based API will raise a lot of deprecation warnings.
  3. A series of PRs updating individual widgets to remove/replace the use of APIs that were deprecated in GTK4
  4. A PR to switch the default GTK version from 3 to 4.

In practice, 1 and 2 might end up being the same PR; 3 will end up being a lot of smaller PRs; and we could merge 4 at any point that the work from 1-3 seems "viable enough" to be worth switching the default.

Longer term, we may need something like this anyway to support two separate use cases:

  1. Higher compatibility version of GTK that supports users on older LTS distros who have packaged their app using a system package
  2. The latest version of GTK that is packaged with Flatpak and integrates with the latest version of GNOME.

Given our limited resources, I'm not overly concerned about maintaining compatibility with GTK3 in the long-term. As soon as we have a viable GTK4 port, I'd be entirely comfortable saying that what we have at that point is as good as the GTK3 implementation is ever going to get, and focus all future development on GTK4. I don't think it's reasonable to require an open source project such as us to perform parallel implementation support for a GTK API that the GTK developers themselves no longer support; it's also unreasonable for a user to insist on using an old Linux version and require access to the very latest features.

My ultimate goal would be to drop GTK3 support entirely, as soon as either:

  1. There are no actively supported distros that don't ship with GTK4.10+ (That's Ubuntu 22.04, Debian Bookworm, and RHEL 8)
  2. Maintaining parallel support of GTK3 becomes especially onerous for some reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New features, or improvements to existing features. linux The issue relates Linux support.
Projects
None yet
Development

No branches or pull requests

2 participants