Added wxNonOwnedWindow::SetShape(wxGraphicsPath).
TODO: Document. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69462 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -39,7 +39,6 @@ class WXDLLIMPEXP_FWD_CORE wxToolBar;
|
|||||||
#define wxFRAME_NO_TASKBAR 0x0002 // No taskbar button (MSW only)
|
#define wxFRAME_NO_TASKBAR 0x0002 // No taskbar button (MSW only)
|
||||||
#define wxFRAME_TOOL_WINDOW 0x0004 // No taskbar button, no system menu
|
#define wxFRAME_TOOL_WINDOW 0x0004 // No taskbar button, no system menu
|
||||||
#define wxFRAME_FLOAT_ON_PARENT 0x0008 // Always above its parent
|
#define wxFRAME_FLOAT_ON_PARENT 0x0008 // Always above its parent
|
||||||
#define wxFRAME_SHAPED 0x0010 // Create a window that is able to be shaped
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxFrame is a top-level window with optional menubar, statusbar and toolbar
|
// wxFrame is a top-level window with optional menubar, statusbar and toolbar
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
#ifndef _WX_GTK_NONOWNEDWND_H_
|
#ifndef _WX_GTK_NONOWNEDWND_H_
|
||||||
#define _WX_GTK_NONOWNEDWND_H_
|
#define _WX_GTK_NONOWNEDWND_H_
|
||||||
|
|
||||||
|
class wxNonOwnedWindowShapeImpl;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxNonOwnedWindow contains code common to wx{Popup,TopLevel}Window in wxGTK.
|
// wxNonOwnedWindow contains code common to wx{Popup,TopLevel}Window in wxGTK.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -18,16 +20,23 @@
|
|||||||
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
|
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxNonOwnedWindow() { }
|
wxNonOwnedWindow() { m_shapeImpl = NULL; }
|
||||||
|
virtual ~wxNonOwnedWindow();
|
||||||
virtual bool SetShape(const wxRegion& region);
|
|
||||||
|
|
||||||
// Overridden to actually set the shape when the window becomes realized.
|
// Overridden to actually set the shape when the window becomes realized.
|
||||||
virtual void GTKHandleRealized();
|
virtual void GTKHandleRealized();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool DoClearShape();
|
||||||
|
virtual bool DoSetRegionShape(const wxRegion& region);
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
virtual bool DoSetPathShape(const wxGraphicsPath& path);
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// If valid, defines the custom shape of the window.
|
// If non-NULL, contains information about custom window shape.
|
||||||
wxRegion m_shape;
|
wxNonOwnedWindowShapeImpl* m_shapeImpl;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindow);
|
wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindow);
|
||||||
};
|
};
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
#ifndef _WX_MSW_NONOWNEDWND_H_
|
#ifndef _WX_MSW_NONOWNEDWND_H_
|
||||||
#define _WX_MSW_NONOWNEDWND_H_
|
#define _WX_MSW_NONOWNEDWND_H_
|
||||||
|
|
||||||
|
class wxNonOwnedWindowShapeImpl;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxNonOwnedWindow
|
// wxNonOwnedWindow
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -18,7 +20,20 @@
|
|||||||
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
|
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool SetShape(const wxRegion& region);
|
wxNonOwnedWindow();
|
||||||
|
virtual ~wxNonOwnedWindow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool DoClearShape();
|
||||||
|
virtual bool DoSetRegionShape(const wxRegion& region);
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
virtual bool DoSetPathShape(const wxGraphicsPath& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxNonOwnedWindowShapeImpl* m_shapeImpl;
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindow);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WX_MSW_NONOWNEDWND_H_
|
#endif // _WX_MSW_NONOWNEDWND_H_
|
||||||
|
@@ -14,6 +14,11 @@
|
|||||||
|
|
||||||
#include "wx/window.h"
|
#include "wx/window.h"
|
||||||
|
|
||||||
|
// Styles that can be used with any wxNonOwnedWindow:
|
||||||
|
#define wxFRAME_SHAPED 0x0010 // Create a window that is able to be shaped
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_FWD_CORE wxGraphicsPath;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxNonOwnedWindow: a window that is not a child window of another one.
|
// wxNonOwnedWindow: a window that is not a child window of another one.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -24,8 +29,52 @@ public:
|
|||||||
// Set the shape of the window to the given region.
|
// Set the shape of the window to the given region.
|
||||||
// Returns true if the platform supports this feature (and the
|
// Returns true if the platform supports this feature (and the
|
||||||
// operation is successful.)
|
// operation is successful.)
|
||||||
virtual bool SetShape(const wxRegion& WXUNUSED(region)) { return false; }
|
bool SetShape(const wxRegion& region)
|
||||||
|
{
|
||||||
|
// This style is in fact only needed by wxOSX/Carbon so once we don't
|
||||||
|
// use this port any more, we could get rid of this requirement, but
|
||||||
|
// for now you must specify wxFRAME_SHAPED for SetShape() to work on
|
||||||
|
// all platforms.
|
||||||
|
wxCHECK_MSG
|
||||||
|
(
|
||||||
|
HasFlag(wxFRAME_SHAPED), false,
|
||||||
|
wxS("Shaped windows must be created with the wxFRAME_SHAPED style.")
|
||||||
|
);
|
||||||
|
|
||||||
|
return region.IsEmpty() ? DoClearShape() : DoSetRegionShape(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
// Set the shape using the specified path.
|
||||||
|
bool SetShape(const wxGraphicsPath& path)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG
|
||||||
|
(
|
||||||
|
HasFlag(wxFRAME_SHAPED), false,
|
||||||
|
wxS("Shaped windows must be created with the wxFRAME_SHAPED style.")
|
||||||
|
);
|
||||||
|
|
||||||
|
return DoSetPathShape(path);
|
||||||
|
}
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool DoClearShape()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool DoSetRegionShape(const wxRegion& WXUNUSED(region))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
virtual bool DoSetPathShape(const wxGraphicsPath& WXUNUSED(path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__WXDFB__)
|
#if defined(__WXDFB__)
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "wx/window.h"
|
#include "wx/window.h"
|
||||||
|
|
||||||
|
#include "wx/graphics.h"
|
||||||
|
|
||||||
#if wxUSE_SYSTEM_OPTIONS
|
#if wxUSE_SYSTEM_OPTIONS
|
||||||
#define wxMAC_WINDOW_PLAIN_TRANSITION wxT("mac.window-plain-transition")
|
#define wxMAC_WINDOW_PLAIN_TRANSITION wxT("mac.window-plain-transition")
|
||||||
#endif
|
#endif
|
||||||
@@ -82,6 +84,10 @@ public:
|
|||||||
virtual bool SetShape(const wxRegion& region);
|
virtual bool SetShape(const wxRegion& region);
|
||||||
const wxRegion& GetShape() const { return m_shape; }
|
const wxRegion& GetShape() const { return m_shape; }
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
const wxGraphicsPath& GetShapePath() { return m_shapePath; }
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
// activation hooks only necessary for MDI Implementation
|
// activation hooks only necessary for MDI Implementation
|
||||||
static void MacDelayedDeactivation(long timestamp);
|
static void MacDelayedDeactivation(long timestamp);
|
||||||
virtual void MacActivate( long timestamp , bool inIsActivating ) ;
|
virtual void MacActivate( long timestamp , bool inIsActivating ) ;
|
||||||
@@ -125,6 +131,12 @@ protected:
|
|||||||
wxShowEffect effect,
|
wxShowEffect effect,
|
||||||
unsigned timeout);
|
unsigned timeout);
|
||||||
|
|
||||||
|
virtual bool DoClearShape();
|
||||||
|
virtual bool DoSetRegionShape(const wxRegion& region);
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
virtual bool DoSetPathShape(const wxGraphicsPath& path);
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
virtual void WillBeDestroyed();
|
virtual void WillBeDestroyed();
|
||||||
|
|
||||||
wxNonOwnedWindowImpl* m_nowpeer ;
|
wxNonOwnedWindowImpl* m_nowpeer ;
|
||||||
@@ -135,6 +147,9 @@ protected:
|
|||||||
|
|
||||||
private :
|
private :
|
||||||
wxRegion m_shape;
|
wxRegion m_shape;
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
wxGraphicsPath m_shapePath;
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
};
|
};
|
||||||
|
|
||||||
// list of all frames and modeless dialogs
|
// list of all frames and modeless dialogs
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/frame.h" // Just for wxFRAME_SHAPED.
|
|
||||||
#include "wx/nonownedwnd.h"
|
#include "wx/nonownedwnd.h"
|
||||||
#include "wx/region.h"
|
#include "wx/region.h"
|
||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
@@ -33,61 +32,275 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
namespace
|
#include "wx/graphics.h"
|
||||||
{
|
|
||||||
|
|
||||||
// helper
|
// ----------------------------------------------------------------------------
|
||||||
bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
|
// wxNonOwnedWindowShapeImpl: base class for region and path-based classes.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class provides behaviour common to both region and path-based
|
||||||
|
// implementations and defines SetShape() method and virtual dtor that can be
|
||||||
|
// called by wxNonOwnedWindow when it's realized leaving just the
|
||||||
|
// implementation of DoSetShape() to the derived classes.
|
||||||
|
class wxNonOwnedWindowShapeImpl : public wxEvtHandler
|
||||||
{
|
{
|
||||||
if (window)
|
public:
|
||||||
|
wxNonOwnedWindowShapeImpl(wxWindow* win) : m_win(win)
|
||||||
{
|
{
|
||||||
if (region.IsEmpty())
|
|
||||||
{
|
|
||||||
gdk_window_shape_combine_mask(window, NULL, 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
virtual ~wxNonOwnedWindowShapeImpl() { }
|
||||||
|
|
||||||
|
bool SetShape()
|
||||||
|
{
|
||||||
|
if ( m_win->m_wxwindow )
|
||||||
|
SetShapeIfNonNull(gtk_widget_get_window(m_win->m_wxwindow));
|
||||||
|
|
||||||
|
return SetShapeIfNonNull(gtk_widget_get_window(m_win->m_widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be overridden to indicate if the data object must stay around or if
|
||||||
|
// it can be deleted once SetShape() was called.
|
||||||
|
virtual bool CanBeDeleted() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxWindow* const m_win;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// SetShape to the given GDK window by calling DoSetShape() if it's non-NULL.
|
||||||
|
bool SetShapeIfNonNull(GdkWindow* window)
|
||||||
|
{
|
||||||
|
return window && DoSetShape(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetShape the shape to the given GDK window which can be either the window
|
||||||
|
// of m_widget or m_wxwindow of the wxWindow we're used with.
|
||||||
|
virtual bool DoSetShape(GdkWindow* window) = 0;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Version not using any custom shape.
|
||||||
|
class wxNonOwnedWindowShapeImplNone : public wxNonOwnedWindowShapeImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxNonOwnedWindowShapeImplNone(wxWindow* win) :
|
||||||
|
wxNonOwnedWindowShapeImpl(win)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool CanBeDeleted() const { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool DoSetShape(GdkWindow* window)
|
||||||
|
{
|
||||||
|
gdk_window_shape_combine_mask(window, NULL, 0, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Version using simple wxRegion.
|
||||||
|
class wxNonOwnedWindowShapeImplRegion : public wxNonOwnedWindowShapeImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxNonOwnedWindowShapeImplRegion(wxWindow* win, const wxRegion& region) :
|
||||||
|
wxNonOwnedWindowShapeImpl(win),
|
||||||
|
m_region(region)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool CanBeDeleted() const { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool DoSetShape(GdkWindow* window)
|
||||||
|
{
|
||||||
|
gdk_window_shape_combine_region(window, m_region.GetRegion(), 0, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxRegion m_region;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
// Version using more complex wxGraphicsPath.
|
||||||
|
class wxNonOwnedWindowShapeImplPath : public wxNonOwnedWindowShapeImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxNonOwnedWindowShapeImplPath(wxWindow* win, const wxGraphicsPath& path) :
|
||||||
|
wxNonOwnedWindowShapeImpl(win),
|
||||||
|
m_path(path),
|
||||||
|
m_mask(CreateShapeBitmap(path), *wxBLACK)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_win->Connect
|
||||||
|
(
|
||||||
|
wxEVT_PAINT,
|
||||||
|
wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
|
||||||
|
NULL,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~wxNonOwnedWindowShapeImplPath()
|
||||||
|
{
|
||||||
|
m_win->Disconnect
|
||||||
|
(
|
||||||
|
wxEVT_PAINT,
|
||||||
|
wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
|
||||||
|
NULL,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently we always return false from here, if drawing the border
|
||||||
|
// becomes optional, we could return true if we don't need to draw it.
|
||||||
|
virtual bool CanBeDeleted() const { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxBitmap CreateShapeBitmap(const wxGraphicsPath& path)
|
||||||
|
{
|
||||||
|
// Draw the path on a bitmap to get the mask we need.
|
||||||
|
//
|
||||||
|
// Notice that using monochrome bitmap here doesn't work because of an
|
||||||
|
// apparent wxGraphicsContext bug in wxGTK, so use a bitmap of screen
|
||||||
|
// depth even if this is wasteful.
|
||||||
|
wxBitmap bmp(m_win->GetSize());
|
||||||
|
|
||||||
|
wxMemoryDC dc(bmp);
|
||||||
|
|
||||||
|
dc.SetBackground(*wxBLACK);
|
||||||
|
dc.Clear();
|
||||||
|
|
||||||
|
wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
|
||||||
|
context->SetBrush(*wxWHITE);
|
||||||
|
context->FillPath(path);
|
||||||
|
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool DoSetShape(GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkBitmap* bitmap = m_mask.GetBitmap();
|
||||||
|
if ( !bitmap )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
gdk_window_shape_combine_mask(window, bitmap, 0, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a shaped window border.
|
||||||
|
void OnPaint(wxPaintEvent& event)
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
wxPaintDC dc(m_win);
|
||||||
|
wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
|
||||||
|
context->SetPen(wxPen(*wxLIGHT_GREY, 2));
|
||||||
|
context->StrokePath(m_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGraphicsPath m_path;
|
||||||
|
wxMask m_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxNonOwnedWindow implementation
|
// wxNonOwnedWindow implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
wxNonOwnedWindow::~wxNonOwnedWindow()
|
||||||
|
{
|
||||||
|
delete m_shapeImpl;
|
||||||
|
}
|
||||||
|
|
||||||
void wxNonOwnedWindow::GTKHandleRealized()
|
void wxNonOwnedWindow::GTKHandleRealized()
|
||||||
{
|
{
|
||||||
wxNonOwnedWindowBase::GTKHandleRealized();
|
wxNonOwnedWindowBase::GTKHandleRealized();
|
||||||
|
|
||||||
if (HasFlag(wxFRAME_SHAPED))
|
if ( m_shapeImpl )
|
||||||
SetShape(m_shape);
|
{
|
||||||
|
m_shapeImpl->SetShape();
|
||||||
|
|
||||||
|
// We can destroy wxNonOwnedWindowShapeImplRegion immediately but need
|
||||||
|
// to keep wxNonOwnedWindowShapeImplPath around as it draws the border
|
||||||
|
// on every repaint.
|
||||||
|
if ( m_shapeImpl->CanBeDeleted() )
|
||||||
|
{
|
||||||
|
delete m_shapeImpl;
|
||||||
|
m_shapeImpl = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
|
bool wxNonOwnedWindow::DoClearShape()
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
|
if ( !m_shapeImpl )
|
||||||
wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
|
{
|
||||||
|
// Nothing to do, we don't have any custom shape.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ( gtk_widget_get_realized(m_widget) )
|
if ( gtk_widget_get_realized(m_widget) )
|
||||||
{
|
{
|
||||||
if ( m_wxwindow )
|
// Reset the existing shape immediately.
|
||||||
do_shape_combine_region(gtk_widget_get_window(m_wxwindow), region);
|
wxNonOwnedWindowShapeImplNone data(this);
|
||||||
|
data.SetShape();
|
||||||
return do_shape_combine_region(gtk_widget_get_window(m_widget), region);
|
|
||||||
}
|
}
|
||||||
else // not realized yet
|
//else: just do nothing, deleting m_shapeImpl is enough to ensure that we
|
||||||
{
|
// don't set the custom shape later when we're realized.
|
||||||
// store the shape to set, it will be really set once we're realized
|
|
||||||
m_shape = region;
|
|
||||||
|
|
||||||
// we don't know if we're going to succeed or fail, be optimistic by
|
delete m_shapeImpl;
|
||||||
// default
|
m_shapeImpl = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
|
||||||
|
{
|
||||||
|
// In any case get rid of the old data.
|
||||||
|
delete m_shapeImpl;
|
||||||
|
m_shapeImpl = NULL;
|
||||||
|
|
||||||
|
if ( gtk_widget_get_realized(m_widget) )
|
||||||
|
{
|
||||||
|
// We can avoid an unnecessary heap allocation and just set the shape
|
||||||
|
// immediately.
|
||||||
|
wxNonOwnedWindowShapeImplRegion data(this, region);
|
||||||
|
return data.SetShape();
|
||||||
|
}
|
||||||
|
else // Create an object that will set shape when we're realized.
|
||||||
|
{
|
||||||
|
m_shapeImpl = new wxNonOwnedWindowShapeImplRegion(this, region);
|
||||||
|
|
||||||
|
// In general we don't know whether we are going to succeed or not, so
|
||||||
|
// be optimistic.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
|
||||||
|
{
|
||||||
|
// The logic here is simpler than above because we always create
|
||||||
|
// wxNonOwnedWindowShapeImplPath on the heap as we must keep it around,
|
||||||
|
// even if we're already realized
|
||||||
|
|
||||||
|
delete m_shapeImpl;
|
||||||
|
m_shapeImpl = new wxNonOwnedWindowShapeImplPath(this, path);
|
||||||
|
|
||||||
|
if ( gtk_widget_get_realized(m_widget) )
|
||||||
|
{
|
||||||
|
return m_shapeImpl->SetShape();
|
||||||
|
}
|
||||||
|
//else: will be done later from GTKHandleRealized().
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
@@ -34,27 +34,27 @@
|
|||||||
|
|
||||||
#include "wx/nonownedwnd.h"
|
#include "wx/nonownedwnd.h"
|
||||||
|
|
||||||
|
#include "wx/msw/wrapgdip.h"
|
||||||
|
#include "wx/graphics.h"
|
||||||
|
#include "wx/scopedptr.h"
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxNonOwnedWindow implementation
|
// wxNonOwnedWindow implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
|
bool wxNonOwnedWindow::DoClearShape()
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
|
if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
|
||||||
wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
|
|
||||||
|
|
||||||
// The empty region signifies that the shape should be removed from the
|
|
||||||
// window.
|
|
||||||
if ( region.IsEmpty() )
|
|
||||||
{
|
{
|
||||||
if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
|
wxLogLastError(wxT("SetWindowRgn"));
|
||||||
{
|
return false;
|
||||||
wxLogLastError(wxT("SetWindowRgn"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
|
||||||
|
{
|
||||||
// Windows takes ownership of the region, so
|
// Windows takes ownership of the region, so
|
||||||
// we'll have to make a copy of the region to give to it.
|
// we'll have to make a copy of the region to give to it.
|
||||||
DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL);
|
DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL);
|
||||||
@@ -77,4 +77,104 @@ bool wxNonOwnedWindow::SetShape(const wxRegion& region)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
#include "wx/msw/wrapgdip.h"
|
||||||
|
|
||||||
|
// This class contains data used only when SetPath(wxGraphicsPath) is called.
|
||||||
|
//
|
||||||
|
// Notice that it derives from wxEvtHandler solely to allow Connect()-ing its
|
||||||
|
// OnPaint() method to the window, we could get rid of this inheritance once
|
||||||
|
// Bind() can be used in wx sources.
|
||||||
|
class wxNonOwnedWindowShapeImpl : public wxEvtHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxNonOwnedWindowShapeImpl(wxNonOwnedWindow* win, const wxGraphicsPath& path) :
|
||||||
|
m_win(win),
|
||||||
|
m_path(path)
|
||||||
|
{
|
||||||
|
// Create the region corresponding to this path and set it as windows
|
||||||
|
// shape.
|
||||||
|
wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(win));
|
||||||
|
Region gr(static_cast<GraphicsPath*>(m_path.GetNativePath()));
|
||||||
|
win->SetShape(
|
||||||
|
wxRegion(
|
||||||
|
gr.GetHRGN(static_cast<Graphics*>(context->GetNativeContext()))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Connect to the paint event to draw the border.
|
||||||
|
//
|
||||||
|
// TODO: Do this only optionally?
|
||||||
|
m_win->Connect
|
||||||
|
(
|
||||||
|
wxEVT_PAINT,
|
||||||
|
wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint),
|
||||||
|
NULL,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~wxNonOwnedWindowShapeImpl()
|
||||||
|
{
|
||||||
|
m_win->Disconnect
|
||||||
|
(
|
||||||
|
wxEVT_PAINT,
|
||||||
|
wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint),
|
||||||
|
NULL,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnPaint(wxPaintEvent& event)
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
wxPaintDC dc(m_win);
|
||||||
|
wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
|
||||||
|
context->SetPen(wxPen(*wxLIGHT_GREY, 2));
|
||||||
|
context->StrokePath(m_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNonOwnedWindow* const m_win;
|
||||||
|
wxGraphicsPath m_path;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
wxNonOwnedWindow::wxNonOwnedWindow()
|
||||||
|
{
|
||||||
|
m_shapeImpl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNonOwnedWindow::~wxNonOwnedWindow()
|
||||||
|
{
|
||||||
|
delete m_shapeImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
|
||||||
|
{
|
||||||
|
delete m_shapeImpl;
|
||||||
|
m_shapeImpl = new wxNonOwnedWindowShapeImpl(this, path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
// Trivial ctor and dtor as we don't have anything to do when wxGraphicsContext
|
||||||
|
// is not used but still define them here to avoid adding even more #if checks
|
||||||
|
// to the header, it it doesn't do any harm even though it's not needed.
|
||||||
|
wxNonOwnedWindow::wxNonOwnedWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNonOwnedWindow::~wxNonOwnedWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT/!wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
#endif // !__WXWINCE__
|
#endif // !__WXWINCE__
|
||||||
|
@@ -1288,6 +1288,19 @@ void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd))
|
|||||||
dc.SetDeviceClippingRegion(clearRgn);
|
dc.SetDeviceClippingRegion(clearRgn);
|
||||||
dc.Clear();
|
dc.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
// If the window shape is defined by a path, stroke the path to show
|
||||||
|
// the window border.
|
||||||
|
const wxGraphicsPath& path = tlwParent->GetShapePath();
|
||||||
|
if ( !path.IsNull() )
|
||||||
|
{
|
||||||
|
CGContextSetLineWidth(context, 1);
|
||||||
|
CGContextSetStrokeColorWithColor(context, wxLIGHT_GREY->GetCGColor());
|
||||||
|
CGContextAddPath(context, (CGPathRef) path.GetNativePath());
|
||||||
|
CGContextStrokePath(context);
|
||||||
|
}
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
wxpeer->MacPaintChildrenBorders();
|
wxpeer->MacPaintChildrenBorders();
|
||||||
|
@@ -497,25 +497,49 @@ WXWindow wxNonOwnedWindow::GetWXWindow() const
|
|||||||
// Shape implementation
|
// Shape implementation
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoClearShape()
|
||||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
|
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
|
m_shape.Clear();
|
||||||
wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
|
|
||||||
|
|
||||||
m_shape = region;
|
wxSize sz = GetClientSize();
|
||||||
|
wxRegion region(0, 0, sz.x, sz.y);
|
||||||
// The empty region signifies that the shape
|
|
||||||
// should be removed from the window.
|
|
||||||
if ( region.IsEmpty() )
|
|
||||||
{
|
|
||||||
wxSize sz = GetClientSize();
|
|
||||||
wxRegion rgn(0, 0, sz.x, sz.y);
|
|
||||||
if ( rgn.IsEmpty() )
|
|
||||||
return false ;
|
|
||||||
else
|
|
||||||
return SetShape(rgn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_nowpeer->SetShape(region);
|
return m_nowpeer->SetShape(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
|
||||||
|
{
|
||||||
|
m_shape = region;
|
||||||
|
|
||||||
|
return m_nowpeer->SetShape(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
#include "wx/scopedptr.h"
|
||||||
|
|
||||||
|
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
|
||||||
|
{
|
||||||
|
m_shapePath = path;
|
||||||
|
|
||||||
|
// Convert the path to wxRegion by rendering the path on a window-sized
|
||||||
|
// bitmap, creating a mask from it and finally creating the region from
|
||||||
|
// this mask.
|
||||||
|
wxBitmap bmp(GetSize());
|
||||||
|
|
||||||
|
{
|
||||||
|
wxMemoryDC dc(bmp);
|
||||||
|
dc.SetBackground(*wxBLACK);
|
||||||
|
dc.Clear();
|
||||||
|
|
||||||
|
wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
|
||||||
|
context->SetBrush(*wxWHITE);
|
||||||
|
context->FillPath(m_shapePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bmp.SetMask(new wxMask(bmp, *wxBLACK));
|
||||||
|
|
||||||
|
return DoSetRegionShape(wxRegion(bmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxUSE_GRAPHICS_CONTEXT
|
||||||
|
Reference in New Issue
Block a user