GTK:
+- Implement support for wxBG_STYLE_TRANSPARENT (Armel Asselin).
- Fix wxNotebook best size calculation.
MSW:
virtual bool SetFont( const wxFont &font );
virtual bool SetBackgroundStyle(wxBackgroundStyle style) ;
+ virtual bool IsTransparentBackgroundSupported(wxString* reason = NULL) const;
virtual int GetCharHeight() const;
virtual int GetCharWidth() const;
bool DoScrollByUnits(ScrollDir dir, ScrollUnit unit, int units);
virtual void AddChildGTK(wxWindowGTK* child);
-
DECLARE_DYNAMIC_CLASS(wxWindowGTK)
wxDECLARE_NO_COPY_CLASS(wxWindowGTK);
};
wxColour GetForegroundColour() const;
// Set/get the background style.
- virtual bool SetBackgroundStyle(wxBackgroundStyle style)
- { m_backgroundStyle = style; return true; }
+ virtual bool SetBackgroundStyle(wxBackgroundStyle style);
wxBackgroundStyle GetBackgroundStyle() const
{ return m_backgroundStyle; }
// from a parent window
virtual bool HasTransparentBackground() { return false; }
+ // Returns true if background transparency is supported for this
+ // window, i.e. if calling SetBackgroundStyle(wxBG_STYLE_TRANSPARENT)
+ // has a chance of succeeding. If reason argument is non-NULL, returns a
+ // user-readable explanation of why it isn't supported if the return
+ // value is false.
+ virtual bool IsTransparentBackgroundSupported(wxString* reason = NULL) const;
+
// set/retrieve the font for the window (SetFont() returns true if the
// font really changed)
virtual bool SetFont(const wxFont& font) = 0;
/* this style is deprecated and doesn't do anything, don't use */
wxBG_STYLE_COLOUR,
- /* this is a Mac-only style, don't use in portable code */
- wxBG_STYLE_TRANSPARENT,
+ /**
+ Indicates that the window background is not erased, letting the parent
+ window show through.
+ Currently this style is only supported in wxOSX and wxGTK with
+ compositing available, see wxWindow::IsTransparentBackgroundSupported().
+ */
+ wxBG_STYLE_TRANSPARENT,
};
@c wxBG_STYLE_PAINT is a simpler and more efficient solution to the same
problem.
+
+ Under wxGTK and wxOSX, you can use ::wxBG_STYLE_TRANSPARENT to obtain
+ full transparency of the window background. Note that wxGTK supports
+ this only since GTK 2.12 with a compositing manager enabled, call
+ IsTransparentBackgroundSupported() to check whether this is the case.
+
+ Also, on order for @c SetBackgroundStyle(wxBG_STYLE_TRANSPARENT) to
+ work, it must be called before Create(). If you're using your own
+ wxWindow-derived class you should write your code in the following way:
+ @code
+ class MyWidget : public wxWindow
+ {
+ public:
+ MyWidget(wxWindow* parent, ...)
+ : wxWindow() // Use default ctor here!
+ {
+ // Do this first:
+ SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+
+ // And really create the window afterwards:
+ Create(parent, ...);
+ }
+ };
+ @endcode
+
@see SetBackgroundColour(), GetForegroundColour(),
- SetTransparent()
+ SetTransparent(), IsTransparentBackgroundSupported()
*/
virtual bool SetBackgroundStyle(wxBackgroundStyle style);
+ /**
+ Checks whether using transparent background might work.
+
+ If this function returns @false, calling SetBackgroundStyle() with
+ ::wxBG_STYLE_TRANSPARENT is not going to work. If it returns @true,
+ setting transparent style should normally succeed.
+
+ Notice that this function would typically be called on the parent of a
+ window you want to set transparent background style for as the window
+ for which this method is called must be fully created.
+
+ @param reason
+ If not @NULL, a reason message is provided if transparency is not
+ supported.
+
+ @return @true if background transparency is supported.
+
+ @since 2.9.4
+ */
+ virtual bool IsTransparentBackgroundSupported(wxString *reason = NULL) const;
+
/**
Sets the font for this window. This function should not be called for the
parent window if you don't want its font to be inherited by its children,
#include "wx/custombgwin.h"
#include "wx/dcbuffer.h"
+#include "wx/artprov.h"
// ----------------------------------------------------------------------------
// resources
ControlWithTransparency(wxWindow *parent,
const wxPoint& pos,
const wxSize& size)
- : wxWindow(parent, wxID_ANY, pos, size, wxBORDER_NONE)
{
+ wxString reason;
+ if ( parent->IsTransparentBackgroundSupported(&reason) )
+ {
+ SetBackgroundStyle (wxBG_STYLE_TRANSPARENT);
+ m_message = "This is custom control with transparency";
+ }
+ else
+ {
+ m_message = "Transparency not supported, check tooltip.";
+ }
+
+ Create (parent, wxID_ANY, pos, size, wxBORDER_NONE);
Connect(wxEVT_PAINT,
wxPaintEventHandler(ControlWithTransparency::OnPaint));
- }
- virtual bool HasTransparentBackground() { return true; }
+ if ( !reason.empty() )
+ {
+ // This can be only done now, after creating the window.
+ SetToolTip(reason);
+ }
+ }
private:
void OnPaint( wxPaintEvent& WXUNUSED(event) )
dc.SetTextForeground(*wxBLUE);
dc.SetBackgroundMode(wxTRANSPARENT);
- dc.DrawText("This is custom control with transparency", 0, 2);
+ dc.DrawText(m_message, 0, 2);
+
+ // Draw some bitmap/icon to ensure transparent bitmaps are indeed
+ // transparent on transparent windows
+ wxBitmap bmp(wxArtProvider::GetBitmap(wxART_WARNING, wxART_MENU));
+ wxIcon icon(wxArtProvider::GetIcon(wxART_GOTO_LAST, wxART_MENU));
+ dc.DrawBitmap (bmp, GetSize().x - 1 - bmp.GetWidth(), 2);
+ dc.DrawIcon(icon, GetSize().x - 1 - bmp.GetWidth()-icon.GetWidth(), 2);
}
+
+ wxString m_message;
};
// ----------------------------------------------------------------------------
"right one drawn directly",
wxPoint(150, 20));
- new ControlWithTransparency(this, wxPoint(65, 125), wxSize(300, 22));
+ new ControlWithTransparency(this, wxPoint(65, 125), wxSize(350, 22));
SetFocusIgnoringChildren();
SetBackgroundColour(*wxCYAN);
return m_foregroundColour;
}
+bool wxWindowBase::SetBackgroundStyle(wxBackgroundStyle style)
+{
+ // The checks below shouldn't be triggered if we're not really changing the
+ // style.
+ if ( style == m_backgroundStyle )
+ return true;
+
+ // Transparent background style can be only set before creation because of
+ // wxGTK limitation.
+ wxCHECK_MSG( (style != wxBG_STYLE_TRANSPARENT) || !GetHandle(),
+ false,
+ "wxBG_STYLE_TRANSPARENT style can only be set before "
+ "Create()-ing the window." );
+
+ // And once it is set, wxBG_STYLE_TRANSPARENT can't be unset.
+ wxCHECK_MSG( (m_backgroundStyle != wxBG_STYLE_TRANSPARENT) ||
+ (style == wxBG_STYLE_TRANSPARENT),
+ false,
+ "wxBG_STYLE_TRANSPARENT can't be unset once it was set." );
+
+ m_backgroundStyle = style;
+
+ return true;
+}
+
+bool wxWindowBase::IsTransparentBackgroundSupported(wxString *reason) const
+{
+ if ( reason )
+ *reason = _("This platform does not support background transparency.");
+
+ return false;
+}
+
bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
{
if ( colour == m_backgroundColour )
wxTEXT_SCREEN,
wxBG_SCREEN,
wxPEN_SCREEN,
- wxBRUSH_SCREEN
+ wxBRUSH_SCREEN,
+ wxTEXT_COLOUR_ALPHA,
+ wxBG_COLOUR_ALPHA,
+ wxPEN_COLOUR_ALPHA,
+ wxBRUSH_COLOUR_ALPHA
};
struct wxGC
m_textGC = wxGetPoolGC( m_gdkwindow, wxTEXT_SCREEN );
m_bgGC = wxGetPoolGC( m_gdkwindow, wxBG_SCREEN );
}
+ else if (m_cmap == gdk_screen_get_rgba_colormap(gdk_colormap_get_screen(m_cmap)))
+ {
+ m_penGC = wxGetPoolGC( m_gdkwindow, wxPEN_COLOUR_ALPHA );
+ m_brushGC = wxGetPoolGC( m_gdkwindow, wxBRUSH_COLOUR_ALPHA );
+ m_textGC = wxGetPoolGC( m_gdkwindow, wxTEXT_COLOUR_ALPHA );
+ m_bgGC = wxGetPoolGC( m_gdkwindow, wxBG_COLOUR_ALPHA );
+ }
else
{
m_penGC = wxGetPoolGC( m_gdkwindow, wxPEN_COLOUR );
#include <gdk/gdkkeysyms-compat.h>
#endif
+#if wxUSE_GRAPHICS_CONTEXT
+#include "wx/graphics.h"
+#include "wx/scopedptr.h"
+#endif // wxUSE_GRAPHICS_CONTEXT
+
+// gdk_window_set_composited() is only supported since 2.12
+#define wxGTK_VERSION_REQUIRED_FOR_COMPOSITING 2,12,0
+#define wxGTK_HAS_COMPOSITING_SUPPORT GTK_CHECK_VERSION(2,12,0)
+
//-----------------------------------------------------------------------------
// documentation on internals
//-----------------------------------------------------------------------------
);
}
+ // Use composited window if background is transparent, if supported.
+ if (m_backgroundStyle == wxBG_STYLE_TRANSPARENT)
+ {
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ if (IsTransparentBackgroundSupported())
+ {
+ GdkWindow* const window = GTKGetDrawingWindow();
+ if (window)
+ gdk_window_set_composited(window, true);
+ }
+ else
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+ {
+ // We revert to erase mode if transparency is not supported
+ m_backgroundStyle = wxBG_STYLE_ERASE;
+ }
+ }
+
+
// We cannot set colours and fonts before the widget
// been realized, so we do this directly after realization
// or otherwise in idle time
{
wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ // Set RGBA visual as soon as possible to minimize the possibility that
+ // somebody uses the wrong one.
+ if ( m_backgroundStyle == wxBG_STYLE_TRANSPARENT &&
+ IsTransparentBackgroundSupported() )
+ {
+ GdkScreen *screen = gtk_widget_get_screen (m_widget);
+
+ GdkColormap *rgba_colormap = gdk_screen_get_rgba_colormap (screen);
+
+ if (rgba_colormap)
+ gtk_widget_set_colormap(m_widget, rgba_colormap);
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+
if (m_wxwindow)
{
if (!m_noExpose)
switch ( GetBackgroundStyle() )
{
+#if wxUSE_GRAPHICS_CONTEXT
+ case wxBG_STYLE_TRANSPARENT:
+ {
+ // Set a transparent background, so that overlaying in parent
+ // might indeed let see through where this child did not
+ // explicitly paint.
+ // NB: it works also for top level windows (but this is the
+ // windows manager which then does the compositing job)
+ wxScopedPtr<wxGraphicsContext> gc (wxGraphicsContext::Create( this ));
+ cairo_t *cairo_context = (cairo_t *)gc->GetNativeContext();
+
+ gc->Clip (m_nativeUpdateRegion);
+ cairo_set_operator (cairo_context, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cairo_context);
+ break;
+ }
+#endif // wxUSE_GRAPHICS_CONTEXT
+
case wxBG_STYLE_ERASE:
{
wxWindowDC dc( (wxWindow*)this );
paint_event.SetEventObject( this );
HandleWindowEvent( paint_event );
+#if wxUSE_GRAPHICS_CONTEXT
+ { // now composite children which need it
+ wxScopedPtr<wxGraphicsContext> gc (wxGraphicsContext::Create( this ));
+ cairo_t *cairo_context = (cairo_t *)gc->GetNativeContext();
+
+ // Overlay all our composite children on top of the painted area
+ wxWindowList::compatibility_iterator node;
+ for ( node = m_children.GetFirst(); node ; node = node->GetNext() )
+ {
+ wxWindow *compositeChild = node->GetData();
+ if (compositeChild->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT)
+ {
+ GtkWidget *child = compositeChild->m_wxwindow;
+
+ // The source data is the (composited) child
+ gdk_cairo_set_source_pixmap (cairo_context, child->window,
+ child->allocation.x,
+ child->allocation.y);
+
+ // Draw no more than our expose event intersects our child
+ gc->Clip (m_nativeUpdateRegion);
+ gc->Clip (child->allocation.x, child->allocation.y,
+ child->allocation.width, child->allocation.height);
+
+ cairo_set_operator (cairo_context, CAIRO_OPERATOR_OVER);
+ cairo_paint (cairo_context);
+
+ gc->ResetClip ();
+ }
+ }
+ }
+#endif // wxUSE_GRAPHICS_CONTEXT
+
m_clipPaintRegion = false;
m_updateRegion.Clear();
bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
{
- wxWindowBase::SetBackgroundStyle(style);
+ if (!wxWindowBase::SetBackgroundStyle(style))
+ return false;
- if ( style == wxBG_STYLE_PAINT )
+ GdkWindow *window;
+ if ( m_wxwindow )
{
- GdkWindow *window;
- if ( m_wxwindow )
- {
- window = GTKGetDrawingWindow();
- }
- else
- {
- GtkWidget * const w = GetConnectWidget();
- window = w ? gtk_widget_get_window(w) : NULL;
- }
+ window = GTKGetDrawingWindow();
+ }
+ else
+ {
+ GtkWidget * const w = GetConnectWidget();
+ window = w ? gtk_widget_get_window(w) : NULL;
+ }
+
+ bool wantNoBackPixmap = style == wxBG_STYLE_PAINT || style == wxBG_STYLE_TRANSPARENT;
+ if ( wantNoBackPixmap )
+ {
if (window)
{
// Make sure GDK/X11 doesn't refresh the window
return true;
}
+bool wxWindowGTK::IsTransparentBackgroundSupported(wxString* reason) const
+{
+#if wxGTK_HAS_COMPOSITING_SUPPORT && wxUSE_GRAPHICS_CONTEXT
+ if (gtk_check_version(wxGTK_VERSION_REQUIRED_FOR_COMPOSITING) != NULL)
+ {
+ if (reason)
+ {
+ *reason = _("GTK+ installed on this machine is too old to "
+ "support screen compositing, please install "
+ "GTK+ 2.12 or later.");
+ }
+
+ return false;
+ }
+
+ // NB: We don't check here if the particular kind of widget supports
+ // transparency, we check only if it would be possible for a generic window
+
+ wxCHECK_MSG ( m_widget, false, "Window must be created first" );
+
+ if (!gdk_screen_is_composited(gtk_widget_get_screen(m_widget)))
+ {
+ if (reason)
+ {
+ *reason = _("Compositing not supported by this system, "
+ "please enable it in your Window Manager.");
+ }
+
+ return false;
+ }
+
+ return true;
+#elif !wxGTK_HAS_COMPOSITING_SUPPORT
+ if (reason)
+ {
+ *reason = _("This program was compiled with a too old version of GTK+, "
+ "please rebuild with GTK+ 2.12 or newer.");
+ }
+#elif !wxUSE_GRAPHICS_CONTEXT
+ if (reason)
+ {
+ *reason = _("wxUSE_GRAPHICS_CONTEXT required for compositing window, "
+ "please rebuild wxWidgets with support for it.");
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT/!wxGTK_HAS_COMPOSITING_SUPPORT
+
+ return false;
+}
+
// ----------------------------------------------------------------------------
// Pop-up menu stuff
// ----------------------------------------------------------------------------