vcl/inc/unx/gtk/gtkframe.hxx |    6 ++
 vcl/unx/gtk3/gtkframe.cxx    |  117 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 113 insertions(+), 10 deletions(-)

New commits:
commit 3a1db3389993fe9a52330fe36bb7bdfcea905242
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu May 19 09:34:16 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Fri May 20 21:29:42 2022 +0200

    follow org.freedesktop.appearance.color-scheme setting
    
    Change-Id: Id26d01fd19cc3ee12c0e14b785b3a5149d22baf5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134634
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Tested-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index ced3613ad0ca..c90afbdee899 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -185,6 +185,8 @@ class GtkSalFrame final : public SalFrame
     GtkEventControllerKey*          m_pKeyController;
     gulong                          m_nSettingChangedSignalId;
 #endif
+    gulong                          m_nPortalSettingChangedSignalId;
+    GDBusProxy*                     m_pSettingsPortal;
 #if !GTK_CHECK_VERSION(4, 0, 0)
     GdkWindow*                      m_pForeignParent;
     GdkNativeWindow                 m_aForeignParentWindow;
@@ -412,6 +414,8 @@ class GtkSalFrame final : public SalFrame
 
     bool HandleMenubarMnemonic(guint eState, guint nKeyval);
 
+    void ListenPortalSettings();
+
 public:
     cairo_surface_t*                m_pSurface;
     basegfx::B2IVector              m_aFrameSize;
@@ -633,6 +637,8 @@ public:
 
     const cairo_font_options_t* get_font_options();
 
+    void SetColorScheme(GVariant* variant);
+
     void DisallowCycleFocusOut();
     bool IsCycleFocusOutDisallowed() const;
     void AllowCycleFocusOut();
diff --git a/vcl/unx/gtk3/gtkframe.cxx b/vcl/unx/gtk3/gtkframe.cxx
index c6fb8ac14ac1..7108f9206380 100644
--- a/vcl/unx/gtk3/gtkframe.cxx
+++ b/vcl/unx/gtk3/gtkframe.cxx
@@ -76,6 +76,12 @@ int GtkSalFrame::m_nFloats = 0;
 
 static GDBusConnection* pSessionBus = nullptr;
 
+static void EnsureSessionBus()
+{
+    if (!pSessionBus)
+        pSessionBus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
+}
+
 sal_uInt16 GtkSalFrame::GetKeyModCode( guint state )
 {
     sal_uInt16 nCode = 0;
@@ -541,8 +547,7 @@ static void attach_menu_model(GtkSalFrame* pSalFrame)
 
 #if !GTK_CHECK_VERSION(4,0,0)
     // Get a DBus session connection.
-    if (!pSessionBus)
-        pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr);
+    EnsureSessionBus();
     if (!pSessionBus)
         return;
 
@@ -629,13 +634,9 @@ void GtkSalFrame::EnsureAppMenuWatch()
         return;
 
     // Get a DBus session connection.
-    if ( pSessionBus == nullptr )
-    {
-        pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, nullptr, nullptr );
-
-        if ( pSessionBus == nullptr )
-            return;
-    }
+    EnsureSessionBus();
+    if (!pSessionBus)
+        return;
 
     // Publish the menu only if AppMenu registrar is available.
     m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
@@ -698,8 +699,14 @@ GtkSalFrame::~GtkSalFrame()
     {
         SolarMutexGuard aGuard;
 
-        if(m_nWatcherId)
+        if (m_nWatcherId)
             g_bus_unwatch_name(m_nWatcherId);
+
+        if (m_nPortalSettingChangedSignalId)
+            g_signal_handler_disconnect(m_pSettingsPortal, 
m_nPortalSettingChangedSignalId);
+
+        if (m_pSettingsPortal)
+            g_object_unref(m_pSettingsPortal);
     }
 
     GtkWidget *pEventWidget = getMouseEventWidget();
@@ -900,6 +907,8 @@ void GtkSalFrame::InitCommon()
     m_pSurface = nullptr;
     m_nGrabLevel = 0;
     m_bSalObjectSetPosSize = false;
+    m_nPortalSettingChangedSignalId = 0;
+    m_pSettingsPortal = nullptr;
 
     m_aDamageHandler.handle = this;
     m_aDamageHandler.damaged = ::damaged;
@@ -1243,6 +1252,91 @@ void GtkSalFrame::AllowCycleFocusOut()
 #endif
 }
 
+namespace
+{
+    enum ColorScheme
+    {
+        DEFAULT,
+        PREFER_DARK,
+        PREFER_LIGHT
+    };
+
+    bool ReadColorScheme(GDBusProxy* proxy, GVariant** out)
+    {
+        g_autoptr (GVariant) ret =
+            g_dbus_proxy_call_sync(proxy, "Read",
+                                   g_variant_new ("(ss)", 
"org.freedesktop.appearance", "color-scheme"),
+                                   G_DBUS_CALL_FLAGS_NONE, G_MAXINT, nullptr, 
nullptr);
+        if (!ret)
+            return false;
+
+        g_autoptr (GVariant) child = nullptr;
+        g_variant_get(ret, "(v)", &child);
+        g_variant_get(child, "v", out);
+
+        return true;
+    }
+}
+
+void GtkSalFrame::SetColorScheme(GVariant* variant)
+{
+    if (!m_pWindow)
+        return;
+
+    guint32 color_scheme = g_variant_get_uint32(variant);
+    if (color_scheme > PREFER_LIGHT)
+        color_scheme = DEFAULT;
+
+    bool bDarkIconTheme(color_scheme == PREFER_DARK);
+    GtkSettings* pSettings = gtk_widget_get_settings(m_pWindow);
+    g_object_set(pSettings, "gtk-application-prefer-dark-theme", 
bDarkIconTheme, nullptr);
+}
+
+static void settings_portal_changed_cb(GDBusProxy*, const char*, const char* 
signal_name,
+                                       GVariant* parameters, gpointer frame)
+{
+    if (g_strcmp0(signal_name, "SettingChanged"))
+        return;
+
+    g_autoptr (GVariant) value = nullptr;
+    const char *name_space;
+    const char *name;
+    g_variant_get(parameters, "(&s&sv)", &name_space, &name, &value);
+
+    if (g_strcmp0(name_space, "org.freedesktop.appearance") ||
+        g_strcmp0(name, "color-scheme"))
+      return;
+
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+    pThis->SetColorScheme(value);
+}
+
+void GtkSalFrame::ListenPortalSettings()
+{
+    EnsureSessionBus();
+
+    if (!pSessionBus)
+        return;
+
+    m_pSettingsPortal = g_dbus_proxy_new_sync(pSessionBus,
+                                              G_DBUS_PROXY_FLAGS_NONE,
+                                              nullptr,
+                                              "org.freedesktop.portal.Desktop",
+                                              
"/org/freedesktop/portal/desktop",
+                                              
"org.freedesktop.portal.Settings",
+                                              nullptr,
+                                              nullptr);
+    if (!m_pSettingsPortal)
+        return;
+
+    g_autoptr (GVariant) value = nullptr;
+
+    if (!ReadColorScheme(m_pSettingsPortal, &value))
+        return;
+
+    SetColorScheme(value);
+    m_nPortalSettingChangedSignalId = g_signal_connect(m_pSettingsPortal, 
"g-signal", G_CALLBACK(settings_portal_changed_cb), this);
+}
 
 void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
 {
@@ -1403,6 +1497,9 @@ void GtkSalFrame::Init( SalFrame* pParent, 
SalFrameStyleFlags nStyle )
     {
         // Enable GMenuModel native menu
         attach_menu_model(this);
+
+        // Listen to portal settings for e.g. prefer dark theme
+        ListenPortalSettings();
     }
 }
 

Reply via email to