tao icon indicating copy to clipboard operation
tao copied to clipboard

feat(linux): Add support for system color scheme using xdg-desktop-portal

Open haecker-felix opened this issue 5 months ago • 28 comments

Use the Linux XDG Desktop Portal to add support for the system color scheme. This works independently of the Linux distribution, desktop environment or toolkit used. If the system colour scheme changes to "dark mode", the window will adjust automatically.

For reference: https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html

Screencast From 2025-08-29 09-30-17.webm

Closes:

  • https://github.com/tauri-apps/tao/issues/643
  • https://github.com/tauri-apps/tauri/issues/9427
  • https://github.com/DioxusLabs/dioxus/issues/3700

haecker-felix avatar Aug 29 '25 07:08 haecker-felix

Package Changes Through 03ca810666d11ce122f4816c11f05cf1b997d0fd

There are 1 changes which include tao with minor

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
tao 0.34.3 0.35.0

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

github-actions[bot] avatar Aug 29 '25 07:08 github-actions[bot]

error: package zvariant v5.7.0 cannot be built because it requires rustc 1.77 or newer, while the currently active rustc version is 1.74.1

I downgraded ashpd from 0.12 to 0.7 with the hope that this will make it possible to compile with rustc 1.74. Alternatively, would it be an option to upgrade rustc to something newer?

haecker-felix avatar Aug 29 '25 14:08 haecker-felix

1.77 is fine since that's tauri's msrv

FabianLars avatar Aug 29 '25 14:08 FabianLars

the real problem though is the dependence on tokio or smol as we try or tried to keep tao and wry runtime agnostic and using dbus/zbus would also make it harder to get back to winit https://github.com/rust-windowing/winit/issues/1549 🤔

really not sure how to proceed so i'll wait for feedback from the others.

does ashpd require the tokio or async-std feature flag to be enabled or could it work without either as well? (if it requires one i think tokio makes more sense since we use that downstream)

FabianLars avatar Aug 29 '25 14:08 FabianLars

1.77 is fine since that's tauri's msrv

Ah, good to know! But let's wait for others feedback first before making any further changes.

does ashpd require the tokio or async-std feature flag to be enabled or could it work without either as well? (if it requires one i think tokio makes more sense since we use that downstream)

I could switch to tokio, but that would likely require async-compat then, as it's not possible to spawn tokio futures directly from glib. But yes, ashpd either requires the async-std or tokio feature to be enabled.

haecker-felix avatar Aug 29 '25 18:08 haecker-felix

hmm that sucks 😅

FabianLars avatar Aug 29 '25 19:08 FabianLars

@FabianLars if the dependency on any async runtime is truly a blocker, we could also directly call the portal with dbus. That would suck though, since we'd basically re-implement parts of ashpd then.

You mentioned that you'll wait for feedback from others, who specifically do you mean?

Hofer-Julian avatar Sep 05 '25 06:09 Hofer-Julian

@amrbashir is the closest we have to a tao maintainer though idk how active he is at the moment. If he's unavail or has no opinion we could also ask @lucasfernog and @Legend-Master . If they don't have an opinion either i'll have to follow whatever winit decides/decided on 🤷

FabianLars avatar Sep 05 '25 19:09 FabianLars

ashpd uses zbus underneath the hood and zbus seems to be an async based crate, so unless we use something like dbus-rs and implement the theme settings ourselves (which doesn't seem to be that hard from the ashpd implementation, not sure with dbus-rs though), we'll need an async runtime

If we are going with the async runtime route, I think it'll have to be in feature flags, defaults could be discussed though

Legend-Master avatar Sep 06 '25 01:09 Legend-Master

What would be your preference @Legend-Master?

Reimplement with dbus-rs or using ashpd?

Hofer-Julian avatar Sep 06 '25 04:09 Hofer-Julian

What would be your preference @Legend-Master?

Reimplement with dbus-rs or using ashpd?

I don't know how much work would it take to re-implement it in dbus-rs, if that's manageable then I would prefer that as that makes the API simpler (no need to think about the async runtime when using tao)

Legend-Master avatar Sep 06 '25 04:09 Legend-Master

Reimplemented using dbus-rs instead of ashpd/zbus :+1:

haecker-felix avatar Sep 08 '25 13:09 haecker-felix

sorry i was away over the weekend. we actually deliberately got rid of dbus-rs in the past eg https://github.com/tauri-apps/tauri/pull/6332 so idk how to feel about this. I think i'll pull myself out of this PR (i'm away for 2 weeks anyway).

FabianLars avatar Sep 08 '25 14:09 FabianLars

I will wait with further changes until it is clear what is desired and what is not :/

To summarize, the current available options are:

  1. ashpd/zbus + smol runtime (allows reusing of already existing glib main thread / context)
  2. ashpd/zbus + tokio runtime
  3. dbus-rs (no async runtime, but needs dedicated thread with message passing)

haecker-felix avatar Sep 08 '25 14:09 haecker-felix

we actually deliberately got rid of dbus-rs in the past

Do you remember the reason for that? (also it seems like tauri currently doesn't depend on dbus nor zbus)

dbus-rs (no async runtime, but needs dedicated thread with message passing)

Personally I would prefer this, but take my opinion with a pinch of salt, I'm not the most familiar with the Linux ecosystem

Also I feel like we shouldn't be as strict as winit when considering these things, that's part of the reason why we branched out right?

And, I'm travelling from 11th to ~25th this month so I probably can't reply between this time period

Legend-Master avatar Sep 09 '25 02:09 Legend-Master

Do you remember the reason for that?

Linked in the PR. basically linking to a system library was a pain 🤷

(also it seems like tauri currently doesn't depend on dbus nor zbus)

correct, a few plugins use zbus (single-instance and notification come to mind)

Also I feel like we shouldn't be as strict as winit when considering these things, that's part of the reason why we branched out right?

to a degree yes, but we're also looking to get back to winit. as long as we still use webkitgtk we still need our own linux backend though (much work on their side going on to make that possible next release(s))

And, I'm travelling from 11th to ~25th this month so I probably can't reply between this time period

Safe travels and have fun :)

FabianLars avatar Sep 09 '25 14:09 FabianLars

Hey folks, I hope you had a great vacation / time off! :)

I wanted to follow up to see if there is any new info on how we are proceeding with this PR so that Linux will get dark mode support as well. I summarized the possible options in https://github.com/tauri-apps/tao/pull/1141#issuecomment-3266723853 - let me know what you think.

haecker-felix avatar Oct 06 '25 12:10 haecker-felix

I believe re-introducing dbus-rs should be avoided if possible. Knowing the zbus community we probably would get a PR "fixing" that later on :D

Also whatever we'll use we should put the dependency behind a feature flag.

Speaking of, how about we mirror rfd's approach and offer both zbus-tokio and zbus-smol/async-std ? I'd really love to avoid the latter in tauri downstream (even considering the downsides of the tokio version you mentioned) but it may help other tao consumers not using tauri.

[about winit] as long as we still use webkitgtk we still need our own linux backend though

btw, without this i would have turned down this PR in favor of something downstream (easy to do but obv would keep ThemeChange noop on linux)

FabianLars avatar Oct 06 '25 16:10 FabianLars

Speaking of, how about we mirror rfd's approach and offer both zbus-tokio and zbus-smol/async-std ?

If we can't use dbus-rs here, this would be the preferred way for me as well

Legend-Master avatar Oct 07 '25 03:10 Legend-Master

I believe re-introducing dbus-rs should be avoided if possible. Knowing the zbus community we probably would get a PR "fixing" that later on :D

Alright, zbus then, no dbus-rs :)

Also whatever we'll use we should put the dependency behind a feature flag.

Just to make sure, if I understood you correctly, I would add a async-std and tokio feature flag, and enable the async-std one by default (to mirror rfd here)? Consumers would need to pick either async-std or zbus then.

haecker-felix avatar Oct 10 '25 12:10 haecker-felix

yep. though i don't care which flag will be the default, we could even have neither in the defaults 🤷

FabianLars avatar Oct 10 '25 13:10 FabianLars

yep. though i don't care which flag will be the default, we could even have neither in the defaults 🤷

If possible, it would be great, of course if the system color scheme would just work without developers manually opting in to it 😀

Hofer-Julian avatar Oct 10 '25 13:10 Hofer-Julian

It's now possible to choose between async-std and tokio, defaulting to async-std.

If you don't choose anything, or have default-features = false, you get a compile-time error:

error: Either the `async-std` or the `tokio` feature has to be enabled
  --> /var/home/haeckerfelix/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ashpd-0.12.0/src/lib.rs:12:1
   |
12 | compile_error!("Either the `async-std` or the `tokio` feature has to be enabled");
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This means that if consumers of tao set default-features = false, they must explicitly enable either the async-std or tokio feature.

haecker-felix avatar Oct 10 '25 16:10 haecker-felix

Thanks for implementing the feature flags!

This means that if consumers of tao set default-features = false, they must explicitly enable either the async-std or tokio feature.

This is a bit of a no-go since we have to keep a tokio & asyncstd free option for a few users. Should be an easy fix though by marking the 3 deps as optional and having both feature flags enable it. plus a few #[cfg(any(feature = "tokio", feature = "async-std"))] flags in the code.

If possible, it would be great, of course if the system color scheme would just work without developers manually opting in to it 😀

I get the sentiment but the lockfile change is a bit intense so we shouldn't take that decision lightly.

FabianLars avatar Oct 23 '25 12:10 FabianLars

This is a bit of a no-go since we have to keep a tokio & asyncstd free option for a few users.

Done 👍

I get the sentiment but the lockfile change is a bit intense so we shouldn't take that decision lightly.

I understand your concerns, but I fear that if this is not enabled by default on Tauri's side, hardly any developers will actively opt in - which would be a shame, because Tauri is one of the few remaining frameworks that does not yet support the new system “color-scheme” standard on Linux environments.

haecker-felix avatar Oct 24 '25 08:10 haecker-felix

it will be enabled on the tauri side (without opt-out probably) which is also why i wanted a tokio option cause that would make the most sense there. my concerns were only about tao (and wry) for those hardcore users (or those building frameworks on top of it like dioxus)

FabianLars avatar Oct 24 '25 08:10 FabianLars

I am happy to hear that, seems like we misunderstood your intentions :)

Hofer-Julian avatar Oct 24 '25 09:10 Hofer-Julian

Hey @FabianLars!

@haecker-felix made both tokio and async-std opt-in in https://github.com/tauri-apps/tao/pull/1141/commits/a7104e767070440ea9e7ef19a0ce31e75577a701

Is there anything else to be done before we can get this merged? :)

Hofer-Julian avatar Dec 11 '25 09:12 Hofer-Julian

One nitpick I have is that Cargo.toml now lost its EOL newline at EOF, which is not great for diffs. And it's not even consistent, as the new src/platform_impl/linux/portal.rs file has it. Though I haven't looked at all other files.

Andrew15-5 avatar Jan 05 '26 16:01 Andrew15-5