diff --git a/include/wx/gtk/window.h b/include/wx/gtk/window.h index baeb7041fb..4c9078e989 100644 --- a/include/wx/gtk/window.h +++ b/include/wx/gtk/window.h @@ -14,6 +14,7 @@ #ifdef __WXGTK3__ typedef struct _cairo cairo_t; + typedef struct _GtkStyleProvider GtkStyleProvider; #define WXUNUSED_IN_GTK3(x) #else #define WXUNUSED_IN_GTK3(x) x @@ -373,10 +374,8 @@ protected: #ifndef __WXGTK3__ // Called by ApplyWidgetStyle (which is called by SetFont() and // SetXXXColour etc to apply style changed to native widgets) to create - // modified GTK style with non-standard attributes. If forceStyle=true, - // creates empty GtkRcStyle if there are no modifications, otherwise - // returns NULL in such case. - GtkRcStyle *GTKCreateWidgetStyle(bool forceStyle = false); + // modified GTK style with non-standard attributes. + GtkRcStyle* GTKCreateWidgetStyle(); #endif void GTKApplyWidgetStyle(bool forceStyle = false); @@ -414,6 +413,8 @@ private: #ifdef __WXGTK3__ // paint context is stashed here so wxPaintDC can use it cairo_t* m_paintContext; + // style provider for "background-image" + GtkStyleProvider* m_styleProvider; public: cairo_t* GTKPaintContext() const diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 978f556ca7..0543ea56e7 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -2191,6 +2191,7 @@ void wxWindowGTK::Init() m_nativeSizeEvent = false; #ifdef __WXGTK3__ m_paintContext = NULL; + m_styleProvider = NULL; #endif m_isScrolling = false; @@ -2390,6 +2391,11 @@ wxWindowGTK::~wxWindowGTK() while (IsFrozen()) Thaw(); +#ifdef __WXGTK3__ + if (m_styleProvider) + g_object_unref(m_styleProvider); +#endif + if (m_widget) { // Note that gtk_widget_destroy() does not destroy the widget, it just @@ -4011,16 +4017,8 @@ PangoContext *wxWindowGTK::GTKGetPangoDefaultContext() } #ifndef __WXGTK3__ -GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) +GtkRcStyle* wxWindowGTK::GTKCreateWidgetStyle() { - // do we need to apply any changes at all? - if ( !forceStyle && - !m_font.IsOk() && - !m_foregroundColour.IsOk() && !m_backgroundColour.IsOk() ) - { - return NULL; - } - GtkRcStyle *style = gtk_rc_style_new(); if ( m_font.IsOk() ) @@ -4081,18 +4079,35 @@ GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) } #endif // !__WXGTK3__ -void wxWindowGTK::GTKApplyWidgetStyle(bool WXUNUSED_IN_GTK3(forceStyle)) +void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle) { -#ifdef __WXGTK3__ - DoApplyWidgetStyle(NULL); -#else - GtkRcStyle *style = GTKCreateWidgetStyle(forceStyle); - if ( style ) + if (forceStyle || m_font.IsOk() || + m_foregroundColour.IsOk() || m_backgroundColour.IsOk()) { +#ifdef __WXGTK3__ + if (m_backgroundColour.IsOk()) + { + // create a GtkStyleProvider to override "background-image" + if (m_styleProvider == NULL) + m_styleProvider = GTK_STYLE_PROVIDER(gtk_css_provider_new()); + const char css[] = + "*{background-image:-gtk-gradient(linear,0 0,0 1," + "from(rgba(%u,%u,%u,%g)),to(rgba(%u,%u,%u,%g)))}"; + char buf[sizeof(css) + 20]; + const unsigned r = m_backgroundColour.Red(); + const unsigned g = m_backgroundColour.Green(); + const unsigned b = m_backgroundColour.Blue(); + const double a = m_backgroundColour.Alpha() / 255.0; + g_snprintf(buf, sizeof(buf), css, r, g, b, a, r, g, b, a); + gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(m_styleProvider), buf, -1, NULL); + } + DoApplyWidgetStyle(NULL); +#else + GtkRcStyle* style = GTKCreateWidgetStyle(); DoApplyWidgetStyle(style); g_object_unref(style); - } #endif + } // Style change may affect GTK+'s size calculation: InvalidateBestSize(); @@ -4130,6 +4145,25 @@ void wxWindowGTK::GTKApplyStyle(GtkWidget* widget, GtkRcStyle* WXUNUSED_IN_GTK3( gtk_widget_override_font(widget, pfd); gtk_widget_override_color(widget, GTK_STATE_FLAG_NORMAL, m_foregroundColour); gtk_widget_override_background_color(widget, GTK_STATE_FLAG_NORMAL, m_backgroundColour); + + // setting background color has no effect with some themes when the widget style + // has a "background-image" property, so we need to override that as well + + GtkStyleContext* context = gtk_widget_get_style_context(widget); + if (m_styleProvider) + gtk_style_context_remove_provider(context, m_styleProvider); + cairo_pattern_t* pattern = NULL; + if (m_backgroundColour.IsOk()) + { + gtk_style_context_get(context, + GTK_STATE_FLAG_NORMAL, "background-image", &pattern, NULL); + } + if (pattern) + { + cairo_pattern_destroy(pattern); + gtk_style_context_add_provider(context, + m_styleProvider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } #else gtk_widget_modify_style(widget, style); #endif