wayfire icon indicating copy to clipboard operation
wayfire copied to clipboard

Select particular applications / windows for server side decoration

Open spl237 opened this issue 1 year ago • 16 comments

I'm becoming frustrated by the way Wayland / wlroots adds window decoration...

By default, in Wayfire, you can either select all windows to be client-side decorated (the default), or server-side decorated.

If windows are client-side decorated, GTK apps get a GtkHeaderBar. However, Qt apps get a Qt-originated header bar, which looks visually very different from the GTK header bar, and apps like Chromium with its Ozone backend get no header bar at all. Xwayland apps get no window decoration, but the decor plugin applies decoration to them.

If windows are server-side decorated, they are all decorated by the decor plugin, so are consistent, but the decor plugin is a lot less nice than the default client-side decoration for a GTK app - you get visible borders rather than invisible resize handles, for example. But the consistency between windows is much better.

I have written a custom version of the decor plugin which pulls its appearance from the GTK theme, so in a system with client-side decorated windows, I have native GTK windows which look good, and Xwayland windows which look almost as good. But I still have inconsistent window decoration on Qt and Ozone windows.

What I would like to do is to get Qt and Ozone windows requesting server-side decoration, so they can be decorated by the plugin, while leaving native GTK windows to be client-side decorated. As far as I can tell, this isn't possible at present, but I think it ought to be possible to make it happen, perhaps by adding an ini setting which takes a criteria argument for "server side decorated windows" instead of / as well as the global server-side decoration setting.

I've had a play with some of the relevant code, but can't get anything that works. Is this change possible? If so, could it please be added to a future version?

Many thanks in advance.

spl237 avatar Mar 28 '23 11:03 spl237

I've had a play with some of the relevant code, but can't get anything that works. Is this change possible? If so, could it please be added to a future version?

I think it might make sense to let plugins decide on this policy. Currently, it is hardcoded here: https://github.com/WayfireWM/wayfire/blob/master/src/core/core.cpp#L90

I suppose it should be easy enough to tweak it locally to see whether it works as intended.

ammen99 avatar Mar 29 '23 18:03 ammen99

Thank you for the reply.

For the time being, this is what I have done:

diff --git a/metadata/core.xml b/metadata/core.xml
index 54e93dc..cd19a92 100644
--- a/metadata/core.xml
+++ b/metadata/core.xml
@@ -70,5 +70,10 @@
 			<_long>Whether to pass buttons through to the client when switching the focus via clicking</_long>
 			<default>true</default>
 		</option>
+		<option name="only_decorate_gtk" type="bool">
+			<_short>Only decorate GTK apps</_short>
+			<_long>When enabled, only requests client-side decoration for GTK applications.</_long>
+			<default>false</default>
+		</option>
 	</plugin>
 </wayfire>
diff --git a/src/view/view-impl.cpp b/src/view/view-impl.cpp
index f9610db..029cf2b 100644
--- a/src/view/view-impl.cpp
+++ b/src/view/view-impl.cpp
@@ -255,13 +255,15 @@ wlr_surface*wf::wlr_view_t::get_keyboard_focus_surface()
 
 bool wf::wlr_view_t::should_be_decorated()
 {
-    return role == wf::VIEW_ROLE_TOPLEVEL && !has_client_decoration;
+    return role == wf::VIEW_ROLE_TOPLEVEL && (!has_client_decoration || !has_gtk_decoration);
 }
 
 void wf::wlr_view_t::set_decoration_mode(bool use_csd)
 {
     bool was_decorated = should_be_decorated();
     this->has_client_decoration = use_csd;
+    wf::option_wrapper_t<bool> only_gtk ("core/only_decorate_gtk");
+    if (only_gtk == 1) this->has_gtk_decoration = false;
     if ((was_decorated != should_be_decorated()) && is_mapped())
     {
         wf::view_decoration_state_updated_signal data;
diff --git a/src/view/view-impl.hpp b/src/view/view-impl.hpp
index 8f34941..c75d5a3 100644
--- a/src/view/view-impl.hpp
+++ b/src/view/view-impl.hpp
@@ -136,6 +136,7 @@ class wlr_view_t :
     virtual void set_decoration_mode(bool use_csd);
     virtual void set_output(wf::output_t*) override;
     bool has_client_decoration = true;
+    bool has_gtk_decoration = true;
 
   protected:
     std::string title, app_id;

This gives me a global setting, only_decorate_gtk. If I set this to true, then Wayfire assumes that client-side decoration has only been applied to GTK applications, and all others are then decorated by the decor plugin or equivalent. If I combine this with setting the global QT_WAYLAND_DISABLE_WINDOWDECORATION environment variable to 1, I get all GTK apps decorated with the normal client-side decorations, and all other apps decorated by the decor plugin.

I'm not sure if this is the best approach, but it seems to work!

spl237 avatar Mar 29 '23 19:03 spl237

Is your custom decorator available for public viewing? Sounds like something I'd be interested in.

allaboutmikey avatar Apr 12 '23 03:04 allaboutmikey

Is your custom decorator available for public viewing? Sounds like something I'd be interested in.

Not yet - it's not quite ready for release. But it will definitely be made available in the not too distant future if you can hang on for a month or two!

spl237 avatar Apr 12 '23 17:04 spl237

I am in need of this interested feature too. Looking forward to your new decorator. :) Qt's CSDs are very ugly.

Jay-716 avatar Oct 12 '23 01:10 Jay-716

It was released yesterday! You can get it from https://github.com/raspberrypi-ui/wayfire.git - it's in the plugins subdirectory, and is called pixdecor.

spl237 avatar Oct 12 '23 08:10 spl237

Thanks for your amazing work! But honestly speaking, I am struggling to build it since there isn't a new build instruction and I am not familiar with deb packaging. XD Maybe adding some docs would be better? Or maybe I just did not find them. And may I ask would you consider merging these into official wayfire? Anyway, thanks!

Jay-716 avatar Oct 13 '23 06:10 Jay-716

@Jay-716 While I have not compiled r-pi's wayfire, the general procedure should be the same. Just clone the r-pi's wayfire repo, enter the wayfire folder and issue the following command:

dpkg-buildpackage -rfakeroot -uc -us

That should give you the deb file(s). I am assuming that you have all the build tools (build-essential, g++, fakeroot, meson, ninja-build and various libraries installed). If you do not have a package installed, dpkg-buildpackage will tell you the name of the package. Alternatively, you can look at debian/control file.

If you want to compile and install it manually, you can do so quite easily:

meson setup .build --prefix /usr --buildtype release -Duse_system_wfconfig=disabled -Duse_system_wlrtoos=enabled
ninja -C .build -k 0 -j $(nproc)
sudo ninja -C .build install

marcusbritanicus avatar Oct 13 '23 06:10 marcusbritanicus

@marcusbritanicus Thanks for your detailed instructions! I successfully built it with dpkg-buildpackage -b -rfakeroot -uc -us. (both official and raspberrypi-ui wayfire)

I tried the new pixdecor plugin. It is really nice. GTK and Qt decorations are finally uniformed. In my opinion, it would be a great enhancement if it could be merged into official wayfire or wayfire-plugin-extra. Of course, it is up to the developers. And thank you @spl237 !

Sorry for my poor English. :)

Jay-716 avatar Oct 13 '23 08:10 Jay-716

That's great - really glad you like it!

BTW, the plugin needs to be modified to work with the new 0.8.0 release; I've got that working here now, but it's not yet in a public repo; I'll make it public when I have done some more testing.

spl237 avatar Oct 13 '23 08:10 spl237

Does pixdecor will be merge in wayfire-plugins-extra in the future? I am looking forward to try this plugin. I try to avoid server-side decorated because I don't like how they look.

bluebyt avatar Dec 07 '23 23:12 bluebyt

@bluebyt I do not think that's likely to happen very soon. If I'm not totally wrong, pixdecor is currently based on Wayfire 0.7.x. There will be some considerable work involved in porting to 0.8.0, which has seen a few major API changes.

You can try windecor from w-p-e for some fancy decorations.

marcusbritanicus avatar Dec 08 '23 01:12 marcusbritanicus

As @marcusbritanicus says, the current pixdecor is based on Wayfire 0.7.x, and while I have indeed started the work to port it to 0.8, it's not yet finished; I got most of it done but then had to move onto other things.

spl237 avatar Dec 08 '23 10:12 spl237

Ok thank you @spl237 and @marcusbritanicus, I will follow the development.

bluebyt avatar Dec 08 '23 19:12 bluebyt

I put together a standalone version of pixdecor, ported to work with wayfire 0.8.0 and latest wayfire git. Hopefully, it is useful.

soreau avatar Dec 10 '23 11:12 soreau

You can also use https://github.com/marcof-nikogo/metacity-decor with server-side decoration. Available for wayfire 0.8.x though

clemencyworld1 avatar Aug 18 '24 07:08 clemencyworld1