Commit 4551509a authored by Bastien Nocera's avatar Bastien Nocera

Make it easy for apps to have dark themes

Some types of applications would benefit from having "dark" themes,
usually black backgrounds, such as:
* Movie players
* Photo management and display applications

To make it easy for those applications to prefer a dark theme,
we're adding the "gtk-application-prefer-dark-theme" GtkSetting, which
will make the theme loading code automatically look for a "gtkrc-dark"
file in the same directory you would usually find a gtkrc file.
the same name and a "-dark" suffix.

If no "-dark" gtkrc variant is available, the normal gtkrc will
be used.

https://bugzilla.gnome.org/show_bug.cgi?id=617955
parent b76557e9
......@@ -19,6 +19,16 @@ activate_action (GtkAction *action)
GtkWidget *dialog;
if (g_str_equal (name, "DarkTheme"))
{
gboolean value = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
GtkSettings *settings = gtk_settings_get_default ();
g_object_set (G_OBJECT (settings),
"gtk-application-prefer-dark-theme", value,
NULL);
return;
}
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
......@@ -212,6 +222,11 @@ static GtkToggleActionEntry toggle_entries[] = {
"Bold", /* tooltip */
G_CALLBACK (activate_action),
TRUE }, /* is_active */
{ "DarkTheme", NULL, /* name, stock id */
"_Prefer Dark Theme", NULL, /* label, accelerator */
"Prefer Dark Theme", /* tooltip */
G_CALLBACK (activate_action),
FALSE }, /* is_active */
};
static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
......@@ -265,6 +280,7 @@ static const gchar *ui_info =
" <menuitem action='Quit'/>"
" </menu>"
" <menu action='PreferencesMenu'>"
" <menuitem action='DarkTheme'/>"
" <menu action='ColorMenu'>"
" <menuitem action='Red'/>"
" <menuitem action='Green'/>"
......
......@@ -125,6 +125,21 @@ that GTK+ creates internally.
</refsect2>
<refsect2><title>Theme gtkrc files</title>
<anchor id="theme-gtkrc-files"/>
<para>
Theme RC files are loaded first from under the <filename>~/.themes/</filename>,
then from the directory from gtk_rc_get_theme_dir(). The files looked at will
be <filename>gtk-3.0/gtkrc</filename>.
</para>
<para>
When the application prefers dark themes
(see the #GtkSettings:gtk-application-prefer-dark-theme property for details),
<filename>gtk-3.0/gtkrc-dark</filename> will be loaded first, and if not present
<filename>gtk-3.0/gtkrc</filename> will be loaded.
</para>
</refsect2>
<refsect2>
<anchor id="optimizing-rc-style-matches"/>
<title>Optimizing RC Style Matches</title>
......
......@@ -117,9 +117,10 @@ struct _GtkRcContext
/* The files we have parsed, to reread later if necessary */
GSList *rc_files;
gchar *theme_name;
gchar *key_theme_name;
gchar *font_name;
gchar *theme_name;
gboolean prefer_dark_theme;
gchar *key_theme_name;
gchar *font_name;
gchar **pixmap_path;
......@@ -160,9 +161,10 @@ static GtkStyle * gtk_rc_style_to_style (GtkRcContext *context,
static GtkStyle* gtk_rc_init_style (GtkRcContext *context,
GSList *rc_styles);
static void gtk_rc_parse_default_files (GtkRcContext *context);
static void gtk_rc_parse_named (GtkRcContext *context,
static gboolean gtk_rc_parse_named (GtkRcContext *context,
const gchar *name,
const gchar *type);
const gchar *type,
const gchar *variant);
static void gtk_rc_context_parse_file (GtkRcContext *context,
const gchar *filename,
gint priority,
......@@ -624,6 +626,7 @@ gtk_rc_settings_changed (GtkSettings *settings,
{
gchar *new_theme_name;
gchar *new_key_theme_name;
gboolean new_prefer_dark_theme;
if (context->reloading)
return;
......@@ -631,12 +634,14 @@ gtk_rc_settings_changed (GtkSettings *settings,
g_object_get (settings,
"gtk-theme-name", &new_theme_name,
"gtk-key-theme-name", &new_key_theme_name,
"gtk-application-prefer-dark-theme", &new_prefer_dark_theme,
NULL);
if ((new_theme_name != context->theme_name &&
!(new_theme_name && context->theme_name && strcmp (new_theme_name, context->theme_name) == 0)) ||
(new_key_theme_name != context->key_theme_name &&
!(new_key_theme_name && context->key_theme_name && strcmp (new_key_theme_name, context->key_theme_name) == 0)))
!(new_key_theme_name && context->key_theme_name && strcmp (new_key_theme_name, context->key_theme_name) == 0)) ||
new_prefer_dark_theme != context->prefer_dark_theme)
{
gtk_rc_reparse_all_for_settings (settings, TRUE);
}
......@@ -692,6 +697,7 @@ gtk_rc_context_get (GtkSettings *settings)
"gtk-key-theme-name", &context->key_theme_name,
"gtk-font-name", &context->font_name,
"color-hash", &context->color_hash,
"gtk-application-prefer-dark-theme", &context->prefer_dark_theme,
NULL);
g_signal_connect (settings,
......@@ -710,6 +716,10 @@ gtk_rc_context_get (GtkSettings *settings)
"notify::color-hash",
G_CALLBACK (gtk_rc_color_hash_changed),
context);
g_signal_connect (settings,
"notify::gtk-application-prefer-dark-theme",
G_CALLBACK (gtk_rc_settings_changed),
context);
context->pixmap_path = NULL;
......@@ -785,22 +795,27 @@ _gtk_rc_context_destroy (GtkSettings *settings)
settings->rc_context = NULL;
}
static void
static gboolean
gtk_rc_parse_named (GtkRcContext *context,
const gchar *name,
const gchar *type)
const gchar *type,
const gchar *variant)
{
gchar *path = NULL;
const gchar *home_dir;
gchar *subpath;
gboolean retval;
retval = FALSE;
if (type)
subpath = g_strconcat ("gtk-3.0-", type,
G_DIR_SEPARATOR_S "gtkrc",
NULL);
else
subpath = g_strdup ("gtk-3.0" G_DIR_SEPARATOR_S "gtkrc");
subpath = g_strconcat ("gtk-3.0" G_DIR_SEPARATOR_S "gtkrc",
variant, NULL);
/* First look in the users home directory
*/
home_dir = g_get_home_dir ();
......@@ -831,9 +846,12 @@ gtk_rc_parse_named (GtkRcContext *context,
{
gtk_rc_context_parse_file (context, path, GTK_PATH_PRIO_THEME, FALSE);
g_free (path);
retval = TRUE;
}
g_free (subpath);
return retval;
}
static void
......@@ -1824,12 +1842,23 @@ gtk_rc_reparse_all_for_settings (GtkSettings *settings,
g_object_get (context->settings,
"gtk-theme-name", &context->theme_name,
"gtk-key-theme-name", &context->key_theme_name,
"gtk-application-prefer-dark-theme", &context->prefer_dark_theme,
NULL);
if (context->theme_name && context->theme_name[0])
gtk_rc_parse_named (context, context->theme_name, NULL);
{
if (context->prefer_dark_theme)
{
if (!gtk_rc_parse_named (context, context->theme_name, NULL, "-dark"))
gtk_rc_parse_named (context, context->theme_name, NULL, NULL);
}
else
{
gtk_rc_parse_named (context, context->theme_name, NULL, NULL);
}
}
if (context->key_theme_name && context->key_theme_name[0])
gtk_rc_parse_named (context, context->key_theme_name, "key");
gtk_rc_parse_named (context, context->key_theme_name, "key", NULL);
context->reloading = FALSE;
......
......@@ -125,7 +125,8 @@ enum {
PROP_ENABLE_TOOLTIPS,
PROP_TOOLBAR_STYLE,
PROP_TOOLBAR_ICON_SIZE,
PROP_AUTO_MNEMONICS
PROP_AUTO_MNEMONICS,
PROP_APPLICATION_PREFER_DARK_THEME
};
......@@ -1017,6 +1018,32 @@ gtk_settings_class_init (GtkSettingsClass *class)
GTK_PARAM_READWRITE),
NULL);
g_assert (result == PROP_AUTO_MNEMONICS);
/**
* GtkSettings:gtk-application-prefer-dark-theme:
*
* Whether the application prefers to use a dark theme. If a GTK+ theme
* includes a dark variant, it will be used instead of the configured
* theme.
*
* Some applications benefit from minimizing the amount of light pollution that
* interferes with the content. Good candidates for dark themes are photo and
* video editors that make the actual content get all the attention and minimize
* the distraction of the chrome.
*
* Dark themes should not be used for documents, where large spaces are white/light
* and the dark chrome creates too much contrast (web browser, text editor...).
*
* Since: 2.22
*/
result = settings_install_property_parser (class,
g_param_spec_boolean ("gtk-application-prefer-dark-theme",
P_("Application prefers a dark theme"),
P_("Whether the application prefers to have a dark theme."),
FALSE,
GTK_PARAM_READWRITE),
NULL);
g_assert (result == PROP_APPLICATION_PREFER_DARK_THEME);
}
static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment