]> git.saurik.com Git - wxWidgets.git/commitdiff
introduce wxBG_STYLE_{ERASE,PAINT} and implement their documented semantics in wxGTK
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 16 Jun 2009 23:04:42 +0000 (23:04 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 16 Jun 2009 23:04:42 +0000 (23:04 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61084 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/dcbuffer.h
include/wx/defs.h
include/wx/window.h
interface/wx/defs.h
interface/wx/window.h
samples/erase/erase.cpp
src/common/wincmn.cpp
src/gtk/window.cpp

index 3fc631a4de2b13d58a07169c09ad36b3c89e7d62..b0be3a6447a7e18d05dfbcacf10df1cd0d363d9e 100644 (file)
@@ -124,6 +124,10 @@ Changes in behaviour not resulting in compilation errors, please read this!
 
 - wxLoadFileSelector() now allows the user to select existing files only.
 
+- Erase background events are now not generated at all when background style is
+  changed. See the updated wxWindow::SetBackgroundStyle() description in the
+  manual for more details.
+
 
 Changes in behaviour which may result in compilation errors
 -----------------------------------------------------------
index 7b54ecd7e8229fd7d99ae8389d6020899652c5da..383dfcb3aed23df164ea6c4ec4bfb327f79fb576 100644 (file)
@@ -219,8 +219,8 @@ public:
     wxAutoBufferedPaintDC(wxWindow* win)
         : wxAutoBufferedPaintDCBase(win)
     {
-        wxASSERT_MSG( win->GetBackgroundStyle() == wxBG_STYLE_CUSTOM,
-            "You need to call SetBackgroundStyle(wxBG_STYLE_CUSTOM) in ctor, "
+        wxASSERT_MSG( win->GetBackgroundStyle() == wxBG_STYLE_PAINT,
+            "You need to call SetBackgroundStyle(wxBG_STYLE_PAINT) in ctor, "
             "and also, if needed, paint the background in wxEVT_PAINT handler."
         );
     }
index 963a4b3d13ff2b670a4c70f08c57de5816492c68..75d36d81b3f452db39d7deb118683cef0ac6bf01 100644 (file)
@@ -1836,13 +1836,32 @@ enum wxBorder
 /*
  * Background styles. See wxWindow::SetBackgroundStyle
  */
-
 enum wxBackgroundStyle
 {
-  wxBG_STYLE_SYSTEM,
-  wxBG_STYLE_COLOUR,
-  wxBG_STYLE_CUSTOM,
-  wxBG_STYLE_TRANSPARENT
+    // background is erased in the EVT_ERASE_BACKGROUND handler or using the
+    // system default background if no such handler is defined (this is the
+    // default style)
+    wxBG_STYLE_ERASE,
+
+    // background is erased by the system, no EVT_ERASE_BACKGROUND event is
+    // generated at all
+    wxBG_STYLE_SYSTEM,
+
+    // background is erased in EVT_PAINT handler and not erased at all before
+    // it, this should be used if the paint handler paints over the entire
+    // window to avoid flicker
+    wxBG_STYLE_PAINT,
+
+
+    // this is a Mac-only style, don't use in portable code
+    wxBG_STYLE_TRANSPARENT,
+
+    // this style is deprecated and doesn't do anything, don't use
+    wxBG_STYLE_COLOUR,
+
+    // this style is deprecated and is synonymous with wxBG_STYLE_PAINT, use
+    // the new name
+    wxBG_STYLE_CUSTOM = wxBG_STYLE_PAINT
 };
 
 /*
index 31dbf9587c8ce1f713e23beb157567ab45729756..913cd7d0aad0fdfae1295fa84a31ddfdc96b9c38 100644 (file)
@@ -1032,9 +1032,10 @@ public:
     wxColour GetForegroundColour() const;
 
         // Set/get the background style.
-        // Pass one of wxBG_STYLE_SYSTEM, wxBG_STYLE_COLOUR, wxBG_STYLE_CUSTOM
-    virtual bool SetBackgroundStyle(wxBackgroundStyle style) { m_backgroundStyle = style; return true; }
-    virtual wxBackgroundStyle GetBackgroundStyle() const { return m_backgroundStyle; }
+    virtual bool SetBackgroundStyle(wxBackgroundStyle style)
+        { m_backgroundStyle = style; return true; }
+    wxBackgroundStyle GetBackgroundStyle() const
+        { return m_backgroundStyle; }
 
         // returns true if the control has "transparent" areas such as a
         // wxStaticText and wxCheckBox and the background should be adapted
index 2b2afd8f168349a6858fd516eb6b8284452db61f..21948b99ffee037f86c2a47184461e2f33bddce6 100644 (file)
@@ -136,28 +136,54 @@ enum wxBorder
 
 
 /**
-    Background styles. See wxWindow::SetBackgroundStyle().
+    Background styles.
+
+    @see wxWindow::SetBackgroundStyle()
 */
 enum wxBackgroundStyle
 {
-    /// Use the default background, as determined by
-    /// the system or the current theme.
+    /**
+        Default background style value indicating that the background may be
+        erased in the user-defined EVT_ERASE_BACKGROUND handler.
+
+        If no such handler is defined (or if it skips the event), the effect of
+        this style is the same as wxBG_STYLE_SYSTEM. If an empty handler (@em
+        not skipping the event) is defined, the effect is the same as
+        wxBG_STYLE_PAINT, i.e. the background is not erased at all until
+        EVT_PAINT handler is executed.
+
+        This is the only background style value for which erase background
+        events are generated at all.
+     */
+    wxBG_STYLE_ERASE,
+
+    /**
+        Use the default background, as determined by the system or the current
+        theme.
+
+        If the window has been assigned a non-default background colour, it
+        will be used for erasing its background. Otherwise the default
+        background (which might be a gradient or a pattern) will be used.
+
+        EVT_ERASE_BACKGROUND event will not be generated at all for windows
+        with this style.
+     */
     wxBG_STYLE_SYSTEM,
 
-    /// Use a solid colour for the background, this style is set automatically if you call
-    /// SetBackgroundColour() so you only need to set it explicitly if you had
-    /// changed the background style to something else before.
-    wxBG_STYLE_COLOUR,
+    /**
+        Indicates that the background is only erased in the user-defined
+        EVT_PAINT handler.
 
-    /// Don't draw the background at all, it's supposed that it is drawn by
-    /// the user-defined erase background event handler.
-    /// This style should be used to avoid flicker when the background is entirely
-    /// custom-drawn.
-    wxBG_STYLE_CUSTOM,
+        Using this style avoids flicker which would result from redrawing the
+        background twice if the EVT_PAINT handler entirely overwrites it. It
+        must not be used however if the paint handler leaves any parts of the
+        window unpainted as their contents is then undetermined. Only use it if
+        you repaint the whole window in your handler.
 
-    /// The background is (partially) transparent,this style is automatically set if you call
-    /// SetTransparent() which is used to set the transparency level.
-    wxBG_STYLE_TRANSPARENT
+        EVT_ERASE_BACKGROUND event will not be generated at all for windows
+        with this style.
+     */
+    wxBG_STYLE_PAINT
 };
 
 
index 962d193a0c7b441a092e4d1df3934e02c2f0f7fc..73b300c789439cd201f7fe5250148a261a6bb9d6 100644 (file)
@@ -1418,12 +1418,12 @@ public:
 
     /**
         Returns the background style of the window.
-        The background style can be one of the wxBackgroundStyle.
 
         @see SetBackgroundColour(), GetForegroundColour(),
              SetBackgroundStyle(), SetTransparent()
     */
     virtual wxBackgroundStyle GetBackgroundStyle() const;
+
     /**
         Returns the character height for this window.
     */
@@ -1583,8 +1583,28 @@ public:
     virtual bool SetBackgroundColour(const wxColour& colour);
 
     /**
-        Sets the background style of the window. see GetBackgroundStyle() for
-        the description of the possible style values.
+        Sets the background style of the window.
+
+        The default background style is wxBG_STYLE_ERASE which indicates that
+        the window background may be erased in EVT_ERASE_BACKGROUND handler.
+        This is a safe compatibility default however you may want to change it
+        to wxBG_STYLE_SYSTEM if you don't define any erase background event
+        handlers at all to avoid unnecessary generation of erase background
+        events and always let system erase the background. And you should
+        change the background style to wxBG_STYLE_PAINT if you define an
+        EVT_PAINT handler which completely overwrites the window background as
+        in this case erasing it previously, either in EVT_ERASE_BACKGROUND
+        handler or in the system default handler, would result in flicker as
+        the background pixels will be repainted twice every time the window is
+        redrawn. Do ensure that the background is entirely erased by your
+        EVT_PAINT handler in this case however as otherwise garbage may be left
+        on screen.
+
+        Notice that in previous versions of wxWidgets a common way to work
+        around the above mentioned flickering problem was to define an empty
+        EVT_ERASE_BACKGROUND handler. Setting background style to
+        wxBG_STYLE_PAINT is a simpler and more efficient solution to the same
+        problem.
 
         @see SetBackgroundColour(), GetForegroundColour(),
              SetTransparent()
index 94dd570ec49a50f0f76025118c2e69bab97ef71b..cc6ca65d4fe51acd5cf9b4552bdc408f5cef0265 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        erase.cpp
+// Name:        samples/erase/erase.cpp
 // Purpose:     Erase wxWidgets sample
-// Author:      Robert Roebling
-// Modified by:
+// Author:      Robert Roebling, Vadim Zeitlin
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Robert Roebling
+// Copyright:   (c) 1998 Robert Roebling
+//              (c) 2009 Vadim Zeitlin
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
@@ -30,6 +30,8 @@
     #include "wx/wx.h"
 #endif
 
+#include "wx/dcbuffer.h"
+
 // ----------------------------------------------------------------------------
 // resources
 // ----------------------------------------------------------------------------
@@ -52,10 +54,10 @@ public:
 class MyCanvas : public wxScrolledWindow
 {
 public:
-    MyCanvas( wxFrame *parent );
+    MyCanvas(wxFrame *parent);
 
     void UseBuffer(bool useBuffer) { m_useBuffer = useBuffer; Refresh(); }
-    void EraseBg(bool eraseBg) { m_eraseBg = eraseBg; Refresh(); }
+    bool UsesBuffer() const { return m_useBuffer; }
 
 private:
     void OnPaint( wxPaintEvent &event );
@@ -71,9 +73,6 @@ private:
     // use wxMemoryDC in OnPaint()?
     bool m_useBuffer;
 
-    // paint custom background in OnEraseBackground()?
-    bool m_eraseBg;
-
 
     DECLARE_EVENT_TABLE()
 };
@@ -83,12 +82,23 @@ class MyFrame : public wxFrame
 public:
     MyFrame();
 
+private:
     void OnUseBuffer(wxCommandEvent& event);
-    void OnEraseBg(wxCommandEvent& event);
+    void OnChangeBgStyle(wxCommandEvent& event);
     void OnQuit(wxCommandEvent& event);
     void OnAbout(wxCommandEvent& event);
 
-private:
+    // we can only use double-buffering with wxBG_STYLE_PAINT
+    void OnUpdateUIUseBuffer(wxUpdateUIEvent& event)
+    {
+        event.Enable( m_canvas->GetBackgroundStyle() == wxBG_STYLE_PAINT );
+    }
+
+    void OnUpdateUIChangeBgStyle(wxUpdateUIEvent& event)
+    {
+        event.Enable( !m_canvas->UsesBuffer() );
+    }
+
     MyCanvas *m_canvas;
 
     DECLARE_EVENT_TABLE()
@@ -103,7 +113,9 @@ enum
 {
     // menu items
     Erase_Menu_UseBuffer = 100,
-    Erase_Menu_EraseBg,
+    Erase_Menu_BgStyleErase,
+    Erase_Menu_BgStyleSystem,
+    Erase_Menu_BgStylePaint,
     Erase_Menu_Exit = wxID_EXIT,
     Erase_Menu_About = wxID_ABOUT
 };
@@ -133,40 +145,46 @@ bool MyApp::OnInit()
 
 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(Erase_Menu_UseBuffer,  MyFrame::OnUseBuffer)
-    EVT_MENU(Erase_Menu_EraseBg,  MyFrame::OnEraseBg)
+    EVT_MENU_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint,
+                   MyFrame::OnChangeBgStyle)
+
     EVT_MENU(Erase_Menu_Exit,  MyFrame::OnQuit)
     EVT_MENU(Erase_Menu_About, MyFrame::OnAbout)
+
+    EVT_UPDATE_UI(Erase_Menu_UseBuffer, MyFrame::OnUpdateUIUseBuffer)
+    EVT_UPDATE_UI_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint,
+                        MyFrame::OnUpdateUIChangeBgStyle)
 END_EVENT_TABLE()
 
 // frame constructor
 MyFrame::MyFrame()
-       : wxFrame(NULL, wxID_ANY, _T("Erase sample"),
+       : wxFrame(NULL, wxID_ANY, "Erase sample",
                  wxPoint(50, 50), wxSize(450, 340))
 {
     SetIcon(wxICON(mondrian));
 
-    wxMenu *menuFile = new wxMenu(_T(""), wxMENU_TEAROFF);
-    menuFile->AppendCheckItem(Erase_Menu_UseBuffer, _T("&Use memory DC\tCtrl-M"));
-    menuFile->AppendCheckItem(Erase_Menu_EraseBg, _T("Custom &background\tCtrl-B"));
+    wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF);
+    menuFile->AppendCheckItem(Erase_Menu_UseBuffer, "&Use memory DC\tCtrl-M");
+    menuFile->AppendSeparator();
+    menuFile->AppendRadioItem(Erase_Menu_BgStyleErase,
+                              "Use wxBG_STYLE_&ERASE\tCtrl-E");
+    menuFile->AppendRadioItem(Erase_Menu_BgStyleSystem,
+                              "Use wxBG_STYLE_&SYSTEM\tCtrl-S");
+    menuFile->AppendRadioItem(Erase_Menu_BgStylePaint,
+                              "Use wxBG_STYLE_&PAINT\tCtrl-P");
     menuFile->AppendSeparator();
-    menuFile->Append(Erase_Menu_Exit, _T("E&xit\tAlt-X"), _T("Quit this program"));
+    menuFile->Append(Erase_Menu_Exit, "E&xit\tAlt-X", "Quit this program");
 
 
     wxMenu *helpMenu = new wxMenu;
-    helpMenu->Append(Erase_Menu_About, _T("&About...\tCtrl-A"), _T("Show about dialog"));
+    helpMenu->Append(Erase_Menu_About, "&About...\tCtrl-A", "Show about dialog");
 
     wxMenuBar *menuBar = new wxMenuBar();
-    menuBar->Append(menuFile, _T("&File"));
-    menuBar->Append(helpMenu, _T("&Help"));
+    menuBar->Append(menuFile, "&File");
+    menuBar->Append(helpMenu, "&Help");
 
     SetMenuBar(menuBar);
 
-#if wxUSE_STATUSBAR
-    // create a status bar just for fun (by default with 1 pane only)
-    CreateStatusBar(2);
-    SetStatusText(_T("Welcome to wxWidgets erase sample!"));
-#endif // wxUSE_STATUSBAR
-
     m_canvas = new MyCanvas( this );
 }
 
@@ -176,9 +194,12 @@ void MyFrame::OnUseBuffer(wxCommandEvent& event)
     m_canvas->UseBuffer(event.IsChecked());
 }
 
-void MyFrame::OnEraseBg(wxCommandEvent& event)
+void MyFrame::OnChangeBgStyle(wxCommandEvent& event)
 {
-    m_canvas->EraseBg(event.IsChecked());
+    int style = wxBG_STYLE_ERASE + event.GetId() - Erase_Menu_BgStyleErase;
+    m_canvas->SetBackgroundStyle(static_cast<wxBackgroundStyle>(style));
+
+    m_canvas->Refresh();
 }
 
 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
@@ -188,22 +209,29 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
 
 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 {
-    wxMessageBox(_T("This sample shows how you can draw custom background."),
-                 _T("About Erase Sample"), wxOK | wxICON_INFORMATION, this);
+    wxMessageBox
+    (
+        "This sample shows differences between different background styles "
+        "and how you may draw custom background.\n"
+        "\n"
+        "(c) 1998 Robert Roebling\n"
+        "(c) 2009 Vadim Zeitlin\n",
+        "About Erase Sample",
+        wxOK | wxICON_INFORMATION,
+        this
+    );
 }
 
 
 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
-    EVT_PAINT(  MyCanvas::OnPaint)
-    EVT_CHAR(  MyCanvas::OnChar)
-    EVT_ERASE_BACKGROUND(  MyCanvas::OnEraseBackground)
+    EVT_PAINT(MyCanvas::OnPaint)
+    EVT_CHAR(MyCanvas::OnChar)
+    EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackground)
 END_EVENT_TABLE()
 
-MyCanvas::MyCanvas( wxFrame *parent )
-        : wxScrolledWindow( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
-                            wxScrolledWindowStyle | wxSUNKEN_BORDER )
+MyCanvas::MyCanvas(wxFrame *parent)
+        : wxScrolledWindow(parent, wxID_ANY)
 {
-    m_eraseBg =
     m_useBuffer = false;
 
     SetScrollbars( 10, 10, 40, 100, 0, 0 );
@@ -213,6 +241,7 @@ MyCanvas::MyCanvas( wxFrame *parent )
     new wxStaticBitmap( this, wxID_ANY, m_bitmap, wxPoint(80,20) );
 
     SetFocusIgnoringChildren();
+    SetBackgroundColour(*wxBLUE);
 }
 
 void MyCanvas::OnChar( wxKeyEvent &event )
@@ -241,99 +270,47 @@ void MyCanvas::OnChar( wxKeyEvent &event )
 void MyCanvas::DoPaint(wxDC& dc)
 {
     dc.SetBrush( *wxBLACK_BRUSH );
-    dc.DrawRectangle( 10,10,200,50 );
+    dc.DrawRectangle( 10,10,60,50 );
 
-    dc.DrawBitmap( m_bitmap, 10, 20, true );
+    dc.DrawBitmap( m_bitmap, 20, 20, true );
 
-    dc.SetTextForeground(*wxBLUE);
-    dc.DrawText(_T("This text is drawn from OnPaint"), 65, 65);
+    dc.SetTextForeground(*wxWHITE);
+    dc.DrawText("This text is drawn from OnPaint", 65, 65);
 
     wxString tmp;
-    tmp.Printf( _T("Hit any key to display more text: %s"), m_text.c_str() );
+    tmp.Printf("Hit any key to display more text: %s", m_text);
+
     int w,h;
     dc.GetTextExtent( tmp, &w, &h );
-    dc.SetBrush( *wxWHITE_BRUSH );
     dc.DrawRectangle( 65, 85, w, h );
     dc.DrawText( tmp, 65, 85 );
-
-#if 0
-    wxRegionIterator upd( GetUpdateRegion() );
-    while (upd)
-    {
-        wxLogDebug( _T("Paint: %d %d %d %d"), upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
-        upd ++;
-    }
-#endif
-
-#if 0
-    wxSize size = GetSize();
-    wxSize client_size = GetClientSize();
-    wxLogDebug( _T("size %d %d client_size %d %d"), size.x, size.y, client_size.x, client_size.y );
-#endif
-
-#if 0
-    int i;
-    dc.SetPen( *wxWHITE_PEN );
-    for (i = 0; i < 20; i += 2)
-       dc.DrawLine( i,i, i+100,i );
-
-    dc.SetPen( *wxWHITE_PEN );
-    for (i = 200; i < 220; i += 2)
-       dc.DrawLine( i-200,i, i-100,i );
-
-    wxRegion region( 110, 110, 80, 80 );
-    wxRegion hole( 130, 130, 40, 1 );
-    region.Intersect( hole );
-    dc.SetClippingRegion( region );
-
-    dc.SetBrush( *wxRED_BRUSH );
-    dc.DrawRectangle( 100, 100, 200, 200 );
-
-    dc.DestroyClippingRegion();
-
-    dc.SetPen( *wxTRANSPARENT_PEN );
-
-    wxRegion strip( 110, 200, 30, 1 );
-    wxRegionIterator it( strip );
-    while (it)
-    {
-        dc.DrawRectangle( it.GetX(), it.GetY(), it.GetWidth(), it.GetHeight() );
-        it ++;
-    }
-#endif // 0
 }
 
 void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
-    wxPaintDC dcWin(this);
-    PrepareDC( dcWin );
-
     if ( m_useBuffer )
     {
-        const wxSize size = GetClientSize();
-        wxMemoryDC dc;
-        wxBitmap bmp(size.x, size.y);
-        dc.SelectObject(bmp);
-        dc.Blit(0, 0, size.x, size.y, &dcWin, 0, 0);
-        dc.DrawText(_T("(copy of background)"), 5, 120 );
+        wxAutoBufferedPaintDC dc(this);
+        PrepareDC(dc);
 
         DoPaint(dc);
-
-        dcWin.Blit(0, 0, size.x, size.y, &dc, 0, 0);
     }
     else
     {
-        DoPaint(dcWin);
+        wxPaintDC dc(this);
+        PrepareDC(dc);
+
+        DoPaint(dc);
     }
 }
 
 void MyCanvas::OnEraseBackground( wxEraseEvent& event )
 {
-    if ( !m_eraseBg )
-    {
-        event.Skip();
-        return;
-    }
+    wxASSERT_MSG
+    (
+        GetBackgroundStyle() == wxBG_STYLE_ERASE,
+        "shouldn't be called unless background style is \"erase\""
+    );
 
     wxDC& dc = *event.GetDC();
     dc.SetPen(*wxGREEN_PEN);
@@ -355,6 +332,7 @@ void MyCanvas::OnEraseBackground( wxEraseEvent& event )
     }
 
     dc.SetTextForeground(*wxRED);
-    dc.DrawText(_T("This text is drawn from OnEraseBackground"), 60, 160);
+    dc.SetBackgroundMode(wxSOLID);
+    dc.DrawText("This text is drawn from OnEraseBackground", 60, 160);
 }
 
index 8d3fa0af2cfa6ad9782857944ef0b99a0d633cf3..8a0ae4f54fb46a827733fef477503fab425bd295 100644 (file)
@@ -154,7 +154,7 @@ wxWindowBase::wxWindowBase()
     m_exStyle =
     m_windowStyle = 0;
 
-    m_backgroundStyle = wxBG_STYLE_SYSTEM;
+    m_backgroundStyle = wxBG_STYLE_ERASE;
 
 #if wxUSE_CONSTRAINTS
     // no constraints whatsoever
@@ -1333,8 +1333,6 @@ bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
         return false;
 
     m_hasBgCol = colour.IsOk();
-    if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
-        m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
 
     m_inheritBgCol = m_hasBgCol;
     m_backgroundColour = colour;
index b5d5d18bfe1c98c559c6682368c04bdde4a25da7..b72018c1df707b19172bb5d70395e1c4328f8a90 100644 (file)
@@ -2586,8 +2586,8 @@ void wxWindowGTK::OnInternalIdle()
         RealizeTabOrder();
     }
 
-    // Update style if the window was not yet realized
-    // and SetBackgroundStyle(wxBG_STYLE_CUSTOM) was called
+    // Update style if the window was not yet realized when
+    // SetBackgroundStyle() was called
     if (m_needsStyleChange)
     {
         SetBackgroundStyle(GetBackgroundStyle());
@@ -3655,54 +3655,74 @@ void wxWindowGTK::GtkSendPaintEvents()
         }
     }
 
-    if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM))
+    switch ( GetBackgroundStyle() )
     {
-        // find ancestor from which to steal background
-        wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
-        if (!parent)
-            parent = (wxWindow*)this;
-
-        if (GTK_WIDGET_MAPPED(parent->m_widget))
-        {
-            wxRegionIterator upd( m_nativeUpdateRegion );
-            while (upd)
+        case wxBG_STYLE_ERASE:
             {
-                GdkRectangle rect;
-                rect.x = upd.GetX();
-                rect.y = upd.GetY();
-                rect.width = upd.GetWidth();
-                rect.height = upd.GetHeight();
-
-                gtk_paint_flat_box( parent->m_widget->style,
-                            m_wxwindow->window,
-                            (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
-                            GTK_SHADOW_NONE,
-                            &rect,
-                            parent->m_widget,
-                            (char *)"base",
-                            0, 0, -1, -1 );
-
-                ++upd;
+                wxWindowDC dc( (wxWindow*)this );
+                dc.SetDeviceClippingRegion( m_updateRegion );
+
+                // Work around gtk-qt <= 0.60 bug whereby the window colour
+                // remains grey
+                if ( UseBgCol() &&
+                        wxSystemOptions::
+                            GetOptionInt("gtk.window.force-background-colour") )
+                {
+                    dc.SetBackground(GetBackgroundColour());
+                    dc.Clear();
+                }
+
+                wxEraseEvent erase_event( GetId(), &dc );
+                erase_event.SetEventObject( this );
+
+                if ( HandleWindowEvent(erase_event) )
+                {
+                    // background erased, don't do it again
+                    break;
+                }
             }
-        }
-    }
-    else
-    {
-        wxWindowDC dc( (wxWindow*)this );
-        dc.SetDeviceClippingRegion( m_updateRegion );
+            // fall through
 
-        // Work around gtk-qt <= 0.60 bug whereby the window colour
-        // remains grey
-        if (GetBackgroundStyle() == wxBG_STYLE_COLOUR && GetBackgroundColour().Ok() && wxSystemOptions::GetOptionInt(wxT("gtk.window.force-background-colour")) == 1)
-        {
-            dc.SetBackground(wxBrush(GetBackgroundColour()));
-            dc.Clear();
-        }
+        case wxBG_STYLE_SYSTEM:
+            if ( GetThemeEnabled() )
+            {
+                // find ancestor from which to steal background
+                wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
+                if (!parent)
+                    parent = (wxWindow*)this;
+
+                if (GTK_WIDGET_MAPPED(parent->m_widget))
+                {
+                    wxRegionIterator upd( m_nativeUpdateRegion );
+                    while (upd)
+                    {
+                        GdkRectangle rect;
+                        rect.x = upd.GetX();
+                        rect.y = upd.GetY();
+                        rect.width = upd.GetWidth();
+                        rect.height = upd.GetHeight();
+
+                        gtk_paint_flat_box( parent->m_widget->style,
+                                    m_wxwindow->window,
+                                    (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
+                                    GTK_SHADOW_NONE,
+                                    &rect,
+                                    parent->m_widget,
+                                    (char *)"base",
+                                    0, 0, -1, -1 );
+
+                        ++upd;
+                    }
+                }
+            }
+            break;
 
-        wxEraseEvent erase_event( GetId(), &dc );
-        erase_event.SetEventObject( this );
+        case wxBG_STYLE_PAINT:
+            // nothing to do: window will be painted over in EVT_PAINT
+            break;
 
-        HandleWindowEvent(erase_event);
+        default:
+            wxFAIL_MSG( "unsupported background style" );
     }
 
     wxNcPaintEvent nc_paint_event( GetId() );
@@ -3767,8 +3787,7 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
 
     // apply style change (forceStyle=true so that new style is applied
     // even if the bg colour changed from valid to wxNullColour)
-    if (GetBackgroundStyle() != wxBG_STYLE_CUSTOM)
-        GTKApplyWidgetStyle(true);
+    GTKApplyWidgetStyle(true);
 
     return true;
 }
@@ -3896,7 +3915,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 {
     wxWindowBase::SetBackgroundStyle(style);
 
-    if (style == wxBG_STYLE_CUSTOM)
+    if ( style == wxBG_STYLE_PAINT )
     {
         GdkWindow *window;
         if ( m_wxwindow )
@@ -3934,6 +3953,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
         // even if the bg colour changed from valid to wxNullColour):
         GTKApplyWidgetStyle(true);
     }
+
     return true;
 }