Skip to content

Ported to GTK4 #290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 122 commits into
base: master
Choose a base branch
from
Open

Ported to GTK4 #290

wants to merge 122 commits into from

Conversation

trigg
Copy link
Contributor

@trigg trigg commented Feb 16, 2025

Extensive changes to bring the code base up to working on GTK4.

Dependencies:

  • gtkmm 3 > 4 (same for gdk, glib so on)
  • gtk-layer-shell > gtk4-layer-shell
  • libdbusmenu-gtk3 > libdbusmenu-glib

Material changes overview:

  • The menus on system tray icons had to be rewritten from scratch as the supporting library appears to not be available for gtk4
    • Menu & items are regenerated when changed over the dbus wire
    • Icons appear to be getting ignored by Popover Menu. From all my reading this is intentional on GTK4s part
    • Dbus library answers that there are no tickbox or radio button variants despite testing intentionally for them. These menu items function correctly but don't display the radio/checkmark
    • I am convinced there are some memory leaks here and am squashing them as I find them
  • The entirety of the event handling side of GTK has been rewritten and redefined.
    • System tray icons, Window list windows and application menu context buttons are all now MenuButton allowing us to connect menu options to them
    • EventBox no longer exists, so event callbacks are connected in directly to widgets
    • Volume control slider popup stops scroll wheel & swipe events on button, so the popup no longer shows when volume changes fixed
  • Size allocation events, Redraw events, Scale change events have been removed from gtk4 and considered "the wrong way to do things" for most uses
    • Widgets should not base their internal logic on position & size
    • Scale is left to GTK4 to account for in all cases
    • Icon size should be changed with CSS rules only
    • All icon_size options have been fed into CSS Styles that are generated & updated from config
  • Output management and hotplugging is managed differently and worth double and triple checking by people with less boring monitor layouts than mine
  • Font override is removed. The only way I can see to do this now is to set it via CSS. While feeding the data in from the config is possible the way people write this options currently won't work in GTK4
    • Size needs to be in pixels or css sizes like : 17px 1.2em 0.9rem
    • Regex pulls apart the config option from user and pieces together in a way that should be backwards-compatible with existing configs

While I was in the area:

  • Implemented CSS directory loading for dock and background
  • Added some hover, open window & close window animations to default css
  • Added a dock window-close-animation option as it has adverse effects if you enable it but don't update your default css
  • Realised we'd be better served with a Gtk Revealer... but that's a bigger task that I'll do in a separate attempt.
  • Reworked Background, needs sanity check as I'm sure it'll leak memory
    • This looks to be in good condition and thanks @soreau for OpenGL implementation which improves the matter massively

I'm sure there's more, and will edit this as and when possible.

I look forward to uncrustify.

trigg and others added 30 commits February 8, 2025 16:02
- - Almost everything is broken.
- - This is expected
- - This is insane.
- - No, how is this even usable
- - Well whatever.
- - Someone please valgrind because I'm sure there's lots of bad ideas here.
- Fixes #8
- Partially fixes #9
- - Menu icons are currently still not shown
- - Menu checkboxes and radios show as generic label only
- Fixes #15
- Fixes #20
- Some changes to SNI dbusmenu
- Getting occassional segfaults in SNI dbusmenu so these need a better read-through before calling it
- - Still inherently broken until dbusmenu-glib reports a type back
- Dock takes entire width but sets itself to click-through on the outside
- Switched panel to using CenterBox which does a better job than my implementation
- Moved CSS dir loading into base app class
- First attempt at output changes
- Output hot plugging sorted.
- - This will need testing by people with more than 1 external monitor to see if there's any unknowns.
- Add an option to animate icons removed from dock
- Added to default dock CSS
- Fixed #4
- Fixed rectangle hints in dock and panel
- Fixed volume scrolling
- Fixed changing fill type in background triggering a new image load
- Remove GTK interactive debugging
@ammen99
Copy link
Member

ammen99 commented Jun 16, 2025

Hi and thanks for the big PR, very nice to see the update! I am going through the code to familiarize myself with whatever changes you have made, in the meantime I tried to copy the default CSS files and to compare the old and the new wf-panel. There are some very annoying differences which I am not sure how to solve, maybe they depend on the theme? Here is a screenshot, above is current master, below is this branch:

slurped

Most notably: backgrounds for menu, command and clock seem to not be unset, and there is a dark/black background behind the launchers instead of semi-transparent. Ditto for the ethernet connection. Icons also appear quite different.

@ammen99
Copy link
Member

ammen99 commented Jun 16, 2025

I am also getting Gtk-WARNING **: 09:47:31.071: Theme parser error: panel-selectors.css:21:11-20: Expected a number which I am not sure what to do about, I thought font could be monospace ...

@ammen99
Copy link
Member

ammen99 commented Jun 16, 2025

Window-list also appears weird:

slurped

Copy link
Member

@ammen99 ammen99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked over the changes, really good work :) My focus was the structure, haven't looked at every single UI call in detail but I assume we will find bugs like that during testing. A few things that I noticed or questions that I have.

@ammen99
Copy link
Member

ammen99 commented Jul 20, 2025

Suggestion to fix handling of command line options (we never feed argc/argv to gtk otherwise):

diff --git a/src/background/background.cpp b/src/background/background.cpp
index 9ff43bf..759a54d 100644
--- a/src/background/background.cpp
+++ b/src/background/background.cpp
@@ -630,9 +630,9 @@ class WayfireBackgroundApp : public WayfireShellApp
     static void create(int argc, char **argv)
     {
         WayfireShellApp::instance =
-            std::make_unique<WayfireBackgroundApp>(argc, argv);
+            std::make_unique<WayfireBackgroundApp>();
         g_unix_signal_add(SIGUSR1, sigusr1_handler, (void*)instance.get());
-        instance->run();
+        instance->run(argc, argv);
     }
 
     void handle_new_output(WayfireOutput *output) override
diff --git a/src/dock/dock-app.cpp b/src/dock/dock-app.cpp
index 08af3a1..dc6e6d9 100644
--- a/src/dock/dock-app.cpp
+++ b/src/dock/dock-app.cpp
@@ -1,7 +1,6 @@
 #include "dock.hpp"
 #include "toplevel.hpp"
 #include "toplevel-icon.hpp"
-#include "glibmm.h"
 #include <iostream>
 #include <gdk/wayland/gdkwayland.h>
 #include <css-config.hpp>
@@ -148,12 +147,11 @@ void WfDockApp::create(int argc, char **argv)
         throw std::logic_error("Running WfDockApp twice!");
     }
 
-    instance = std::unique_ptr<WfDockApp>{new WfDockApp(argc, argv)};
-    instance->run();
+    instance = std::unique_ptr<WfDockApp>{new WfDockApp()};
+    instance->run(argc, argv);
 }
 
-WfDockApp::WfDockApp(int argc, char **argv) :
-    WayfireShellApp(argc, argv), priv(new WfDockApp::impl())
+WfDockApp::WfDockApp() : WayfireShellApp(), priv(new WfDockApp::impl())
 {}
 WfDockApp::~WfDockApp() = default;
 
diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp
index aba6f56..ba461c2 100644
--- a/src/dock/dock.cpp
+++ b/src/dock/dock.cpp
@@ -3,9 +3,6 @@
 #include <glibmm/main.h>
 #include <gdk/wayland/gdkwayland.h>
 
-#include <iostream>
-#include <map>
-
 #include <gtk-utils.hpp>
 #include <wf-shell-app.hpp>
 #include <gtk4-layer-shell.h>
diff --git a/src/dock/dock.hpp b/src/dock/dock.hpp
index c0a1d5d..012c8e8 100644
--- a/src/dock/dock.hpp
+++ b/src/dock/dock.hpp
@@ -1,12 +1,11 @@
 #ifndef WF_DOCK_HPP
 #define WF_DOCK_HPP
 
-#include <map>
 #include <gtkmm/box.h>
 #include <wayland-client.h>
 
-#include "toplevel-icon.hpp"
 #include "wf-shell-app.hpp"
+#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
 #include <wf-option-wrap.hpp>
 
 class WfDock
@@ -45,7 +44,7 @@ class WfDockApp : public WayfireShellApp
     void handle_output_removed(WayfireOutput *output) override;
 
   private:
-    WfDockApp(int argc, char **argv);
+    WfDockApp();
 
     class impl;
     std::unique_ptr<impl> priv;
diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp
index 93ee6cd..f550758 100644
--- a/src/panel/panel.cpp
+++ b/src/panel/panel.cpp
@@ -6,16 +6,12 @@
 #include <gdk/wayland/gdkwayland.h>
 #include <gtk4-layer-shell.h>
 
-#include <stdio.h>
 #include <iostream>
 #include <sstream>
 
 #include <map>
-#include <filesystem>
 #include <css-config.hpp>
-
 #include "panel.hpp"
-#include "../util/gtk-utils.hpp"
 
 #include "widgets/battery.hpp"
 #include "widgets/command-output.hpp"
@@ -77,7 +73,7 @@ class WayfirePanel::impl
     {
         window = std::make_unique<WayfireAutohidingWindow>(output, "panel");
 
-        window->set_default_size(0, minimal_panel_height);
+        window->set_size_request(-1, minimal_panel_height);
         window->get_style_context()->add_class("wf-panel");
         panel_layer.set_callback(set_panel_layer);
         set_panel_layer(); // initial setting
@@ -410,13 +406,12 @@ void WayfirePanelApp::create(int argc, char **argv)
         throw std::logic_error("Running WayfirePanelApp twice!");
     }
 
-    instance = std::unique_ptr<WayfireShellApp>(new WayfirePanelApp{argc, argv});
-    instance->run();
+    instance = std::unique_ptr<WayfireShellApp>(new WayfirePanelApp{});
+    instance->run(argc, argv);
 }
 
 WayfirePanelApp::~WayfirePanelApp() = default;
-WayfirePanelApp::WayfirePanelApp(int argc, char **argv) :
-    WayfireShellApp(argc, argv), priv(new impl())
+WayfirePanelApp::WayfirePanelApp() : WayfireShellApp(), priv(new impl())
 {}
 
 int main(int argc, char **argv)
diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp
index 6ade607..cae9903 100644
--- a/src/panel/panel.hpp
+++ b/src/panel/panel.hpp
@@ -39,7 +39,7 @@ class WayfirePanelApp : public WayfireShellApp
     void on_config_reload() override;
 
   private:
-    WayfirePanelApp(int argc, char **argv);
+    WayfirePanelApp();
 
 
     class impl;
diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp
index 0475340..3b9f4e2 100644
--- a/src/util/wf-shell-app.cpp
+++ b/src/util/wf-shell-app.cpp
@@ -124,6 +124,7 @@ void WayfireShellApp::add_css_file(std::string file, int priority)
 bool WayfireShellApp::parse_cfgfile(const Glib::ustring & option_name,
     const Glib::ustring & value, bool has_value)
 {
+    std::cout << "%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
     std::cout << "Using custom config file " << value << std::endl;
     cmdline_config = value;
     return true;
@@ -284,8 +285,9 @@ void WayfireShellApp::rem_output(GMonitor monitor)
     }
 }
 
-WayfireShellApp::WayfireShellApp(int argc, char **argv)
+WayfireShellApp::WayfireShellApp()
 {
+    std::cout << "setting up" << std::endl;
     app = Gtk::Application::create("", Gio::Application::Flags::HANDLES_COMMAND_LINE);
     app->signal_activate().connect(
         sigc::mem_fun(*this, &WayfireShellApp::on_activate));
@@ -312,9 +314,9 @@ WayfireShellApp& WayfireShellApp::get()
     return *instance;
 }
 
-void WayfireShellApp::run()
+void WayfireShellApp::run(int argc, char **argv)
 {
-    app->run();
+    app->run(argc, argv);
 }
 
 /* -------------------------- WayfireOutput --------------------------------- */
diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp
index e9f8174..44c1357 100644
--- a/src/util/wf-shell-app.hpp
+++ b/src/util/wf-shell-app.hpp
@@ -1,7 +1,6 @@
 #ifndef WF_SHELL_APP_HPP
 #define WF_SHELL_APP_HPP
 
-#include <set>
 #include <string>
 #include <wayfire/config/config-manager.hpp>
 
@@ -70,12 +69,12 @@ class WayfireShellApp
     wf::config::config_manager_t config;
     zwf_shell_manager_v2 *wf_shell_manager = nullptr;
 
-    WayfireShellApp(int argc, char **argv);
+    WayfireShellApp();
     virtual ~WayfireShellApp();
 
     virtual std::string get_config_file();
     virtual std::string get_css_config_dir();
-    virtual void run();
+    virtual void run(int argc, char **argv);
 
     virtual void on_config_reload()
     {}

soreau and others added 12 commits July 20, 2025 05:39
This makes it so minimize targets of width <= 0 || height <= 0 are discarded,
which fixes unminimize animations after selecting a window-list button on
another output.
window-list: Don't send empty minimize targets
- split layout logic to own files
-  Remove abritrary char-width rule from window list labels
- Fixed smooth rearranging of window list
Re-implements the smooth window-list reordering via gtk layoutmanager.

The logic is intentionally sparse and missing most features of boxlayout for simplicity sake.
shell-app: set argc/argv when running gtk app
- bump gtk4-layer-shell
@trigg
Copy link
Contributor Author

trigg commented Jul 25, 2025

I am also getting Gtk-WARNING **: 09:47:31.071: Theme parser error: panel-selectors.css:21:11-20: Expected a number which I am not sure what to do about, I thought font could be monospace ...

Specifically to this : The font string needed to be formatted exactly in the order it expected. This didn't match other CSS font string I'd seen before...

I wrote a parser that splits up font strings and pieces it together again in a way this will accept.

https://github.com/trigg/wf-shell/blob/1a236bb9809573d8dc275e82e566f8a62cb85f75/src/util/css-config.cpp#L84

soreau and others added 2 commits July 27, 2025 07:52
Before, closing a toplevel and unminimizing another would unminimize from
the target position before closing the other toplevel. Sending the rectangle
hints after removing the button from the Gtk::Box did not work. Instead, we
send the rectangle hints from the layout vfunc allocation. This required
a lot of refactoring, but now the code is simpler and easier to work with.
window-list: Fix minimize targets after closing a toplevel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants