1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/nonownedwnd.cpp
3 // Purpose: wxGTK implementation of wxNonOwnedWindow.
4 // Author: Vadim Zeitlin
6 // RCS-ID: $Id: wxhead.cpp,v 1.11 2010-04-22 12:44:51 zeitlin Exp $
7 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
27 #include "wx/nonownedwnd.h"
28 #include "wx/region.h"
31 #include "wx/gtk/private.h"
35 #include "wx/graphics.h"
37 // ----------------------------------------------------------------------------
38 // wxNonOwnedWindowShapeImpl: base class for region and path-based classes.
39 // ----------------------------------------------------------------------------
41 // This class provides behaviour common to both region and path-based
42 // implementations and defines SetShape() method and virtual dtor that can be
43 // called by wxNonOwnedWindow when it's realized leaving just the
44 // implementation of DoSetShape() to the derived classes.
45 class wxNonOwnedWindowShapeImpl
: public wxEvtHandler
48 wxNonOwnedWindowShapeImpl(wxWindow
* win
) : m_win(win
)
52 virtual ~wxNonOwnedWindowShapeImpl() { }
56 if ( m_win
->m_wxwindow
)
57 SetShapeIfNonNull(gtk_widget_get_window(m_win
->m_wxwindow
));
59 return SetShapeIfNonNull(gtk_widget_get_window(m_win
->m_widget
));
62 // Must be overridden to indicate if the data object must stay around or if
63 // it can be deleted once SetShape() was called.
64 virtual bool CanBeDeleted() const = 0;
67 wxWindow
* const m_win
;
70 // SetShape to the given GDK window by calling DoSetShape() if it's non-NULL.
71 bool SetShapeIfNonNull(GdkWindow
* window
)
73 return window
&& DoSetShape(window
);
76 // SetShape the shape to the given GDK window which can be either the window
77 // of m_widget or m_wxwindow of the wxWindow we're used with.
78 virtual bool DoSetShape(GdkWindow
* window
) = 0;
80 wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl
);
83 // Version not using any custom shape.
84 class wxNonOwnedWindowShapeImplNone
: public wxNonOwnedWindowShapeImpl
87 wxNonOwnedWindowShapeImplNone(wxWindow
* win
) :
88 wxNonOwnedWindowShapeImpl(win
)
92 virtual bool CanBeDeleted() const { return true; }
95 virtual bool DoSetShape(GdkWindow
* window
)
97 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
103 // Version using simple wxRegion.
104 class wxNonOwnedWindowShapeImplRegion
: public wxNonOwnedWindowShapeImpl
107 wxNonOwnedWindowShapeImplRegion(wxWindow
* win
, const wxRegion
& region
) :
108 wxNonOwnedWindowShapeImpl(win
),
113 virtual bool CanBeDeleted() const { return true; }
116 virtual bool DoSetShape(GdkWindow
* window
)
118 gdk_window_shape_combine_region(window
, m_region
.GetRegion(), 0, 0);
126 #if wxUSE_GRAPHICS_CONTEXT
128 // Version using more complex wxGraphicsPath.
129 class wxNonOwnedWindowShapeImplPath
: public wxNonOwnedWindowShapeImpl
132 wxNonOwnedWindowShapeImplPath(wxWindow
* win
, const wxGraphicsPath
& path
) :
133 wxNonOwnedWindowShapeImpl(win
),
135 m_mask(CreateShapeBitmap(path
), *wxBLACK
)
141 wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint
),
147 virtual ~wxNonOwnedWindowShapeImplPath()
152 wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint
),
158 // Currently we always return false from here, if drawing the border
159 // becomes optional, we could return true if we don't need to draw it.
160 virtual bool CanBeDeleted() const { return false; }
163 wxBitmap
CreateShapeBitmap(const wxGraphicsPath
& path
)
165 // Draw the path on a bitmap to get the mask we need.
167 // Notice that using monochrome bitmap here doesn't work because of an
168 // apparent wxGraphicsContext bug in wxGTK, so use a bitmap of screen
169 // depth even if this is wasteful.
170 wxBitmap
bmp(m_win
->GetSize());
174 dc
.SetBackground(*wxBLACK
);
177 wxScopedPtr
<wxGraphicsContext
> context(wxGraphicsContext::Create(dc
));
178 context
->SetBrush(*wxWHITE
);
179 context
->FillPath(path
);
184 virtual bool DoSetShape(GdkWindow
*window
)
186 GdkBitmap
* bitmap
= m_mask
.GetBitmap();
190 gdk_window_shape_combine_mask(window
, bitmap
, 0, 0);
195 // Draw a shaped window border.
196 void OnPaint(wxPaintEvent
& event
)
201 wxScopedPtr
<wxGraphicsContext
> context(wxGraphicsContext::Create(dc
));
202 context
->SetPen(wxPen(*wxLIGHT_GREY
, 2));
203 context
->StrokePath(m_path
);
206 wxGraphicsPath m_path
;
210 #endif // wxUSE_GRAPHICS_CONTEXT
212 // ============================================================================
213 // wxNonOwnedWindow implementation
214 // ============================================================================
216 wxNonOwnedWindow::~wxNonOwnedWindow()
221 void wxNonOwnedWindow::GTKHandleRealized()
223 wxNonOwnedWindowBase::GTKHandleRealized();
227 m_shapeImpl
->SetShape();
229 // We can destroy wxNonOwnedWindowShapeImplRegion immediately but need
230 // to keep wxNonOwnedWindowShapeImplPath around as it draws the border
232 if ( m_shapeImpl
->CanBeDeleted() )
240 bool wxNonOwnedWindow::DoClearShape()
244 // Nothing to do, we don't have any custom shape.
248 if ( gtk_widget_get_realized(m_widget
) )
250 // Reset the existing shape immediately.
251 wxNonOwnedWindowShapeImplNone
data(this);
254 //else: just do nothing, deleting m_shapeImpl is enough to ensure that we
255 // don't set the custom shape later when we're realized.
263 bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion
& region
)
265 // In any case get rid of the old data.
269 if ( gtk_widget_get_realized(m_widget
) )
271 // We can avoid an unnecessary heap allocation and just set the shape
273 wxNonOwnedWindowShapeImplRegion
data(this, region
);
274 return data
.SetShape();
276 else // Create an object that will set shape when we're realized.
278 m_shapeImpl
= new wxNonOwnedWindowShapeImplRegion(this, region
);
280 // In general we don't know whether we are going to succeed or not, so
286 #if wxUSE_GRAPHICS_CONTEXT
288 bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath
& path
)
290 // The logic here is simpler than above because we always create
291 // wxNonOwnedWindowShapeImplPath on the heap as we must keep it around,
292 // even if we're already realized
295 m_shapeImpl
= new wxNonOwnedWindowShapeImplPath(this, path
);
297 if ( gtk_widget_get_realized(m_widget
) )
299 return m_shapeImpl
->SetShape();
301 //else: will be done later from GTKHandleRealized().
306 #endif // wxUSE_GRAPHICS_CONTEXT