@@ -183,6 +183,64 @@ static void notify_gtk_font_name(GObject*, GParamSpec*, void*)
183183}
184184}
185185
186+ static bool UpdatePreferDark (GVariant* value)
187+ {
188+ // 0: No preference, 1: Prefer dark appearance, 2: Prefer light appearance
189+ gboolean preferDark = g_variant_get_uint32 (value) == 1 ;
190+
191+ GtkSettings* settings = gtk_settings_get_default ();
192+ char * themeName;
193+ gboolean preferDarkPrev;
194+ g_object_get (settings,
195+ " gtk-theme-name" , &themeName,
196+ " gtk-application-prefer-dark-theme" , &preferDarkPrev, nullptr );
197+
198+ // We don't need to enable prefer-dark if the theme is already dark
199+ if (strstr (themeName, " -dark" ) || strstr (themeName, " -Dark" ))
200+ preferDark = false ;
201+ g_free (themeName);
202+
203+ const bool changed = preferDark != preferDarkPrev;
204+ if (changed)
205+ {
206+ g_object_set (settings,
207+ " gtk-application-prefer-dark-theme" , preferDark, nullptr );
208+ }
209+ return changed;
210+ }
211+
212+ // "g-signal" from GDBusProxy
213+ extern " C" {
214+ static void
215+ proxy_g_signal (GDBusProxy*, const char *, const char * signal_name, GVariant* parameters, void *)
216+ {
217+ if (strcmp (signal_name, " SettingChanged" ) != 0 )
218+ return ;
219+
220+ const char * nameSpace;
221+ const char * key;
222+ GVariant* value;
223+ g_variant_get (parameters, " (&s&sv)" , &nameSpace, &key, &value);
224+ if (strcmp (nameSpace, " org.freedesktop.appearance" ) == 0 &&
225+ strcmp (key, " color-scheme" ) == 0 )
226+ {
227+ if (UpdatePreferDark (value))
228+ {
229+ for (int i = wxSYS_COLOUR_MAX; i--;)
230+ gs_systemColorCache[i].UnRef ();
231+
232+ for (auto * win: wxTopLevelWindows)
233+ {
234+ wxSysColourChangedEvent event;
235+ event.SetEventObject (win);
236+ win->HandleWindowEvent (event);
237+ }
238+ }
239+ }
240+ g_variant_unref (value);
241+ }
242+ }
243+
186244// Some notes on using GtkStyleContext. Style information from a context
187245// attached to a non-visible GtkWidget is not accurate. The context has an
188246// internal visibility state, controlled by the widget, which it presumably
@@ -1124,12 +1182,68 @@ bool wxSystemSettingsNative::HasFeature(wxSystemFeature index)
11241182class wxSystemSettingsModule : public wxModule
11251183{
11261184public:
1127- virtual bool OnInit () wxOVERRIDE { return true ; }
1185+ virtual bool OnInit () wxOVERRIDE;
11281186 virtual void OnExit () wxOVERRIDE;
1187+
1188+ #ifdef __WXGTK3__
1189+ GDBusProxy* m_proxy;
1190+ #endif
11291191 wxDECLARE_DYNAMIC_CLASS (wxSystemSettingsModule);
11301192};
11311193wxIMPLEMENT_DYNAMIC_CLASS (wxSystemSettingsModule, wxModule);
11321194
1195+ bool wxSystemSettingsModule::OnInit ()
1196+ {
1197+ #ifdef __WXGTK3__
1198+ // Gnome has gone to a dark style setting rather than a selectable dark
1199+ // theme, available via GSettings as the 'color-scheme' key under the
1200+ // 'org.gnome.desktop.interface' schema. It's also available via a "portal"
1201+ // (https://docs.flatpak.org/en/latest/portal-api-reference.html), which
1202+ // has the advantage of allowing the setting to be accessed from within a
1203+ // virtualized environment such as Flatpak. Since the setting does not
1204+ // change the theme, we propagate it to the GtkSettings
1205+ // 'gtk-application-prefer-dark-theme' property to get a dark theme.
1206+
1207+ m_proxy = nullptr ;
1208+
1209+ if (getenv (" ORCA_SLICER_DARK_THEME" ) != nullptr ) {
1210+ /* 1 for prefer dark */
1211+ GVariant *value = g_variant_new_uint32 (1 );
1212+ UpdatePreferDark (value);
1213+ g_variant_unref (value);
1214+ }
1215+ // GTK_THEME environment variable overrides other settings
1216+ else if (getenv (" GTK_THEME" ) == nullptr )
1217+ {
1218+ m_proxy = g_dbus_proxy_new_for_bus_sync (
1219+ G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, nullptr ,
1220+ " org.freedesktop.portal.Desktop" ,
1221+ " /org/freedesktop/portal/desktop" ,
1222+ " org.freedesktop.portal.Settings" ,
1223+ nullptr , nullptr );
1224+ }
1225+ if (m_proxy)
1226+ {
1227+ g_signal_connect (m_proxy, " g-signal" , G_CALLBACK (proxy_g_signal), nullptr );
1228+
1229+ GVariant* ret = g_dbus_proxy_call_sync (m_proxy, " Read" ,
1230+ g_variant_new (" (ss)" , " org.freedesktop.appearance" , " color-scheme" ),
1231+ G_DBUS_CALL_FLAGS_NONE, -1 , nullptr , nullptr );
1232+ if (ret)
1233+ {
1234+ GVariant* child;
1235+ g_variant_get (ret, " (v)" , &child);
1236+ GVariant* value = g_variant_get_variant (child);
1237+ UpdatePreferDark (value);
1238+ g_variant_unref (value);
1239+ g_variant_unref (child);
1240+ g_variant_unref (ret);
1241+ }
1242+ }
1243+ #endif // __WXGTK3__
1244+ return true ;
1245+ }
1246+
11331247void wxSystemSettingsModule::OnExit ()
11341248{
11351249#ifdef __WXGTK3__
@@ -1141,6 +1255,8 @@ void wxSystemSettingsModule::OnExit()
11411255 g_signal_handlers_disconnect_by_func (settings,
11421256 (void *)notify_gtk_font_name, NULL );
11431257 }
1258+ if (m_proxy)
1259+ g_object_unref (m_proxy);
11441260#endif
11451261 if (gs_tlw_parent)
11461262 {
0 commit comments