Getting some theme definition to apply on app not made with GTK/Gnome lib

Hi,

I’m trying to make some routines to get style definition from Gtk/Gnmoe to apply more or less the same theme to an app that is built with Fyne.io (Golang).
To be clear, I know that GTK4 now uses a purely CSS-made theme and I had a long discussion on Mastodon where someone explained to me that GTK4 has no “color” definition.

So I will try to explain what’s the problem and what is missing to help whatever the outside library we can use to be well integrated in Gnome. And maybe you will provide me with some track or solution.

Before, with GTK3, I only called this GJS script from my app to get some information:

imports.gi.versions.Gtk = "3.0";
const Gtk = imports.gi.Gtk;
Gtk.init(null);

// create a simple window
let window = new Gtk.Window({
  title: "Hello World",
  default_width: 200,
  default_height: 200,
});

// get the background color of the window
let bg = window
  .get_style_context()
  .get_background_color(Gtk.STATE_FLAG_NORMAL)
  .to_string();
print(bg);

This worked because there was only basic color in GTK3. I only had to parse the rgba string and I could then apply the same colors (background, foreground) to the current app made with in Fyne.

But, GTK4 is born… and everything is now, more than complex, impossible to use like this.

imports.gi.versions.Gtk = "4.0";
const Gtk = imports.gi.Gtk;
Gtk.init();

// create a simple window
let window = new Gtk.Window({
  title: "Hello World",
  default_width: 200,
  default_height: 200,
});

// get the background color of the window
let [ok, bg] = window.get_style_context().lookup_color("theme_bg_color");
print(`rgb(${bg.red * 255}, ${bg.green * 255}, ${bg.blue * 255})`);

The given color is absolutely not the one used by the displayed window. It’s a black (very dark grey) color that returns this call, while the Gnome theme uses “Nord” as background (rgb(59,66,82)) -

GTK3 was OK, not GTK4.

Of course, maybe the theme declares other overridden colors, or maybe it doesn’t declare the Adw color. But, the window in GTK4 uses the right background, when I really display it, the theme is well applied. So, what’s the deal to get this applied color/background ?

Today, with GTK4, I’m simply in the impossibility to get at least a few pieces of information from a very tiny standard window… More become less…

Is there a way to get the background definition of a simple window that is created with Gtk.Window ?

Of course, the easiest thing would be to have a CSS selector like window.get_theme_css() as a string :wink:

There’s a lot of wrong assumptions here.

Let’s start from the most obvious one.

As does GTK3. Since 3.10 when theme engines got removed, anyway. So there’s no difference between GTK3 and 4 here, except 4 has removed some of the more broken API for interacting with the style. You’ll see shortly why exactly it’s broken.

Let’s start from this. Sorry to disappoint, but it didn’t work. Well, it worked in GTK 3.0, but it long since stopped working by 3.24. The docs shed some light onto the reason. Notice how it’s deprecated, and says this:

This function is far less useful than it seems, and it should not be used in newly written code. CSS has no concept of “background color”, as a background can be an image, or a gradient, or any other pattern including solid colors.

Yep. And that’s why it was removed in GTK4 - it was misleading people into assuming the background is always a solid color one could retrieve. In reality whether it works with any given widget or not was (and still is) up to the particular theme.

Next one is the named colors and gtk_style_context_lookup_color().

Again, this existed in GTK3 and really even in GTK2. Nothing new here. But you’re assuming these colors 1. exist, 2. correspond to the actual styles. But they don’t have to. There’s no standard saying they have to do any of that, and they aren’t an API. For example, the elementary stylesheet doesn’t define all of them, and Libadwaita defines a completely different set of colors in its stylesheet.

Oh also, they can contain non-1 alpha as well (why didn’t you use to_string() here, it would have handled that), and they don’t even have to be static colors. For example, Libadwaita does this:

@define-color borders alpha(currentColor,0.15);

Yep - it depends on the foreground color of the current widget. If you try to get it with what your code does, you’ll probably get a different color depending on what widget it is.

And even if the stylesheet actually defines them, there’s 0 guarantee it actually uses them anywhere. Or maybe it defines a color just in case but uses a gradient? Plenty of possibilities - themes are freeform and you can’t assume anything here.

Now, the specific reason you’re getting a different color is likely that your theme doesn’t support GTK4 and you get Default:dark (dunno why :dark but @theme_bg_color is not dark in regular Default). Alternatively, your theme might be doing something weird - as we’ve already established, there’s absolutely nothing requiring them to keep those colors consistent with the UI or have them at all.

Yes, there are and the docs do point you to one of them. gtk_render_background() and/or gtk_snapshot_render_background(). Yes, they don’t return a single color - but I mean the background doesn’t have to be one anyway - like Default (or GTK3 Adwaita) header bars have a gradient, for example. Multiple gradients for .devel windows in fact, with an overlaid image on top.

So, you can render the whole background. How exactly you pick color from it? Up to you, maybe pick a pixel from the center or something.

It can still fail, of course - what if the header bar has no background at all and lets the window one through? Well, again themes are freeform and you won’t be able to find that out, you’ll just get a transparent color.

I don’t understand what this means.


Bottom line - don’t bother, this can’t work and only worked by accident. Just hardcode colors and call it a day.