Yeah, like after six, when it was the last session. Okay.
So, I hope you all had a nice coffee break. Thank you for being here.
I'm not supposed to be a session chair right now, so I should have come up with a joke by now.
And then Eike stole my joke about the State of the Union, and Arjen doesn't
want me to introduce it as the State of the Union, so I'll just leave the rest
of the introduction to Arjen. That's fine.
Hello, my name is Arjen Hiemstra. I am here to talk about a project that I've called Union,
which I hope will become the future of everything styling within KDE and maybe even more than KDE.
So, what I will start with, though, is some pictures.
So, most of you will probably have seen some of these things.
I'll start with this is Kate, probably familiar.
This is Plasma, also quite familiar to most of you.
We have Neo Chat, might be less familiar to people, but will still be familiar to a lot of you here.
And then we have an application called KClock, which isn't all that familiar
to most people, but still also a KDE application.
So that's all great. We have four applications that look quite similar.
So what's the problem here? Well, we have four applications,
and we have four different implementations of the Breeze style.
We have Kate using Qt Widgets, using Breeze.
We have Plasma using Plasma style, using SVGs to supply that information.
And then we have Qt Quick, which, in the case of Neo Chat, is its own special thing.
And then in the case of KClock, it actually uses a Qt Quick-based implementation of the Breeze style.
I hope that all of you recognize that having four different implementations
of the same thing is already a problem, but sorry.
Yeah, I intentionally didn't mention that one here, mostly because that's a
whole different can of worms.
But yes, you're right, there is a
potential fifth in that we also have an implementation of Breeze for GTK.
So, apart from that issue of having four different implementations,
there are also issues with the individual implementations.
Starting off with Qt Widgets implementation, which is build using the C++ Qstyle API,
which Which is, to put it politely, not the greatest API,
for doing stuff with this.
I actually put up some code from the Breeze style.
Basically, you need to manually paint all the individual controls.
And it's very painful to make any changes to how Breeze looks in Q style.
It takes a lot of time and effort and deep knowledge of how Qstyle works.
So this is really not that great.
And similarly, an additional problem here is that it is limited by specifically
those types of widgets that Qstyle supports.
So if you have a custom widget, which we don't all that much,
but if you do have it, it also becomes quite hard to reuse the styling from Qstyle.
On the other hand, we have the Qt Quick side, which is better.
Qt Quick is styled using Qt Quick Control, or Qt Quick Control specifically
is styled using QML files, which is already a lot easier to work with than Qstyle,
but it still has its issues.
Specifically one being if you make a mistake in your Qt Quick style,
you can break applications.
Which is dangerous when you want to include a custom style in like say,
or inject a custom style in something like a Flatpak, which is a use case we do have.
So to get around this issue of having multiple implementations of the style,
at some point we developed Qt Quick desktop style,
which makes use of the widget style, Q style,
to render controls for Qt Quick.
Which works. It means we have a bunch
of things that don't require re-implementation but it also comes with its drawbacks
because we're now limiting our Qt QuickSight by what the QStyle side supports which isn't great,
so it's and there it also comes with a nice another drawback because QStyle
is software rendered standard,
which means that on mobile platforms,
you now have an issue where the performance of this isn't great.
So at some point, Noah actually, Noah Davis, built a version of the the Breeze
style using pure Qt Quick,
because that was targeted to help make KDE applications work better on Plasma Mobile,
and that it did, but it didn't mean we had yet another implementation of Breeze.
And then finally, we get back to Plasma, which has its own SVG-based system for styling,
which is actually pretty decent to work with for non-developers.
But even with them, when talking to them about it, it turned out,
yeah, it's better to work with than, say,
Qt Quick, but it's still an issue because SVG is not a format designed for making UIs in.
It's a graphics format meant for making images.
It's still not great for doing UIs.
It additionally also runs into the issue that you now need to render these SVGs
which comes with their own problems and performance penalties and everything.
And additionally, the plasma styling still contain,
misses the, the actual SVG file still miss a lot of information that is encoded
in the Qt Quick that's making use of this about to identify which elements to
use and all those kinds of details.
So, I think you can all agree that we have a problem here.
We actually, within the Visual Design Group and some other areas,
we've identified this problem a while back.
And it's taken a while to get to a solution.
But basically, the question becomes, we have this problem. How do we move forward?
How do we get to the next stage?
So, yeah, we need something new because what we want to go to is the classic
case of, hey, we now don't have 15 standards or five in our case.
We now have just the one and just that one thing that we can use to build our UIs with.
So just to work on, hey, what are we going to do with this?
I came up with some requirements during a long, long process of getting to where we are now.
So the main point being, we need something where we have a single source of
truth for all our styling.
Styling this is not this is
something that also our designers want because they
want to make changes to how things look but right
now they are being blocked because we
as developers say hey sorry we
we like your ideas but we just can't do
this because it's going to take way too much effort and way too much work to
make these changes and in some cases it's even saying yeah well we can't technically
do this here because we're being limited by for example cue style.
So one of our the main requirement is we need a single source of truth but we
We also need to make sure that that single source of truth is easy to change
and easy to change for people who are not necessarily developers.
Because we want to be able to work with our designers to make it easier for
them to implement their vision of how things should look.
On the other hand, I also have some requirements, and those come from my side,
from the technical side, because I want to make, if I'm going to work on this,
if I'm going to build something for this,
I want to make sure that I can build something that is optimized for our target.
So if I'm building something and I want to target Qt Quick, I want to have something
that uses Qt's quick hardware acceleration to render.
If I'm using it in, I don't know, if we're going to use it in a crazy idea,
in a game engine using Vulkan, I want it to be able to use Vulkan internally.
So that's one of the things. the other requirement is that single source of
truth should not have any logic.
And this is a technical requirement from my side because if we don't have logic
in there, it means that we can do a lot more, lots more optimization on the library side,
with this, on this input format so that we can do cache, more intelligent caching,
that doesn't need things like, oh, hey, state changed, so I need to call back
into whatever gives me this information.
And needs to ask that to re-render something. No, you can just say,
okay, state changed, here, have this different thing.
And it needs to be flexible enough that we can define custom types.
Because within KDE, we have the Kirigami library, which implements a whole bunch
of custom controls on top of Qt Quick.
And they are all styled like Breeze.
And there is no way for you, or well, there is a way, but there is practically
almost no way for you to restyle those into a different style.
So if you go and use a Kirigami application under GNOME, it will look like Breeze, at least partially.
So, with those requirements listed, let's look at how I got to where we are currently.
So at some point while working on this
entire thing, which has been a long process, I came up with this idea.
What if we separate things? What if we say, hey, we have some kind of definition
that defines how things should look.
And then we have an intermediate layer where that input format can get transformed
into that intermediate layer.
And then we have an output format that consumes that intermediate layer instead of the input format.
The main difference this makes is that if something needs to change,
if we want a different input format or whatever, we don't need to change the output format.
If we want to add a different output format, we don't need to bother with the input format.
So that was my idea that I had at some point.
And I basically came up with, hey, could we use this to build something where
we use CSS as an input format,
read a CSS file, read some definitions from that CSS file, and use that to style
both a Qt Quick application and a Qt Widgets application.
So I built a proof of concept of that a few years back at this point,
proving that, hey, yeah, maybe we can actually do this.
So I built this using a CSS parser that I found somewhere on the Internet, which is its own issue.
I'll get into that a bit later, and build this very minimal intermediate layer
that this CSS got converted into, and then build a Qt Quick style using some of our standard stuff.
But using the information that came out of this intermediate layer to render
a button that looks somewhat like how Breeze would style it.
And then on the other side, I built a cue style that used that same information
and then did the same thing and ended up rendering a button that looked mostly
the same to the Cued Quick side.
There's some bits that are not entirely the same, but that was mostly because
I ended up not wanting to spend that extreme amount of time to get that rendering right.
Right so what
can we learn what could we learn from that proof of concept well most importantly
my the core of my idea seems like it would be work and it would be possible
to have something where we have a single input format and two or more output formats.
Of course, it also means that, hey,
yeah, okay, so we have this, but it means that we're basically going to need
to rewrite the entire set of how we do our styling within KDE,
which is going to be a lot of work.
Yeah um and also something from the input from the proof of concept as i mentioned it was using css.
Css is a problem mainly because there are no good css parses out on the internet
at least not for what i want to do here like there's there are plenty of css
there's plenty of css parses around like in web browsers and stuff,
but none of them are available as a C++ library where I can get a parsed tree
of what's in a CSS file because most of them go like,
oh yeah, here have a styled thing already or stuff like that.
And because, as I mentioned, it's all going to be a lot of work.
So we need some way of splitting up this thing, because rather than building
this monolith somewhere in
a dark corner of KDE and then at some point going, look, here is my thing.
It's done and it's going to be awesome.
And then the real world hits it and it turns out to shatter that entire monolith.
With, um, we need to be able to do this in a more intimate, um,
step step by step way so that we can prove parts of the implementation are correct.
So this proof of concept was done, I think I presented it to people during Academy 2022.
And then it kind of didn't go anywhere because of various reasons.
But I did mostly because I didn't have the time for it.
I did spend on occasion some time on, hey, okay, let's make a production version of this.
How do I go about this? And this is how the project that I now call Union came about.
And it's meant to become this single source of truth,
styling engine that we can use to get our styling into a shape that where our
designers aren't running away screaming.
So, again, I go back to how do we go about this.
At some point when we were discussing this,
a fairly smart guy who you may have heard about called David Edmondson suggested,
hey, what about doing it as, what about just reimplementing the way Plasma is
styled using this engine,
so that we know what the input format is, we know what the output format is,
and we have a way of, a thing where we can focus on that intermediate layer, because a lot of stuff,
depends on that intermediate layer, and if that intermediate layer sucks,
then the entire thing will suck.
So that's basically what I've been doing for the past several months,
because finally someone came with, hey, I also want this.
Also, I'm going to give you guys some money for this.
So now I suddenly do have the time as part of my day job to work on this.
So it's finally making progress, luckily.
So what does that look like? Well, it looks like this. The left two buttons
are being rendered by Union, are using styling from Union.
The right two buttons are using styling from Plasma.
It doesn't look any, well, apart from the icon, ignore that,
it doesn't look any different at the moment,
which is exactly the intention, because right now,
what we are trying to do is recreate Plasma styling,
styling because that's what now we know
we know what that needs to look like so we
need to come up with all the constructs to
make sure that with that separation of
concerns about having the inputs layer which
now reads plasma svg that converts all that into this intermediate layer and
then goes into a separate cute quick style that reads makes use of that intermediate
layer and puts out something that actually looks like what Plasma does.
So some implementation details about that.
We now have a core library that basically is built around a concept of a theme
where a theme has a collection of style rules.
And a style rule is well
I'll get into that in a moment but it has a
collection of style rules and selectors and then we have an input plugin input
plugins currently only one one that reads plasma SVGs and converts that into
a bunch of style rules and then we have an acute quick style
implementation that feeds information into the theme and with that information
selects which of those style rules apply to the current thing that it's trying to render.
So style rules, I mentioned that.
Style rules are which properties do apply to this element.
That's the most generic description I can give you of this.
And importantly as well, style rules have a selector. that selector determines
what kind of elements this style rule applies to.
So you can have something that says, hey, my text color should be red and this
should apply to any button.
And if we have a button that is currently focused, rather than using red, it should become blue.
These kind of things are encoded using the style rules.
And they are effectively, they form a stack where the topmost properties read
first, and if there's no value in the current style rule for that,
the next one is used, etc.
For those who have experience with CSS, this may sound very familiar.
That is kind of intentional, partly because I was inspired by CSS and partly
because I still want to be able to use CSS eventually,
but that's also a thing I got into.
Um sorry how much time is
left 15 minutes okay um so
that's the current state what's next
um i want to finish up this plasma
style thing and uh basically get that into a state where we can say hey we deprecate
uh plasma controls uh the plasma specific implementation of the styling and
use it use union instead so that we can get some real-world testing of this,
we need to implement the Qt widget side which is going to be its own dragon to slay.
And we need to decide on a
new input format because CSVG is not meant as
the final input format as I said
before I still really prefer using would
like to use css but that's tricky
with library things there
might be a solution in using a rust css parser
but yeah that's still in the in the investigative state um we also need to do
a bunch of application integration because union assumes that a bunch of the
information comes from from the application,
next to what the style can already provide.
But as a simple example, we have this header area in our applications.
With Union, my intent is that the application will provide us information about
what is defined as its header area.
And there are some other things. We have a bunch of things where we use styling,
breeze-like styling, and as
well, mentioned here, GTK is a thing where we currently have a custom CSS.
We might be able to use this to generate a CSS style.
But that depends also on whether that GTK styling is actually maintainable,
because from the GTK side there's a lot of push about, hey, don't team my apps and all that stuff.
So with that, I come to the end and would say, any questions?
All right, so specifically, when it comes to PlasmaSight, you also mentioned this.
So we have these SDGs with a bunch of elements that have truly established names.
The code on the PlasmaSight knows how to use them.
That's the component. but can you walk me through where does that match up happen
in the SQ implementation?
Because you mentioned the output plugin that we currently have is a generically
quick one. Where's the sort of Plasma knowledge?
That's on the inputs plugin side.
So in the case of Plasma SVG, we actually have two layers there because we have
a bunch of definitions in YAML that define which elements should be used for certain controls.
So, could you explain how your work on this has any implications about using a Qtab,
in a desktop environment that is not Plasma?
So, the intent is eventually that we can have different input format,
different input styles that implement platform specific styles.
So rather than having to rely on a bunch of different elements coming from different styles,
we have a single source of truth that might be Breeze,
but it also might be a window specific thing or
a gdk specific thing or whatever or
uh and and i've not mentioned this intentionally but if someone wants to go
and do third-party implement a third-party theme they can style the entire uh
the intention at least is that
they can style the entire plasma desktop using their own custom theme.
Have you looked into the integration with the Q-Palette and the Palette's configurations
for Qt application together with this?
Because Qt application can also provide their own styling information using the Palette.
Yeah um right now it doesn't
do that because the plasma styling doesn't do that it is a thing that we will
need to look into especially for Qt widgets and Qt style we do actually have
some experience with this already on the with the Qt desktop style Qt quick
desktop style and things
like that, we already do some integration with Qt Palette.
Unfortunately, it became harder with Qt 6 because Qt Palette in Qt Quick moved
from being a Qt Palette to a Qt Quick Palette.
That's a different discussion, but yeah, that's definitely one of the things
that we do intend to support.
Hello! It happens that we have a CSS style in Qt Widgets, which I assume you have looked at.
That includes a CSS parser and also a similar architecture around rules from
what I understood from you.
One of the challenges we have for the CSS style or the style sheet style in
Qt is of of course, that it tries to know which aspects of the UI you have styled
using CSS versus where it should fall back to the default style.
Do you plan to do something similar magic or do you agree with me that by not
having any kind of default behavior, everything is unstyled,
if it's not explicitly styled, we just draw everything as dumb rectangles,
we can remove move a lot of that complexity.
So, uh, I agree with you in there that no, we, I am not planning on any fallback behavior there.
Um, or at least no, no low level, like per properties fallback stuff.
We might be able to do something with, with higher level fallbacks,
but, um, yeah, the, the intent is not to have complicated fallback mechanisms there.
On the topic of CSS as an input format, CSS is quite powerful with animations and logic constraints.
How much do you actually want to support Fromset, what is the large feature set?
That's currently an open question. It's something that needs to be investigated
when we're actually developing a CSS input format.
Animations are something that we will want to support simply because we want
to be able to use that for Breeze stuff, but maybe not all the types of animation.
I'm mostly thinking like transitions we would want to support,
but maybe not completely freeform animations.
And there's also things like media queries and stuff, what do you do with that.
Advanced selectors Yeah, you're completely right, CSS, especially what's becoming
CSS4, is quite complex and large.
And we'll have to see what we can support, also what needs to be supported.
You mentioned something about custom controls.
How do you currently do that in using Qt Quick style?
Because you need to provide this template for all the controls that we currently support.
So what is your solution for these custom ones?
So as I mentioned, currently the solution is that we style them as Breeze.
And we don't we we there is
a an in on the kirigami side we do have a construct where we do support like
having a template where you that you can re-implement but in practice basically
almost no one does that because it's it's just a lot of work and ends up being very complex,
So the end result is basically that we always have Breeze-styled custom controls, unfortunately.
So so um previously you
said there was be like no fallback behavior and yeah
i'm sure that makes sense uh but would it be possible
for like a user to say oh i
want my theme to inherit from this
other theme like let's say a user says i
like most debris but i want to change this
bit it yes that uh will be
uh at least uh i do intend to
support things like that um it will be up to the input formats on how that works
like uh with css it might just end up being something like hey import breeze
and in the css file and then override some rules um but that that it's it's
one of those areas where it,
I think it is up to the input format to determine the best solution.
Uh, have you looked into the GTK CSS styling, if it's something like that can
be used, uh, so we at least get a bunch of themes, uh, for free automatically
if you use the same CSS style.
Yeah. You're, you're not the first one to mention that. I have looked at that
and basically concluded that it's probably not feasible for us, unfortunately.
And also partly because of current attitude of GTK developers towards this.
So I am quite hesitant to go and reuse something where they say,
no, no, this is ours and you must not touch this.
I was hoping to revive Advaita Q, but sadly no.
While the implementation part is another story for this architecture specifically,
while GNOME and GTK sites is a little different on that for this intermediate
layer would you consider contributions that cover more than the Qt for like,
other desktops, like Cinnamon, et cetera,
to make it from KDE into a more free desktop thing, possibly?
I mean, if there's interest there, yes, I would definitely consider them.
I am open to have this integrated in more layers, also to make it easier to
run KDE stuff on Cinnamon or something. thing.
So I would totally be open to that.
We need to figure out what the right place for such things would be.
So in my mind, I'm kind of getting hung up on the details.
On the notion of custom controls, I'm curious if you can give a little hint
at how you plan for that intermediary layer to be extensible.
Because you mentioned one of your requirements is that the input side should be logic-free.
But in your re-implementation, that's currently not the case, right?
Because you have the input plugin reading the SVG doing the magic translation
of this should be a task manager button.
These are the element names to the intermediary thing.
But in your future input format, the input would be more generic so how do you
transport the notion that there is not just,
a button but there's also a specialization which is let's say a task manager
button which doesn't occur anywhere else into that like how do you extend that
i'm curious about that So, I'll correct you on one thing.
The input format, the format needs to be logic-free.
It's not the plugin that needs to be logic-free. You don't consider the plugin
to be the... No, the plugin is the thing that translates the input format into
the intermediate format. Okay.
Yeah, and I ran out of time. I'll gladly talk about it in detail with you.
I can actually show you some code.
That was very great. Thank you.