Skip to content

Commit 139e4f2

Browse files
committed
Patch wxWidgets to automatically select dark theme variant
ref to OrcaSlicer/OrcaSlicer#7283
1 parent e4ee967 commit 139e4f2

1 file changed

Lines changed: 117 additions & 1 deletion

File tree

src/gtk/settings.cpp

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)
11241182
class wxSystemSettingsModule: public wxModule
11251183
{
11261184
public:
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
};
11311193
wxIMPLEMENT_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+
11331247
void 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

Comments
 (0)