From: Debarshi Ray Date: Mon, 12 May 2014 14:57:18 +0200 Subject: [PATCH] Restore transparency The transparency settings were removed as a side effect of 2bff4b63ed3ceef6055e35563e9b0b33ad57349d This restores them and you will need a compositing window manager to use it. The background image setting, also known as faux transparency, was not restored. Also contains 326c4f143511a3fae61aed1466568260a2ac1c4e Mon Sep 17 00:00:00 2001 Lars Uebernickel Wed, 28 May 2014 14:11:02 +0200 [PATCH] window: Make the drawing robust across all themes There are lots of themes out there in the wild that do not specify a background-color for all widgets and the default is transparent. This is usually not a problem because GTK+ sets an opaque region on the whole window and things without a background-color get drawn with the theme's default background colour. However, to achieve transparency we disable the opaque region by making the window app-paintable. This can lead to transparent menubars or notebook tabs in some themes. We can avoid this by ensuring that the window always renders a background. https://bugzilla.gnome.org/show_bug.cgi?id=730016 --- src/org.gnome.Terminal.gschema.xml | 14 +++++ src/preferences.ui | 121 +++++++++++++++++++++++++++++++++++++ src/profile-editor.cc | 17 ++++++ src/terminal-schemas.hh | 4 ++ src/terminal-screen.cc | 45 +++++++++++++- src/terminal-window.cc | 28 +++++++++ 6 files changed, 228 insertions(+), 1 deletion(-) diff --git a/src/org.gnome.Terminal.gschema.xml b/src/org.gnome.Terminal.gschema.xml index 26b96ac..9c16b53 100644 --- a/src/org.gnome.Terminal.gschema.xml +++ b/src/org.gnome.Terminal.gschema.xml @@ -349,6 +349,20 @@ 'narrow' Whether ambiguous-width characters are narrow or wide when using UTF-8 encoding + + false + Whether to use a transparent background + + + true + Whether to use the value of TerminalScreen-background-darkness, + if available, from the theme for the transparency value. + + + 50 + Adjust the amount of transparency + A value between 0 and 100, where 0 is opaque and 100 is fully transparent. + diff --git a/src/preferences.ui b/src/preferences.ui index d1aca7b..c01f16b 100644 --- a/src/preferences.ui +++ b/src/preferences.ui @@ -113,6 +113,11 @@ + + 100 + 1 + 10 + @@ -1402,6 +1407,122 @@ 1 + + + True + False + horizontal + 12 + + + Use t_ransparent background + True + True + False + True + 0 + True + + + False + False + 0 + + + + + True + False + horizontal + 6 + + + True + False + 0.5 + none + + + + False + False + 0 + + + + + True + True + background-transparent-adjustment + False + + + True + True + 1 + + + + + True + False + 0.5 + full + + + + False + False + 2 + + + + + True + True + 1 + + + + + True + True + 2 + + + + + True + False + horizontal + 12 + + + Use transparency from system theme + True + True + False + True + 0 + True + + + False + False + 0 + + + + + True + True + 3 + + diff --git a/src/profile-editor.cc b/src/profile-editor.cc index a99fb89..a88e72d 100644 --- a/src/profile-editor.cc +++ b/src/profile-editor.cc @@ -1492,6 +1492,23 @@ profile_prefs_load (const char *uuid, GSettings *profile) GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET)); gtk_widget_set_visible (w, (vte_get_feature_flags() & VTE_FEATURE_FLAG_SIXEL) != 0); + + profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_TRANSPARENT_BACKGROUND, + gtk_builder_get_object (builder, "use-transparent-background"), + "active", GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET)); + profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_TRANSPARENT_BACKGROUND, + gtk_builder_get_object (builder, "background-transparent-scale-box"), + "sensitive", GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY)); + profile_prefs_settings_bind (profile, TERMINAL_PROFILE_BACKGROUND_TRANSPARENCY_PERCENT, + gtk_builder_get_object (builder, "background-transparent-adjustment"), + "value", GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET)); + profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_THEME_TRANSPARENCY, + gtk_builder_get_object (builder, "use-theme-transparency-checkbutton"), + "active", GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET)); + profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_THEME_TRANSPARENCY, + gtk_builder_get_object (builder, "use-transparent-background-box"), + "sensitive", + GSettingsBindFlags(G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN | G_SETTINGS_BIND_NO_SENSITIVITY)); } /* Called once per Preferences window, to destroy stuff that doesn't depend on the profile being edited */ diff --git a/src/terminal-schemas.hh b/src/terminal-schemas.hh index b146ba8..b93bd02 100644 --- a/src/terminal-schemas.hh +++ b/src/terminal-schemas.hh @@ -78,6 +78,10 @@ G_BEGIN_DECLS #define TERMINAL_PROFILE_VISIBLE_NAME_KEY "visible-name" #define TERMINAL_PROFILE_WORD_CHAR_EXCEPTIONS_KEY "word-char-exceptions" +#define TERMINAL_PROFILE_USE_TRANSPARENT_BACKGROUND "use-transparent-background" +#define TERMINAL_PROFILE_USE_THEME_TRANSPARENCY "use-theme-transparency" +#define TERMINAL_PROFILE_BACKGROUND_TRANSPARENCY_PERCENT "background-transparency-percent" + #define TERMINAL_SETTING_CONFIRM_CLOSE_KEY "confirm-close" #define TERMINAL_SETTING_CONTEXT_INFO_KEY "context-info" #define TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY "default-show-menubar" diff --git a/src/terminal-screen.cc b/src/terminal-screen.cc index 0ef74f3..a987f26 100644 --- a/src/terminal-screen.cc +++ b/src/terminal-screen.cc @@ -718,6 +718,14 @@ terminal_screen_class_init (TerminalScreenClass *klass) g_type_class_add_private (object_class, sizeof (TerminalScreenPrivate)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_float ("background-darkness", NULL, NULL, -1, 1, -1, + GParamFlags(G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB))); + + n_url_regexes = G_N_ELEMENTS (url_regex_patterns); precompile_regexes (url_regex_patterns, n_url_regexes, &url_regexes, &url_regex_flavors); n_extra_regexes = G_N_ELEMENTS (extra_regex_patterns); @@ -1112,7 +1120,10 @@ terminal_screen_profile_changed_cb (GSettings *profile, prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_COLORS_SET_KEY) || prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_BACKGROUND_COLOR_KEY) || prop_name == I_(TERMINAL_PROFILE_HIGHLIGHT_FOREGROUND_COLOR_KEY) || - prop_name == I_(TERMINAL_PROFILE_PALETTE_KEY)) + prop_name == I_(TERMINAL_PROFILE_PALETTE_KEY) || + prop_name == I_(TERMINAL_PROFILE_USE_TRANSPARENT_BACKGROUND) || + prop_name == I_(TERMINAL_PROFILE_BACKGROUND_TRANSPARENCY_PERCENT) || + prop_name == I_(TERMINAL_PROFILE_USE_THEME_TRANSPARENCY)) update_color_scheme (screen); if (!prop_name || prop_name == I_(TERMINAL_PROFILE_AUDIBLE_BELL_KEY)) @@ -1198,6 +1209,9 @@ update_color_scheme (TerminalScreen *screen) GdkRGBA *highlight_bgp = nullptr, *highlight_fgp = nullptr; GtkStyleContext *context; gboolean use_theme_colors; + GtkWidget *toplevel; + gboolean transparent, theme_transparent; + gfloat style_darkness; context = gtk_widget_get_style_context (widget); gtk_style_context_get_color (context, gtk_style_context_get_state (context), &theme_fg); @@ -1240,6 +1254,31 @@ update_color_scheme (TerminalScreen *screen) } colors = terminal_g_settings_get_rgba_palette (priv->profile, TERMINAL_PROFILE_PALETTE_KEY, &n_colors); + theme_transparent = g_settings_get_boolean (profile, TERMINAL_PROFILE_USE_THEME_TRANSPARENCY); + transparent = g_settings_get_boolean (profile, TERMINAL_PROFILE_USE_TRANSPARENT_BACKGROUND); + + gtk_widget_style_get (GTK_WIDGET (screen), + "background-darkness", &style_darkness, + NULL); + + if (theme_transparent && style_darkness >= 0) + { + bg.alpha = style_darkness; + } + else if (transparent) + { + gint transparency_percent; + + transparency_percent = g_settings_get_int (profile, TERMINAL_PROFILE_BACKGROUND_TRANSPARENCY_PERCENT); + bg.alpha = (100 - transparency_percent) / 100.0; + } + else + bg.alpha = 1.0; + + /* If this gets out of range, let's not crash */ + if (bg.alpha < 0.0 || bg.alpha > 1.0) + bg.alpha = 1.0; + vte_terminal_set_colors (VTE_TERMINAL (screen), &fg, &bg, colors, n_colors); vte_terminal_set_color_bold (VTE_TERMINAL (screen), boldp); @@ -1247,6 +1286,10 @@ update_color_scheme (TerminalScreen *screen) vte_terminal_set_color_cursor_foreground (VTE_TERMINAL (screen), cursor_fgp); vte_terminal_set_color_highlight (VTE_TERMINAL (screen), highlight_bgp); vte_terminal_set_color_highlight_foreground (VTE_TERMINAL (screen), highlight_fgp); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (screen)); + if (toplevel != NULL && gtk_widget_is_toplevel (toplevel)) + gtk_widget_set_app_paintable (toplevel, transparent); } static void diff --git a/src/terminal-window.cc b/src/terminal-window.cc index 60f4950..269514f 100644 --- a/src/terminal-window.cc +++ b/src/terminal-window.cc @@ -1963,6 +1963,26 @@ terminal_window_realize (GtkWidget *widget) terminal_window_update_size (window); } +static gboolean +terminal_window_draw (GtkWidget *widget, + cairo_t *cr) +{ + if (gtk_widget_get_app_paintable (widget)) + { + GtkStyleContext *context; + int width; + int height; + + context = gtk_widget_get_style_context (widget); + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + gtk_render_background (context, cr, 0, 0, width, height); + gtk_render_frame (context, cr, 0, 0, width, height); + } + + return GTK_WIDGET_CLASS (terminal_window_parent_class)->draw (widget, cr); +} + static gboolean terminal_window_state_event (GtkWidget *widget, GdkEventWindowState *event) @@ -2133,6 +2153,8 @@ terminal_window_init (TerminalWindow *window) }; TerminalWindowPrivate *priv; TerminalApp *app; + GdkScreen *screen; + GdkVisual *visual; GSettings *gtk_debug_settings; GtkWindowGroup *window_group; // GtkAccelGroup *accel_group; @@ -2148,6 +2170,11 @@ terminal_window_init (TerminalWindow *window) gtk_widget_init_template (GTK_WIDGET (window)); + screen = gtk_widget_get_screen (GTK_WIDGET (window)); + visual = gdk_screen_get_rgba_visual (screen); + if (visual != NULL) + gtk_widget_set_visual (GTK_WIDGET (window), visual); + uuid_generate (u); uuid_unparse (u, uuidstr); priv->uuid = g_strdup (uuidstr); @@ -2296,6 +2323,7 @@ terminal_window_class_init (TerminalWindowClass *klass) widget_class->show = terminal_window_show; widget_class->realize = terminal_window_realize; + widget_class->draw = terminal_window_draw; widget_class->window_state_event = terminal_window_state_event; widget_class->screen_changed = terminal_window_screen_changed; widget_class->style_updated = terminal_window_style_updated;