diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt index 2b412040ea..287599b54b 100644 --- a/docs/reference/gdk/gdk3-sections.txt +++ b/docs/reference/gdk/gdk3-sections.txt @@ -949,6 +949,7 @@ gdk_x11_screen_supports_net_wm_hint gdk_x11_window_foreign_new_for_display gdk_x11_window_lookup_for_display gdk_x11_window_get_xid +gdk_x11_window_set_theme_variant gdk_x11_window_set_user_time gdk_x11_window_move_to_current_desktop gdk_x11_get_default_root_xwindow diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index b159b1ce32..9581e7ddd5 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -564,6 +564,7 @@ gdk_x11_window_lookup_for_display gdk_x11_window_get_type gdk_x11_window_get_xid gdk_x11_window_move_to_current_desktop +gdk_x11_window_set_theme_variant gdk_x11_window_set_user_time gdk_x11_xatom_to_atom gdk_x11_xatom_to_atom_for_display diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 6cd5573a40..fd62e4caad 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -3086,6 +3086,45 @@ gdk_x11_window_set_user_time (GdkWindow *window, toplevel->user_time = timestamp_long; } +/** + * gdk_x11_window_set_theme_variant: + * @window: a #GdkWindow + * @variant: the theme variant to export + * + * GTK+ applications can request a dark theme variant. In order to + * make other applications - namely window managers using GTK+ for + * themeing - aware of this choice, GTK+ uses this function to + * export the requested theme variant as _GTK_THEME_VARIANT property + * on toplevel windows. + * + * Note that this property is automatically updated by GTK+, so this + * function should only be used by applications which do not use GTK+ + * to create toplevel windows. + * + * Since: 3.2 + */ +void +gdk_x11_window_set_theme_variant (GdkWindow *window, + char *variant) +{ + GdkDisplay *display = gdk_window_get_display (window); + + if (variant != NULL) + { + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (display, "_GTK_THEME_VARIANT"), + gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8, + PropModeReplace, (guchar *)variant, strlen (variant)); + } + else + { + XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (display, "_GTK_THEME_VARIANT")); + } +} + #define GDK_SELECTION_MAX_SIZE(display) \ MIN(262144, \ XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \ diff --git a/gdk/x11/gdkx11window.h b/gdk/x11/gdkx11window.h index ecfbea5c8d..1e8a09ad34 100644 --- a/gdk/x11/gdkx11window.h +++ b/gdk/x11/gdkx11window.h @@ -57,6 +57,8 @@ GType gdk_x11_window_get_type (void); Window gdk_x11_window_get_xid (GdkWindow *window); void gdk_x11_window_set_user_time (GdkWindow *window, guint32 timestamp); +void gdk_x11_window_set_theme_variant (GdkWindow *window, + char *variant); void gdk_x11_window_move_to_current_desktop (GdkWindow *window); /** diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 6d42d422f9..8d5113e0c2 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -413,6 +413,10 @@ static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window); static void gtk_window_free_key_hash (GtkWindow *window); static void gtk_window_on_composited_changed (GdkScreen *screen, GtkWindow *window); +static void gtk_window_on_theme_variant_changed (GtkSettings *settings, + GParamSpec *pspec, + GtkWindow *window); +static void gtk_window_set_theme_variant (GtkWindow *window); static GSList *toplevel_list = NULL; static guint window_signals[LAST_SIGNAL] = { 0 }; @@ -1111,6 +1115,12 @@ gtk_window_init (GtkWindow *window) if (priv->screen) g_signal_connect (priv->screen, "composited-changed", G_CALLBACK (gtk_window_on_composited_changed), window); + +#ifdef GDK_WINDOWING_X11 + g_signal_connect (gtk_settings_get_default (), + "notify::gtk-application-prefer-dark-theme", + G_CALLBACK (gtk_window_on_theme_variant_changed), window); +#endif } static void @@ -4531,6 +4541,12 @@ gtk_window_finalize (GObject *object) g_free (priv->startup_id); +#ifdef GDK_WINDOWING_X11 + g_signal_handlers_disconnect_by_func (gtk_settings_get_default (), + gtk_window_on_theme_variant_changed, + window); +#endif + G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object); } @@ -4696,6 +4712,9 @@ gtk_window_map (GtkWidget *widget) gdk_window_set_keep_below (toplevel, priv->below_initially); + if (priv->type == GTK_WINDOW_TOPLEVEL) + gtk_window_set_theme_variant (window); + /* No longer use the default settings */ priv->need_default_size = FALSE; priv->need_default_position = FALSE; @@ -8008,6 +8027,34 @@ gtk_window_set_screen (GtkWindow *window, gtk_widget_map (widget); } +static void +gtk_window_set_theme_variant (GtkWindow *window) +{ +#ifdef GDK_WINDOWING_X11 + GdkWindow *gdk_window; + gboolean dark_theme_requested; + + g_object_get (gtk_settings_get_default (), + "gtk-application-prefer-dark-theme", &dark_theme_requested, + NULL); + + gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); + + if (GDK_IS_X11_WINDOW (gdk_window)) + gdk_x11_window_set_theme_variant (gdk_window, + dark_theme_requested ? "dark" : NULL); +#endif +} + +static void +gtk_window_on_theme_variant_changed (GtkSettings *settings, + GParamSpec *pspec, + GtkWindow *window) +{ + if (window->priv->type == GTK_WINDOW_TOPLEVEL) + gtk_window_set_theme_variant (window); +} + static void gtk_window_on_composited_changed (GdkScreen *screen, GtkWindow *window)