How to code 3D effects in a Gnome extension?

I’m curious on how to code 3D effects for Gnome Shell.

I know it supports CSS, and I see the docs show that the translate property has a matrix function, but it seems to be 2D. Or is the doc outdated and it has matrix3d? Maybe I found the wrong doc page.

EDIT, I was in the GTK3 docs. I see GTK4 has matrix3d, yaaay.

What about in JS? Are there any APIs for 3D on the JS side? Some OpenGL bindings, or something similar to WebGL?

Is there a difference in GTK4 CSS and Gnome Shell CSS? Are they the same engine, or different engines? If different, how do the 3D options differ? The CSS section of Gnome Shell Development docs doesn’t say much.

I’m not sure if this is what you’re looking for but have you seen gthree?

Gthree has nothing to do with GNOME Shell extensions, as it’s written for GTK3 (and GTK4) and GNOME Shell extensions cannot use GTK.

You cannot use CSS to influence layout in GNOME Shell and GTK: applications and the compositor are not web pages or the CSS zen garden.

If you want to use 3D transformations inside GNOME Shell, you can use the Clutter API.

That’s interesting. What I’m looking to do is customize the Desktop experience (like Compiz for example), which is why I want to do it in a Gnome extension. Can gthree be used for that?


GNOME Shell extensions cannot use GTK
If you want to use 3D transformations inside GNOME Shell, you can use the Clutter API.

Ah ok. Any docs or articles on Clutter for 3D? EDIT: Okay, I see CluttlerActor, and it has transforms inside. Found the Gnome Extension intro tutorial, which shows how to access Clutter in Gnome Shell. I can take it from there!

Any plan for CSS transform:matrix3d to land in Gnome Shell CSS?

Not that I’m aware, and I struggle to think of a reason why themes should be involved in 3D transformations.

Suppose I want to make an alt-backtick window switcher that is themable, and that cycles through windows. I am imagining that I could set classes on the actor/element depending on state: previous, current, and next, where previous is for windows before the currently-selected window, and next is for windows after the currently selected window. Then I could also supply configurable spacing and animateToPosition parameters, or something. Then people could theme that, and they could add 3D rotation like in the Coverflow extension using CSS.

That may be a good use for matrix3d.

Maybe you’re imagining that we wouldn’t want to apply matrix3d to, say, the title bar. That’s probably true for the most part, but we can’t imagine everything people want to make, we can only give them the tools to make anything.

Now I’m imagining the KNotifier extension with icons that rotate around Y (assuming Y is up/down on the screen and that the CSS has the same coordinate system as in HTML’s CSS) that are triggered by simply adding/removing a class that is associated with a CSS animation, and the developer not having to imperatively manage all that animation stuff and making bugs.

I suppose CSS transform maps to a ClutterActor’s transform, and I don’t see why matrix3d would be a bad idea if it allows some neat tricks.

Here’s an introductory example I made of UI with HTML <button>s that have real lighting and shadow: It’s a 2D UI in a 3D space.

The JavaScript in the example uses Tween.js to animate the buttons when you click and hold them, but once I add the CSS polyfill then it’ll be in CSS (where the harder-to-read imperative logic can be avoided).

That’s horrific, and it won’t ever work, no matter how many hacks you put in place.

The more complexity you can override in the theme, the more complexity you need in the backing code, for no good reason whatsoever.

The CSS in use for GNOME Shell, and GTK applications, is not meant to provide you with the capabilities of the CSS Zen Garden. As an added difficulty level, GNOME Shell is your compositor; injecting code into it—even well behaved and well tested code—is going to be problematic because it might end up preventing you from actually using your desktop. A web page lives inside your web browser; if it misbehaves, you can always retain control and close it; you cannot do the same with the thing that is managing all your windows and drawing them on the screen.

1 Like

Mildly relevant, last year there was an article about a library for window effects. It appears to be developed by Endless so perhaps looking at how are they using it in their GNOME Shell fork might be enlightening.

1 Like

Can you explain why it is horrific?

I don’t understand that. I’m not wanting to inject code anywhere. I’m wanting to write CSS. CSS in a browser is (in theory) incapable of misbehaving in ways that imperative code (JavaScript) can. You can’t hack in CSS. You can’t write logic errors in CSS. I’m not sure what you mean, but I’m imagining that a rotating icon (3D rotation), is perfectly fine, especially since it has no effect on layout.

Because writing a complex UI model like a coverflow visualisation using CSS is bound to end in tragedy and blood. It’ll never work.

In order to make every bit of CSS work, you’ll have to add code inside GNOME Shell, which is the entity responsible for taking that CSS and translating it into draw commands and scene graph state.

That’s a nice theory, but while it’s true that CSS is much more sandboxed because it’s a declarative state description, it’s also not going to be able to represent everything. Additionally, GNOME Shell does not (and likely will not) support every bit of the CSS specification because—as I said—it’s not trying to reimplement the CSS Zen Garden. You won’t be able to define in CSS the position and size of every UI element on the screen, like you would do on a web page.

So TLDR, I can’t use CSS transform:matrix3d in Gnome Shell and there are no plans to support that in Gnome Shell (yet gtk4 will have it)?

That’s correct: there are no plans to add CSS Transform support to the GNOME Shell theming engine.

What may end up happening if the 3D API in JavaScript is still accessible, is that we’ll write more code to achieve what would otherwise be simpler and less code via CSS.