]> git.saurik.com Git - wxWidgets.git/blobdiff - src/aui/framemanager.cpp
non-PCH build fix (according to Tinderbox).
[wxWidgets.git] / src / aui / framemanager.cpp
index 48e7daf104b69c1730c4128610ebdd71eb450db7..6822196ead112dd61e361d8c0a19e4fba7ab3934 100644 (file)
@@ -1,10 +1,10 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        framemanager.cpp
+// Name:        src/aui/framemanager.cpp
 // Purpose:     wxaui: wx advanced user interface - docking window manager
 // Author:      Benjamin I. Williams
 // Modified by:
 // Created:     2005-05-17
-// RCS-ID:      
+// RCS-ID:      $Id$
 // Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
 // Licence:     wxWindows Library Licence, Version 3.1
 ///////////////////////////////////////////////////////////////////////////////
 #include "wx/aui/floatpane.h"
 
 #ifndef WX_PRECOMP
-//    #include "wx/log.h"
-#endif
-
-//#include "wx/dcbuffer.h"
-
-#include "wx/dcclient.h"
-#include "wx/dcscreen.h"
-#include "wx/app.h"
-#include "wx/image.h"
-#include "wx/settings.h"
-#include "wx/toolbar.h"
-
-#if wxUSE_MDI
-#include "wx/mdi.h"
+    #include "wx/panel.h"
+    #include "wx/settings.h"
+    #include "wx/app.h"
+    #include "wx/dcclient.h"
+    #include "wx/dcscreen.h"
+    #include "wx/toolbar.h"
+    #include "wx/mdi.h"
+    #include "wx/image.h"
 #endif
 
 WX_CHECK_BUILD_OPTIONS("wxAUI")
@@ -59,6 +53,8 @@ WX_DEFINE_OBJARRAY(wxPaneInfoArray)
 wxPaneInfo wxNullPaneInfo;
 wxDockInfo wxNullDockInfo;
 DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
+DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSE)
+DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER)
 
 #ifdef __WXMAC__
     // a few defines to avoid nameclashes
@@ -67,6 +63,137 @@ DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON)
     #include "wx/mac/private.h"
 #endif
 
+IMPLEMENT_DYNAMIC_CLASS(wxFrameManagerEvent, wxEvent)
+
+class wxPseudoTransparentFrame : public wxFrame
+{
+public:
+    wxPseudoTransparentFrame(wxWindow* parent = NULL,
+                wxWindowID id = wxID_ANY,
+                const wxString& title = wxEmptyString,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxDEFAULT_FRAME_STYLE,
+                const wxString &name = wxT("frame"))
+                    : wxFrame(parent, id, title, pos, size, style | wxFRAME_SHAPED, name)
+    {
+        SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+        m_Amount=0;
+        m_MaxWidth=0;
+        m_MaxHeight=0;
+        m_lastWidth=0;
+        m_lastHeight=0;
+#ifdef __WXGTK__
+        m_CanSetShape = false; // have to wait for window create event on GTK
+#else
+        m_CanSetShape = true;
+#endif
+        m_Region = wxRegion(0, 0, 0, 0);
+        SetTransparent(0);
+    }
+
+    virtual bool SetTransparent(wxByte alpha)
+    {
+        if (m_CanSetShape)
+        {
+            int w=100; // some defaults
+            int h=100;
+            GetClientSize(&w, &h);
+
+            m_MaxWidth = w;
+            m_MaxHeight = h;
+            m_Amount = alpha;
+            m_Region.Clear();
+//            m_Region.Union(0, 0, 1, m_MaxWidth);
+            if (m_Amount)
+            {
+                for (int y=0; y<m_MaxHeight; y++)
+                {
+                    // Reverse the order of the bottom 4 bits
+                    int j=((y&8)?1:0)|((y&4)?2:0)|((y&2)?4:0)|((y&1)?8:0);
+                    if ((j*16+8)<m_Amount)
+                        m_Region.Union(0, y, m_MaxWidth, 1);
+                }
+            }
+            SetShape(m_Region);
+            Refresh();
+        }
+        return true;
+    }
+
+    void OnPaint(wxPaintEvent& WXUNUSED(event))
+    {
+        wxPaintDC dc(this);
+
+        if (m_Region.IsEmpty())
+            return;
+
+#ifdef __WXMAC__
+        dc.SetBrush(wxColour(128, 192, 255));
+#else
+        dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
+#endif
+        dc.SetPen(*wxTRANSPARENT_PEN);
+
+        wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
+
+        while (upd)
+        {
+            wxRect rect(upd.GetRect());
+            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
+
+            upd++;
+        }
+    }
+
+#ifdef __WXGTK__
+    void OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event)) {m_CanSetShape=true; SetTransparent(0);}
+#endif
+
+    void OnSize(wxSizeEvent& event)
+    {
+        // We sometimes get surplus size events
+        if ((event.GetSize().GetWidth() == m_lastWidth) &&
+            (event.GetSize().GetHeight() == m_lastHeight))
+        {
+            event.Skip();
+            return;
+        }
+        m_lastWidth = event.GetSize().GetWidth();
+        m_lastHeight = event.GetSize().GetHeight();
+
+        SetTransparent(m_Amount);
+        m_Region.Intersect(0, 0, event.GetSize().GetWidth(),
+                           event.GetSize().GetHeight());
+        SetShape(m_Region);
+        Refresh();
+        event.Skip();
+    }
+
+private:
+    wxByte m_Amount;
+    int m_MaxWidth;
+    int m_MaxHeight;
+    bool m_CanSetShape;
+    int m_lastWidth,m_lastHeight;
+
+    wxRegion m_Region;
+
+    DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame)
+    DECLARE_EVENT_TABLE()
+};
+
+
+IMPLEMENT_DYNAMIC_CLASS( wxPseudoTransparentFrame, wxFrame )
+
+BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame)
+    EVT_PAINT(wxPseudoTransparentFrame::OnPaint)
+    EVT_SIZE(wxPseudoTransparentFrame::OnSize)
+#ifdef __WXGTK__
+    EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate)
+#endif
+END_EVENT_TABLE()
+
 
 // -- static utility functions --
 
@@ -81,46 +208,13 @@ static void DrawResizeHint(wxDC& dc, const wxRect& rect)
 {
     wxBitmap stipple = wxPaneCreateStippleBitmap();
     wxBrush brush(stipple);
-    dc.SetBrush(brush);    
+    dc.SetBrush(brush);
     dc.SetPen(*wxTRANSPARENT_PEN);
 
     dc.SetLogicalFunction(wxXOR);
     dc.DrawRectangle(rect);
 }
 
-#ifdef __WXMSW__
-
-// on supported windows systems (Win2000 and greater), this function
-// will make a frame window transparent by a certain amount
-static void MakeWindowTransparent(wxWindow* wnd, int amount)
-{
-    // this API call is not in all SDKs, only the newer ones, so
-    // we will runtime bind this
-    typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD);
-    static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL;
-    static HMODULE h = NULL;
-    HWND hwnd = (HWND)wnd->GetHWND();
-    
-    if (!h)
-        h = LoadLibrary(_T("user32"));
-        
-    if (!pSetLayeredWindowAttributes)
-    {
-        pSetLayeredWindowAttributes =
-         (PSETLAYEREDWINDOWATTR)GetProcAddress(h,"SetLayeredWindowAttributes");
-    }
-    
-    if (pSetLayeredWindowAttributes == NULL)
-        return;
-        
-    LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
-    if (0 == (exstyle & 0x80000) /*WS_EX_LAYERED*/)
-        SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | 0x80000 /*WS_EX_LAYERED*/);   
-             
-    pSetLayeredWindowAttributes(hwnd, 0, amount, 2 /*LWA_ALPHA*/);
-}
-
-#endif
 
 
 // CopyDocksAndPanes() - this utility function creates copies of
@@ -171,7 +265,7 @@ static int GetMaxRow(const wxPaneInfoArray& panes, int direction, int layer)
     {
         wxPaneInfo& pane = panes.Item(i);
         if (pane.dock_direction == direction &&
-            pane.dock_layer == layer && 
+            pane.dock_layer == layer &&
             pane.dock_row > max_row)
                 max_row = pane.dock_row;
     }
@@ -216,7 +310,7 @@ static void DoInsertDockRow(wxPaneInfoArray& panes,
     }
 }
 
-// DoInsertDockLayer() is an internal function that inserts a space for 
+// DoInsertDockLayer() is an internal function that inserts a space for
 // another dock pane by incrementing all existing dock row values by one
 static void DoInsertPane(wxPaneInfoArray& panes,
                          int dock_direction,
@@ -259,14 +353,14 @@ static void FindDocks(wxDockInfoArray& docks,
         max_row = wxMax(max_row, docks.Item(i).dock_row);
         max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
     }
-    
+
     // if no dock layer was specified, search all dock layers
     if (dock_layer == -1)
     {
         begin_layer = 0;
         end_layer = max_layer;
     }
-    
+
     // if no dock row was specified, search all dock row
     if (dock_row == -1)
     {
@@ -304,16 +398,16 @@ static wxPaneInfo* FindPaneInDock(const wxDockInfo& dock, wxWindow* window)
 }
 
 // RemovePaneFromDocks() removes a pane window from all docks
-// with a possible exception specified by parameter "except"
+// with a possible exception specified by parameter "ex_cept"
 static void RemovePaneFromDocks(wxDockInfoArray& docks,
                                 wxPaneInfo& pane,
-                                wxDockInfo* except = NULL)
+                                wxDockInfo* ex_cept  = NULL  )
 {
     int i, dock_count;
     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
     {
         wxDockInfo& d = docks.Item(i);
-        if (&d == except)
+        if (&d == ex_cept)
             continue;
         wxPaneInfo* pi = FindPaneInDock(d, pane.window);
         if (pi)
@@ -337,7 +431,9 @@ static void RenumberDockRows(wxDockInfoPtrArray& docks)
 }
 
 
-
+// SetActivePane() sets the active pane, as well as cycles through
+// every other pane and makes sure that all others' active flags
+// are turned off
 static void SetActivePane(wxPaneInfoArray& panes, wxWindow* active_pane)
 {
     int i, pane_count;
@@ -363,6 +459,7 @@ static int PaneSortFunc(wxPaneInfo** p1, wxPaneInfo** p2)
 
 BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler)
     EVT_AUI_PANEBUTTON(wxFrameManager::OnPaneButton)
+    EVT_AUI_RENDER(wxFrameManager::OnRender)
     EVT_PAINT(wxFrameManager::OnPaint)
     EVT_ERASE_BACKGROUND(wxFrameManager::OnEraseBackground)
     EVT_SIZE(wxFrameManager::OnSize)
@@ -376,7 +473,7 @@ BEGIN_EVENT_TABLE(wxFrameManager, wxEvtHandler)
 END_EVENT_TABLE()
 
 
-wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags)
+wxFrameManager::wxFrameManager(wxWindow* managed_wnd, unsigned int flags)
 {
     m_action = actionNone;
     m_last_mouse_move = wxPoint();
@@ -384,10 +481,11 @@ wxFrameManager::wxFrameManager(wxFrame* frame, unsigned int flags)
     m_art = new wxDefaultDockArt;
     m_hint_wnd = NULL;
     m_flags = flags;
+    m_skipping = false;
 
-    if (frame)
+    if (managed_wnd)
     {
-        SetFrame(frame);
+        SetManagedWindow(managed_wnd);
     }
 }
 
@@ -396,6 +494,12 @@ wxFrameManager::~wxFrameManager()
     delete m_art;
 }
 
+// Creates a floating frame for the windows
+wxFloatingPane * wxFrameManager::CreateFloatingFrame(wxWindow* parent, const wxPaneInfo& p)
+{
+    return new wxFloatingPane(parent, this, p);
+}
+
 // GetPane() looks up a wxPaneInfo structure based
 // on the supplied window pointer.  Upon failure, GetPane()
 // returns an empty wxPaneInfo, a condition which can be checked
@@ -448,26 +552,26 @@ wxDockUIPart* wxFrameManager::HitTest(int x, int y)
     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
     {
         wxDockUIPart* item = &m_uiparts.Item(i);
-        
-        // we are not interested in typeDock, because this space 
+
+        // we are not interested in typeDock, because this space
         // isn't used to draw anything, just for measurements;
         // besides, the entire dock area is covered with other
         // rectangles, which we are interested in.
         if (item->type == wxDockUIPart::typeDock)
             continue;
-        
+
         // if we already have a hit on a more specific item, we are not
         // interested in a pane hit.  If, however, we don't already have
         // a hit, returning a pane hit is necessary for some operations
         if ((item->type == wxDockUIPart::typePane ||
             item->type == wxDockUIPart::typePaneBorder) && result)
             continue;
-           
+
         // if the point is inside the rectangle, we have a hit
-        if (item->rect.Inside(x,y))
+        if (item->rect.Contains(x,y))
             result = item;
     }
-    
+
     return result;
 }
 
@@ -485,10 +589,25 @@ unsigned int wxFrameManager::GetFlags() const
 }
 
 
-// SetFrame() is usually called once when the frame
+// don't use these anymore as they are deprecated
+// use Set/GetManagedFrame() instead
+void wxFrameManager::SetFrame(wxFrame* frame)
+{
+    SetManagedWindow((wxWindow*)frame);
+}
+
+wxFrame* wxFrameManager::GetFrame() const
+{
+    return (wxFrame*)m_frame;
+}
+
+
+
+
+// SetManagedWindow() is usually called once when the frame
 // manager class is being initialized.  "frame" specifies
 // the frame which should be managed by the frame mananger
-void wxFrameManager::SetFrame(wxFrame* frame)
+void wxFrameManager::SetManagedWindow(wxWindow* frame)
 {
     wxASSERT_MSG(frame, wxT("specified frame must be non-NULL"));
 
@@ -512,6 +631,58 @@ void wxFrameManager::SetFrame(wxFrame* frame)
                 CenterPane().PaneBorder(false));
     }
 #endif
+
+    // Make a window to use for a transparent hint
+#if defined(__WXMSW__) || defined(__WXGTK__)
+    m_hint_wnd = new wxFrame(m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
+                             wxFRAME_TOOL_WINDOW |
+                             wxFRAME_FLOAT_ON_PARENT |
+                             wxFRAME_NO_TASKBAR |
+                             wxNO_BORDER);
+
+    m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
+
+#elif defined(__WXMAC__)
+    // Using a miniframe with float and tool styles keeps the parent
+    // frame activated and highlighted as such...
+    m_hint_wnd = new wxMiniFrame(m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
+                                 wxFRAME_FLOAT_ON_PARENT
+                                 | wxFRAME_TOOL_WINDOW );
+
+    // Can't set the bg colour of a Frame in wxMac
+    wxPanel* p = new wxPanel(m_hint_wnd);
+
+    // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver
+    // color that is really hard to see, especially transparent.
+    // Until a better system color is decided upon we'll just use
+    // blue.
+    p->SetBackgroundColour(*wxBLUE);
+#endif
+
+    m_hint_fademax=50;
+
+    if (m_hint_wnd
+        // CanSetTransparent is only present in the 2.7.0 ABI. To allow this file to be easily used
+        // in a backported environment, conditionally compile this in.
+#if wxCHECK_VERSION(2,7,0)
+       && !m_hint_wnd->CanSetTransparent()
+#endif
+        )
+    {
+
+        m_hint_wnd->Close();
+        m_hint_wnd->Destroy();
+        m_hint_wnd = NULL;
+
+        // If we can convert it to a PseudoTransparent window, do so
+        m_hint_wnd = new wxPseudoTransparentFrame (m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
+                                                wxFRAME_TOOL_WINDOW |
+                                                wxFRAME_FLOAT_ON_PARENT |
+                                                wxFRAME_NO_TASKBAR |
+                                                wxNO_BORDER);
+
+        m_hint_fademax = 128;
+    }
 }
 
 
@@ -523,8 +694,8 @@ void wxFrameManager::UnInit()
     m_frame->RemoveEventHandler(this);
 }
 
-// GetFrame() returns the frame pointer being managed by wxFrameManager
-wxFrame* wxFrameManager::GetFrame() const
+// GetManagedWindow() returns the window pointer being managed
+wxWindow* wxFrameManager::GetManagedWindow() const
 {
     return m_frame;
 }
@@ -548,16 +719,19 @@ void wxFrameManager::ProcessMgrEvent(wxFrameManagerEvent& event)
 
 // SetArtProvider() instructs wxFrameManager to use the
 // specified art provider for all drawing calls.  This allows
-// plugable look-and-feel features
+// plugable look-and-feel features.  The pointer that is
+// passed to this method subsequently belongs to wxFrameManager,
+// and is deleted in the frame manager destructor
 void wxFrameManager::SetArtProvider(wxDockArt* art_provider)
 {
     // delete the last art provider, if any
     delete m_art;
-    
+
     // assign the new art provider
     m_art = art_provider;
 }
 
+
 bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
 {
     // check if the pane has a valid window
@@ -574,16 +748,21 @@ bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
 
     // set the pane window
     pinfo.window = window;
-    
+
     // if the pane's name identifier is blank, create a random string
-    if (pinfo.name.IsEmpty())
+    if (pinfo.name.empty())
     {
-        pinfo.name.Printf(wxT("%08x%08x%08x%08x"),
+        pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"),
              ((unsigned long)pinfo.window) & 0xffffffff,
              (unsigned int)time(NULL),
-             (unsigned int)clock(), m_panes.GetCount());
+#ifdef __WXWINCE__
+             (unsigned int)GetTickCount(),
+#else
+             (unsigned int)clock(),
+#endif
+             (unsigned long)m_panes.GetCount());
     }
-    
+
     // set initial proportion (if not already set)
     if (pinfo.dock_proportion == 0)
         pinfo.dock_proportion = 100000;
@@ -595,7 +774,7 @@ bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
         button.button_id = wxPaneInfo::buttonClose;
         pinfo.buttons.Add(button);
     }
-    
+
     if (pinfo.best_size == wxDefaultSize &&
         pinfo.window)
     {
@@ -607,7 +786,7 @@ bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
             // a toolbar under some newer versions of wxWidgets,
             // so use GetBestSize()
             pinfo.best_size = pinfo.window->GetBestSize();
-                    
+
             // for some reason, wxToolBar::GetBestSize() is returning
             // a size that is a pixel shy of the correct amount.
             // I believe this to be the correct action, until
@@ -615,7 +794,7 @@ bool wxFrameManager::AddPane(wxWindow* window, const wxPaneInfo& pane_info)
             // correct?
             pinfo.best_size.y++;
         }
-        
+
         if (pinfo.min_size != wxDefaultSize)
         {
             if (pinfo.best_size.x < pinfo.min_size.x)
@@ -645,6 +824,20 @@ bool wxFrameManager::AddPane(wxWindow* window,
     return AddPane(window, pinfo);
 }
 
+bool wxFrameManager::AddPane(wxWindow* window,
+                             const wxPaneInfo& pane_info,
+                             const wxPoint& drop_pos)
+{
+    if (!AddPane(window, pane_info))
+        return false;
+
+    wxPaneInfo& pane = GetPane(window);
+
+    DoDrop(m_docks, m_panes, pane, drop_pos, wxPoint(0,0));
+
+    return true;
+}
+
 bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
                                 int insert_level)
 {
@@ -670,7 +863,7 @@ bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
                  pane_info.dock_layer);
             break;
     }
-    
+
     // if the window already exists, we are basically just moving/inserting the
     // existing window.  If it doesn't exist, we need to add it and insert it
     wxPaneInfo& existing_pane = GetPane(window);
@@ -678,7 +871,7 @@ bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
     {
         return AddPane(window, pane_info);
     }
-     else
+    else
     {
         if (pane_info.IsFloating())
         {
@@ -700,13 +893,15 @@ bool wxFrameManager::InsertPane(wxWindow* window, const wxPaneInfo& pane_info,
     return true;
 }
 
-    
+
+// DetachPane() removes a pane from the frame manager.  This
+// method will not destroy the window that is removed.
 bool wxFrameManager::DetachPane(wxWindow* window)
 {
     int i, count;
     for (i = 0, count = m_panes.GetCount(); i < count; ++i)
     {
-        wxPaneInfo& p = m_panes.Item(i);    
+        wxPaneInfo& p = m_panes.Item(i);
         if (p.window == window)
         {
             if (p.frame)
@@ -716,7 +911,9 @@ bool wxFrameManager::DetachPane(wxWindow* window)
 
                 // reduce flicker
                 p.window->SetSize(1,1);
-                p.frame->Show(false);
+
+                if (p.frame->IsShown())
+                    p.frame->Show(false);
 
                 // reparent to m_frame and destroy the pane
                 p.window->Reparent(m_frame);
@@ -724,6 +921,24 @@ bool wxFrameManager::DetachPane(wxWindow* window)
                 p.frame->Destroy();
                 p.frame = NULL;
             }
+
+            // make sure there are no references to this pane in our uiparts,
+            // just in case the caller doesn't call Update() immediately after
+            // the DetachPane() call.  This prevets obscure crashes which would
+            // happen at window repaint if the caller forgets to call Update()
+            int pi, part_count;
+            for (pi = 0, part_count = (int)m_uiparts.GetCount(); pi < part_count; ++pi)
+            {
+                wxDockUIPart& part = m_uiparts.Item(pi);
+                if (part.pane == &p)
+                {
+                    m_uiparts.RemoveAt(pi);
+                    part_count--;
+                    pi--;
+                    continue;
+                }
+            }
+
             m_panes.RemoveAt(i);
             return true;
         }
@@ -731,6 +946,40 @@ bool wxFrameManager::DetachPane(wxWindow* window)
     return false;
 }
 
+// ClosePane() destroys or hides the pane depending on its
+// flags
+void wxFrameManager::ClosePane(wxPaneInfo& pane_info)
+{
+    // first, hide the window
+    if (pane_info.window && pane_info.window->IsShown()) {
+        pane_info.window->Show(false);
+    }
+
+    // make sure that we are the parent of this window
+    if(pane_info.window && pane_info.window->GetParent() != m_frame) {
+        pane_info.window->Reparent(m_frame);
+    }
+
+    // if we have a frame, destroy it
+    if(pane_info.frame) {
+        pane_info.frame->Destroy();
+        pane_info.frame = NULL;
+    }
+
+    // now we need to either destroy or hide the pane
+    if(pane_info.IsDestroyOnClose()) 
+    {
+        wxWindow * window = pane_info.window;
+        DetachPane(window);
+        if(window) {
+            window->Destroy();
+        }
+    } 
+    else 
+    {
+        pane_info.Hide();
+    }
+}
 
 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
 // in the input string.  This is an internal functions which is
@@ -738,7 +987,7 @@ bool wxFrameManager::DetachPane(wxWindow* window)
 static wxString EscapeDelimiters(const wxString& s)
 {
     wxString result;
-    result.Alloc(s.Length());
+    result.Alloc(s.length());
     const wxChar* ch = s.c_str();
     while (*ch)
     {
@@ -750,6 +999,112 @@ static wxString EscapeDelimiters(const wxString& s)
     return result;
 }
 
+wxString wxFrameManager::SavePaneInfo(wxPaneInfo& pane)
+{
+    wxString result = wxT("name=");
+    result += EscapeDelimiters(pane.name);
+    result += wxT(";");
+
+    result += wxT("caption=");
+    result += EscapeDelimiters(pane.caption);
+    result += wxT(";");
+
+    result += wxString::Format(wxT("state=%u;"), pane.state);
+    result += wxString::Format(wxT("dir=%d;"), pane.dock_direction);
+    result += wxString::Format(wxT("layer=%d;"), pane.dock_layer);
+    result += wxString::Format(wxT("row=%d;"), pane.dock_row);
+    result += wxString::Format(wxT("pos=%d;"), pane.dock_pos);
+    result += wxString::Format(wxT("prop=%d;"), pane.dock_proportion);
+    result += wxString::Format(wxT("bestw=%d;"), pane.best_size.x);
+    result += wxString::Format(wxT("besth=%d;"), pane.best_size.y);
+    result += wxString::Format(wxT("minw=%d;"), pane.min_size.x);
+    result += wxString::Format(wxT("minh=%d;"), pane.min_size.y);
+    result += wxString::Format(wxT("maxw=%d;"), pane.max_size.x);
+    result += wxString::Format(wxT("maxh=%d;"), pane.max_size.y);
+    result += wxString::Format(wxT("floatx=%d;"), pane.floating_pos.x);
+    result += wxString::Format(wxT("floaty=%d;"), pane.floating_pos.y);
+    result += wxString::Format(wxT("floatw=%d;"), pane.floating_size.x);
+    result += wxString::Format(wxT("floath=%d"), pane.floating_size.y);
+
+    return result;
+}
+
+// Load a "pane" with the pane infor settings in pane_part
+void wxFrameManager::LoadPaneInfo(wxString pane_part, wxPaneInfo &pane)
+{
+    // replace escaped characters so we can
+    // split up the string easily
+    pane_part.Replace(wxT("\\|"), wxT("\a"));
+    pane_part.Replace(wxT("\\;"), wxT("\b"));
+
+    while(1)
+    {
+        wxString val_part = pane_part.BeforeFirst(wxT(';'));
+        pane_part = pane_part.AfterFirst(wxT(';'));
+        wxString val_name = val_part.BeforeFirst(wxT('='));
+        wxString value = val_part.AfterFirst(wxT('='));
+        val_name.MakeLower();
+        val_name.Trim(true);
+        val_name.Trim(false);
+        value.Trim(true);
+        value.Trim(false);
+
+        if (val_name.empty())
+            break;
+
+        if (val_name == wxT("name"))
+            pane.name = value;
+        else if (val_name == wxT("caption"))
+            pane.caption = value;
+        else if (val_name == wxT("state"))
+            pane.state = (unsigned int)wxAtoi(value.c_str());
+        else if (val_name == wxT("dir"))
+            pane.dock_direction = wxAtoi(value.c_str());
+        else if (val_name == wxT("layer"))
+            pane.dock_layer = wxAtoi(value.c_str());
+        else if (val_name == wxT("row"))
+            pane.dock_row = wxAtoi(value.c_str());
+        else if (val_name == wxT("pos"))
+            pane.dock_pos = wxAtoi(value.c_str());
+        else if (val_name == wxT("prop"))
+            pane.dock_proportion = wxAtoi(value.c_str());
+        else if (val_name == wxT("bestw"))
+            pane.best_size.x = wxAtoi(value.c_str());
+        else if (val_name == wxT("besth"))
+            pane.best_size.y = wxAtoi(value.c_str());
+        else if (val_name == wxT("minw"))
+            pane.min_size.x = wxAtoi(value.c_str());
+        else if (val_name == wxT("minh"))
+            pane.min_size.y = wxAtoi(value.c_str());
+        else if (val_name == wxT("maxw"))
+            pane.max_size.x = wxAtoi(value.c_str());
+        else if (val_name == wxT("maxh"))
+            pane.max_size.y = wxAtoi(value.c_str());
+        else if (val_name == wxT("floatx"))
+            pane.floating_pos.x = wxAtoi(value.c_str());
+        else if (val_name == wxT("floaty"))
+            pane.floating_pos.y = wxAtoi(value.c_str());
+        else if (val_name == wxT("floatw"))
+            pane.floating_size.x = wxAtoi(value.c_str());
+        else if (val_name == wxT("floath"))
+            pane.floating_size.y = wxAtoi(value.c_str());
+        else {
+            wxFAIL_MSG(wxT("Bad Perspective String"));
+        }
+    }
+
+    // replace escaped characters so we can
+    // split up the string easily
+    pane.name.Replace(wxT("\a"), wxT("|"));
+    pane.name.Replace(wxT("\b"), wxT(";"));
+    pane.caption.Replace(wxT("\a"), wxT("|"));
+    pane.caption.Replace(wxT("\b"), wxT(";"));
+    pane_part.Replace(wxT("\a"), wxT("|"));
+    pane_part.Replace(wxT("\b"), wxT(";"));
+
+    return;
+}
+
 
 // SavePerspective() saves all pane information as a single string.
 // This string may later be fed into LoadPerspective() to restore
@@ -766,44 +1121,19 @@ wxString wxFrameManager::SavePerspective()
     for (pane_i = 0; pane_i < pane_count; ++pane_i)
     {
         wxPaneInfo& pane = m_panes.Item(pane_i);
-        
-        result += wxT("name=");
-        result += EscapeDelimiters(pane.name);
-        result += wxT(";");
-        
-        result += wxT("caption=");
-        result += EscapeDelimiters(pane.caption);
-        result += wxT(";");
-        
-        result += wxString::Format(wxT("state=%u;"), pane.state);
-        result += wxString::Format(wxT("dir=%d;"), pane.dock_direction);
-        result += wxString::Format(wxT("layer=%d;"), pane.dock_layer);
-        result += wxString::Format(wxT("row=%d;"), pane.dock_row);
-        result += wxString::Format(wxT("pos=%d;"), pane.dock_pos);
-        result += wxString::Format(wxT("prop=%d;"), pane.dock_proportion);
-        result += wxString::Format(wxT("bestw=%d;"), pane.best_size.x);
-        result += wxString::Format(wxT("besth=%d;"), pane.best_size.y);
-        result += wxString::Format(wxT("minw=%d;"), pane.min_size.x);
-        result += wxString::Format(wxT("minh=%d;"), pane.min_size.y);
-        result += wxString::Format(wxT("maxw=%d;"), pane.max_size.x);
-        result += wxString::Format(wxT("maxh=%d;"), pane.max_size.y);
-        result += wxString::Format(wxT("floatx=%d;"), pane.floating_pos.x);
-        result += wxString::Format(wxT("floaty=%d;"), pane.floating_pos.y);
-        result += wxString::Format(wxT("floatw=%d;"), pane.floating_size.x);
-        result += wxString::Format(wxT("floath=%d"), pane.floating_size.y);
-        result += wxT("|");
-    }
-    
+        result += SavePaneInfo(pane)+wxT("|");
+    }
+
     int dock_i, dock_count = m_docks.GetCount();
     for (dock_i = 0; dock_i < dock_count; ++dock_i)
     {
         wxDockInfo& dock = m_docks.Item(dock_i);
-        
+
         result += wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"),
                                    dock.dock_direction, dock.dock_layer,
                                    dock.dock_row, dock.size);
     }
-    
+
     return result;
 }
 
@@ -814,7 +1144,7 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
 {
     wxString input = layout;
     wxString part;
-    
+
     // check layout string version
     part = input.BeforeFirst(wxT('|'));
     input = input.AfterFirst(wxT('|'));
@@ -822,8 +1152,7 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
     part.Trim(false);
     if (part != wxT("layout1"))
         return false;
-    
-    
+
     // mark all panes currently managed as docked and hidden
     int pane_i, pane_count = m_panes.GetCount();
     for (pane_i = 0; pane_i < pane_count; ++pane_i)
@@ -831,12 +1160,12 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
 
     // clear out the dock array; this will be reconstructed
     m_docks.Clear();
-    
+
     // replace escaped characters so we can
     // split up the string easily
     input.Replace(wxT("\\|"), wxT("\a"));
     input.Replace(wxT("\\;"), wxT("\b"));
-    
+
     while (1)
     {
         wxPaneInfo pane;
@@ -846,15 +1175,14 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
         pane_part.Trim(true);
 
         // if the string is empty, we're done parsing
-        if (pane_part.IsEmpty())
+        if (pane_part.empty())
             break;
 
-
         if (pane_part.Left(9) == wxT("dock_size"))
         {
             wxString val_name = pane_part.BeforeFirst(wxT('='));
             wxString value = pane_part.AfterFirst(wxT('='));
-                  
+
             long dir, layer, row, size;
             wxString piece = val_name.AfterFirst(wxT('('));
             piece = piece.BeforeLast(wxT(')'));
@@ -863,7 +1191,7 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
             piece.BeforeFirst(wxT(',')).ToLong(&layer);
             piece.AfterFirst(wxT(',')).ToLong(&row);
             value.ToLong(&size);
-            
+
             wxDockInfo dock;
             dock.dock_direction = dir;
             dock.dock_layer = layer;
@@ -873,69 +1201,13 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
             continue;
         }
 
-        while (1)
-        {
-            wxString val_part = pane_part.BeforeFirst(wxT(';'));
-            pane_part = pane_part.AfterFirst(wxT(';'));
-            wxString val_name = val_part.BeforeFirst(wxT('='));
-            wxString value = val_part.AfterFirst(wxT('='));
-            val_name.MakeLower();
-            val_name.Trim(true);
-            val_name.Trim(false);
-            value.Trim(true);
-            value.Trim(false);
-        
-            if (val_name.IsEmpty())
-                break;
+        // Undo our escaping as LoadPaneInfo needs to take an unescaped
+        // name so it can be called by external callers
+        pane_part.Replace(wxT("\a"), wxT("|"));
+        pane_part.Replace(wxT("\b"), wxT(";"));
+
+        LoadPaneInfo(pane_part, pane);
 
-            if (val_name == wxT("name"))
-                pane.name = value;
-            else if (val_name == wxT("caption"))
-                pane.caption = value;
-            else if (val_name == wxT("state"))
-                pane.state = (unsigned int)wxAtoi(value.c_str());
-            else if (val_name == wxT("dir"))
-                pane.dock_direction = wxAtoi(value.c_str());
-            else if (val_name == wxT("layer"))
-                pane.dock_layer = wxAtoi(value.c_str());
-            else if (val_name == wxT("row"))
-                pane.dock_row = wxAtoi(value.c_str());
-            else if (val_name == wxT("pos"))
-                pane.dock_pos = wxAtoi(value.c_str());
-            else if (val_name == wxT("prop"))
-                pane.dock_proportion = wxAtoi(value.c_str());
-            else if (val_name == wxT("bestw"))
-                pane.best_size.x = wxAtoi(value.c_str());
-            else if (val_name == wxT("besth"))
-                pane.best_size.y = wxAtoi(value.c_str());
-            else if (val_name == wxT("minw"))
-                pane.min_size.x = wxAtoi(value.c_str());
-            else if (val_name == wxT("minh"))
-                pane.min_size.y = wxAtoi(value.c_str());
-            else if (val_name == wxT("maxw"))
-                pane.max_size.x = wxAtoi(value.c_str());
-            else if (val_name == wxT("maxh"))
-                pane.max_size.y = wxAtoi(value.c_str());
-            else if (val_name == wxT("floatx"))
-                pane.floating_pos.x = wxAtoi(value.c_str());
-            else if (val_name == wxT("floaty"))
-                pane.floating_pos.y = wxAtoi(value.c_str());
-            else if (val_name == wxT("floatw"))
-                pane.floating_size.x = wxAtoi(value.c_str());
-            else if (val_name == wxT("floath"))
-                pane.floating_size.y = wxAtoi(value.c_str());
-            else {
-                wxFAIL_MSG(wxT("Bad Perspective String"));
-            }
-        }
-        
-        // replace escaped characters so we can
-        // split up the string easily
-        pane.name.Replace(wxT("\a"), wxT("|"));
-        pane.name.Replace(wxT("\b"), wxT(";"));
-        pane.caption.Replace(wxT("\a"), wxT("|"));
-        pane.caption.Replace(wxT("\b"), wxT(";"));
-        
         wxPaneInfo& p = GetPane(pane.name);
         if (!p.IsOk())
         {
@@ -943,20 +1215,17 @@ bool wxFrameManager::LoadPerspective(const wxString& layout, bool update)
             // in the existing layout
             return false;
         }
-        
-        pane.window = p.window;
-        pane.frame = p.frame;
-        pane.buttons = p.buttons;
-        p = pane;
+
+        p.SafeSet(pane);
+
     }
-    
+
     if (update)
         Update();
 
     return true;
 }
 
-
 void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
                                               wxArrayInt& positions,
                                               wxArrayInt& sizes)
@@ -982,7 +1251,7 @@ void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
             action_pane = pane_i;
         }
     }
-    
+
     // set up each panes default position, and
     // determine the size (width or height, depending
     // on the dock's orientation) of each pane
@@ -991,10 +1260,10 @@ void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
         wxPaneInfo& pane = *(dock.panes.Item(pane_i));
         positions.Add(pane.dock_pos);
         int size = 0;
-        
+
         if (pane.HasBorder())
             size += (pane_border_size*2);
-                
+
         if (dock.IsHorizontal())
         {
             if (pane.HasGripper() && !pane.HasGripperTop())
@@ -1007,10 +1276,10 @@ void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
                 size += gripper_size;
 
             if (pane.HasCaption())
-                size += caption_size; 
+                size += caption_size;
             size += pane.best_size.y;
         }
-   
+
         sizes.Add(size);
     }
 
@@ -1031,7 +1300,7 @@ void wxFrameManager::GetPanePositionsAndSizes(wxDockInfo& dock,
 
         offset += sizes[pane_i];
     }
-    
+
     // if the dock mode is fixed, make sure none of the panes
     // overlap; we will bump panes that overlap
     offset = 0;
@@ -1053,7 +1322,7 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
                                    wxPaneInfo& pane,
                                    wxDockUIPartArray& uiparts,
                                    bool spacer_only)
-{        
+{
     wxDockUIPart part;
     wxSizerItem* sizer_item;
 
@@ -1081,7 +1350,7 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
     {
         if (pane.HasGripperTop())
             sizer_item = vert_pane_sizer ->Add(1, gripper_size, 0, wxEXPAND);
-       else
+        else
             sizer_item = horz_pane_sizer ->Add(gripper_size, 1, 0, wxEXPAND);
 
         part.type = wxDockUIPart::typeGripper;
@@ -1143,9 +1412,12 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
     {
         sizer_item = vert_pane_sizer->Add(1, 1, 1, wxEXPAND);
     }
-     else
+    else
     {
         sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND);
+        // Don't do this because it breaks the pane size in floating windows
+        // BIW: Right now commenting this out is causing problems with
+        // an mdi client window as the center pane.
         vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
     }
 
@@ -1162,7 +1434,7 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
     // determine if the pane should have a minimum size; if the pane is
     // non-resizable (fixed) then we must set a minimum size. Alternitavely,
     // if the pane.min_size is set, we must use that value as well
-    
+
     wxSize min_size = pane.min_size;
     if (pane.IsFixed())
     {
@@ -1172,7 +1444,7 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
             pane_proportion = 0;
         }
     }
-    
+
     if (min_size != wxDefaultSize)
     {
         vert_pane_sizer->SetItemMinSize(
@@ -1202,7 +1474,7 @@ void wxFrameManager::LayoutAddPane(wxSizer* cont,
         part.sizer_item = sizer_item;
         uiparts.Add(part);
     }
-     else
+    else
     {
         sizer_item = cont->Add(horz_pane_sizer, pane_proportion, wxEXPAND);
     }
@@ -1244,7 +1516,7 @@ void wxFrameManager::LayoutAddDock(wxSizer* cont,
     if (dock.fixed)
     {
         wxArrayInt pane_positions, pane_sizes;
-        
+
         // figure out the real pane positions we will
         // use, without modifying the each pane's pane_pos member
         GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
@@ -1292,7 +1564,7 @@ void wxFrameManager::LayoutAddDock(wxSizer* cont,
         part.sizer_item = sizer_item;
         uiparts.Add(part);
     }
-     else
+    else
     {
         for (pane_i = 0; pane_i < pane_count; ++pane_i)
         {
@@ -1365,12 +1637,12 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
     int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
     wxSize cli_size = m_frame->GetClientSize();
     int i, dock_count, pane_count;
-    
+
 
     // empty all docks out
     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
         docks.Item(i).panes.Empty();
-    
+
     // iterate through all known panes, filing each
     // of them into the appropriate dock. If the
     // pane does not exist in the dock, add it
@@ -1405,7 +1677,7 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
             RemovePaneFromDocks(docks, p, dock);
 
             // pane needs to be added to the dock,
-            // if it doesn't already exist 
+            // if it doesn't already exist
             if (!FindPaneInDock(*dock, p.window))
                 dock->panes.Add(&p);
         }
@@ -1429,7 +1701,7 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
     {
         wxDockInfo& dock = docks.Item(i);
         int j, dock_pane_count = dock.panes.GetCount();
-        
+
         // sort the dock pane array by the pane's
         // dock position (dock_pos), in ascending order
         dock.panes.Sort(PaneSortFunc);
@@ -1447,13 +1719,13 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
                     pane_size = pane.min_size;
                 if (pane_size == wxDefaultSize)
                     pane_size = pane.window->GetSize();
-                
+
                 if (dock.IsHorizontal())
                     size = wxMax(pane_size.y, size);
                      else
                     size = wxMax(pane_size.x, size);
             }
-            
+
             // add space for the border (two times), but only
             // if at least one pane inside the dock has a pane border
             for (j = 0; j < dock_pane_count; ++j)
@@ -1516,15 +1788,15 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
                 }
             }
         }
-        
+
         if (plus_border)
             dock_min_size += (pane_border_size*2);
         if (plus_caption && dock.IsHorizontal())
             dock_min_size += (caption_size);
-           
+
         dock.min_size = dock_min_size;
-        
-        
+
+
         // if the pane's current size is less than it's
         // minimum, increase the dock's size to it's minimum
         if (dock.size < dock.min_size)
@@ -1568,7 +1840,7 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
         {
             wxArrayInt pane_positions, pane_sizes;
             GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
-            
+
             int offset = 0;
             for (j = 0; j < dock_pane_count; ++j)
             {
@@ -1585,12 +1857,12 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
             }
         }
     }
-    
+
     // discover the maximum dock layer
     int max_layer = 0;
     for (i = 0; i < dock_count; ++i)
         max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
+
 
     // clear out uiparts
     uiparts.Empty();
@@ -1629,10 +1901,10 @@ wxSizer* wxFrameManager::LayoutAll(wxPaneInfoArray& panes,
                 LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
         }
 
-        
+
         // fill out the middle layer (which consists
         // of left docks, content area and right docks)
-        
+
         middle = new wxBoxSizer(wxHORIZONTAL);
 
         // find any left docks in this layer
@@ -1741,11 +2013,13 @@ void wxFrameManager::Update()
         {
             // because the pane is no longer in a floating, we need to
             // reparent it to m_frame and destroy the floating frame
-            
+
             // reduce flicker
             p.window->SetSize(1,1);
-            p.frame->Show(false);
-                       
+
+            if (p.frame->IsShown())
+                p.frame->Show(false);
+
             // reparent to m_frame and destroy the pane
             p.window->Reparent(m_frame);
             p.frame->SetSizer(NULL);
@@ -1770,27 +2044,22 @@ void wxFrameManager::Update()
             {
                 // we need to create a frame for this
                 // pane, which has recently been floated
-                wxFloatingPane* frame = new wxFloatingPane(m_frame,
-                                                  this, -1,
-                                                  p.floating_pos,
-                                                  p.floating_size);
-                                
-                // on MSW, if the owner desires transparent dragging, and
+                wxFloatingPane* frame = CreateFloatingFrame(m_frame, p);
+
+#if wxCHECK_VERSION(2,7,0)
+                // on MSW and Mac, if the owner desires transparent dragging, and
                 // the dragging is happening right now, then the floating
-                // window should have this style by default                  
-                #ifdef __WXMSW__
+                // window should have this style by default
                 if (m_action == actionDragFloatingPane &&
                     (m_flags & wxAUI_MGR_TRANSPARENT_DRAG))
-                        MakeWindowTransparent(frame, 150);
-                #endif
-                
+                        frame->SetTransparent(150);
+#endif
+
                 frame->SetPaneWindow(p);
                 p.frame = frame;
 
-                if (p.IsShown())
-                {
+                if (p.IsShown() && !frame->IsShown())
                     frame->Show();
-                }
             }
              else
             {
@@ -1799,16 +2068,19 @@ void wxFrameManager::Update()
                 if (p.frame->GetPosition() != p.floating_pos)
                 {
                     p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
-                                     -1, -1, wxSIZE_USE_EXISTING);
+                                     wxDefaultCoord, wxDefaultCoord,
+                                     wxSIZE_USE_EXISTING);
                     //p.frame->Move(p.floating_pos.x, p.floating_pos.y);
                 }
 
-                 p.frame->Show(p.IsShown());
+                if (p.frame->IsShown() != p.IsShown())
+                    p.frame->Show(p.IsShown());
             }
         }
          else
         {
-            p.window->Show(p.IsShown());
+            if (p.window->IsShown() != p.IsShown())
+                p.window->Show(p.IsShown());
         }
 
         // if "active panes" are no longer allowed, clear
@@ -1863,9 +2135,9 @@ void wxFrameManager::Update()
 
 
     Repaint();
-    
+
     // set frame's minimum size
-    
+
 /*
     // N.B. More work needs to be done on frame minimum sizes;
     // this is some intresting code that imposes the minimum size,
@@ -1877,9 +2149,9 @@ void wxFrameManager::Update()
 
     wxSize minframe_size(min_size.x+frame_size.x-client_size.x,
                          min_size.y+frame_size.y-client_size.y );
-                         
+
     m_frame->SetMinSize(minframe_size);
+
     if (frame_size.x < minframe_size.x ||
         frame_size.y < minframe_size.y)
             sizer->Fit(m_frame);
@@ -1895,7 +2167,7 @@ void wxFrameManager::Update()
 void wxFrameManager::DoFrameLayout()
 {
     m_frame->Layout();
-    
+
     int i, part_count;
     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
     {
@@ -1906,7 +2178,7 @@ void wxFrameManager::DoFrameLayout()
         //    part.rect = wxRect(part.sizer_item->GetPosition(),
         //                       part.sizer_item->GetSize());
         // this worked quite well, with one exception: the mdi
-        // client window had a "deferred" size variable 
+        // client window had a "deferred" size variable
         // that returned the wrong size.  It looks like
         // a bug in wx, because the former size of the window
         // was being returned.  So, we will retrieve the part's
@@ -1976,7 +2248,7 @@ int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test)
 {
     // the only way to accurately calculate the dock's
     // offset is to actually run a theoretical layout
-    
+
     int i, part_count, dock_count;
     wxDockInfoArray docks;
     wxPaneInfoArray panes;
@@ -1997,9 +2269,9 @@ int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test)
         if (part.type == wxDockUIPart::typeDock)
             part.dock->rect = part.rect;
     }
-    
+
     delete sizer;
-    
+
     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
     {
         wxDockInfo& dock = docks.Item(i);
@@ -2022,7 +2294,7 @@ int wxFrameManager::GetDockPixelOffset(wxPaneInfo& test)
 // if a dock operation is allowed, the new dock position is copied into
 // the target info.  If the operation was allowed, the function returns true.
 
-static bool ProcessDockResult(wxPaneInfo& target,
+bool wxFrameManager::ProcessDockResult(wxPaneInfo& target,
                               const wxPaneInfo& new_pos)
 {
     bool allowed = false;
@@ -2067,7 +2339,7 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
 
     // The result should always be shown
     drop.Show();
-    
+
 
     // Check to see if the pane has been dragged outside of the window
     // (or near to the outside of the window), if so, dock it along the edge
@@ -2076,49 +2348,38 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
     int layer_insert_offset = auiLayerInsertOffset;
     if (target.IsToolbar())
         layer_insert_offset = 0;
-    
+
     if (pt.x < layer_insert_offset &&
         pt.x > layer_insert_offset-auiLayerInsertPixels)
     {
-        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
-                                    GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
-                                    GetMaxLayer(docks, wxAUI_DOCK_TOP)) + 1;       
         drop.Dock().Left().
-             Layer(new_layer).
              Row(0).
              Position(pt.y - GetDockPixelOffset(drop) - offset.y);
         return ProcessDockResult(target, drop);
     }
-     else if (pt.y < layer_insert_offset &&
-              pt.y > layer_insert_offset-auiLayerInsertPixels)
+    else if (pt.y < layer_insert_offset &&
+             pt.y > layer_insert_offset-auiLayerInsertPixels)
     {
-        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
-                                    GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
-                                    GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
         drop.Dock().Top().
-             Layer(new_layer).
              Row(0).
              Position(pt.x - GetDockPixelOffset(drop) - offset.x);
         return ProcessDockResult(target, drop);
     }
-     else if (pt.x >= cli_size.x - layer_insert_offset &&
-              pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
+    else if (pt.x >= cli_size.x - layer_insert_offset &&
+             pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
     {
-        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
-                                    GetMaxLayer(docks, wxAUI_DOCK_TOP)),
-                                    GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)) + 1;    
         drop.Dock().Right().
-             Layer(new_layer).
              Row(0).
              Position(pt.y - GetDockPixelOffset(drop) - offset.y);
         return ProcessDockResult(target, drop);
     }
-     else if (pt.y >= cli_size.y - layer_insert_offset &&
-              pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
+    else if (pt.y >= cli_size.y - layer_insert_offset &&
+             pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
     {
-        int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
-                                    GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
-                                    GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
+        int new_layer = wxMax( wxMax( GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
+                                      GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
+                                      GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
+
         drop.Dock().Bottom().
              Layer(new_layer).
              Row(0).
@@ -2126,7 +2387,6 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
         return ProcessDockResult(target, drop);
     }
 
-
     wxDockUIPart* part = HitTest(pt.x, pt.y);
 
 
@@ -2134,7 +2394,6 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
     {
         if (!part || !part->dock)
             return false;
-        
 
         // calculate the offset from where the dock begins
         // to the point where the user dropped the pane
@@ -2150,17 +2409,40 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
         // should float if being dragged over center pane windows
         if (!part->dock->fixed || part->dock->dock_direction == wxAUI_DOCK_CENTER)
         {
-            if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
+            if (m_last_rect.IsEmpty() || m_last_rect.Contains(pt.x, pt.y ))
+            {
+                m_skipping = true;
+            }
+            else
+            {
+                if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
                    (drop.IsFloatable() ||
                     (part->dock->dock_direction != wxAUI_DOCK_CENTER &&
                      part->dock->dock_direction != wxAUI_DOCK_NONE)))
-            {
-                drop.Float();
+                {
+                    drop.Float();
+                }
+
+                m_skipping = false;
+
+                return ProcessDockResult(target, drop);
             }
-            
+
+            drop.Position(pt.x - GetDockPixelOffset(drop) - offset.x);
+
             return ProcessDockResult(target, drop);
         }
-        
+        else
+        {
+            m_skipping = false;
+        }
+
+        if (!m_skipping)
+        {
+            m_last_rect = part->dock->rect;
+            m_last_rect.Inflate( 15, 15 );
+        }
+
         drop.Dock().
              Direction(part->dock->dock_direction).
              Layer(part->dock->dock_layer).
@@ -2168,26 +2450,49 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
              Position(dock_drop_offset);
 
         if ((
-            ((pt.y < part->dock->rect.y + 2) && part->dock->IsHorizontal()) ||
-            ((pt.x < part->dock->rect.x + 2) && part->dock->IsVertical())
+            ((pt.y < part->dock->rect.y + 1) && part->dock->IsHorizontal()) ||
+            ((pt.x < part->dock->rect.x + 1) && part->dock->IsVertical())
             ) && part->dock->panes.GetCount() > 1)
         {
-            int row = drop.dock_row;
-            DoInsertDockRow(panes, part->dock->dock_direction,
-                            part->dock->dock_layer,
-                            part->dock->dock_row);
-            drop.dock_row = row;
+            if ((part->dock->dock_direction == wxAUI_DOCK_TOP) ||
+                (part->dock->dock_direction == wxAUI_DOCK_LEFT))
+            {
+                int row = drop.dock_row;
+                DoInsertDockRow(panes, part->dock->dock_direction,
+                                part->dock->dock_layer,
+                                part->dock->dock_row);
+                drop.dock_row = row;
+            }
+            else
+            {
+                DoInsertDockRow(panes, part->dock->dock_direction,
+                                part->dock->dock_layer,
+                                part->dock->dock_row+1);
+                drop.dock_row = part->dock->dock_row+1;
+            }
         }
-        
+
         if ((
             ((pt.y > part->dock->rect.y + part->dock->rect.height - 2 ) && part->dock->IsHorizontal()) ||
             ((pt.x > part->dock->rect.x + part->dock->rect.width - 2 ) && part->dock->IsVertical())
             ) && part->dock->panes.GetCount() > 1)
         {
-            DoInsertDockRow(panes, part->dock->dock_direction,
-                            part->dock->dock_layer,
-                            part->dock->dock_row+1);
-            drop.dock_row = part->dock->dock_row+1;
+            if ((part->dock->dock_direction == wxAUI_DOCK_TOP) ||
+                (part->dock->dock_direction == wxAUI_DOCK_LEFT))
+            {
+                DoInsertDockRow(panes, part->dock->dock_direction,
+                                part->dock->dock_layer,
+                                part->dock->dock_row+1);
+                drop.dock_row = part->dock->dock_row+1;
+            }
+            else
+            {
+                int row = drop.dock_row;
+                DoInsertDockRow(panes, part->dock->dock_direction,
+                                part->dock->dock_layer,
+                                part->dock->dock_row);
+                drop.dock_row = row;
+            }
         }
 
         return ProcessDockResult(target, drop);
@@ -2195,7 +2500,7 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
 
 
 
-    
+
     if (!part)
         return false;
 
@@ -2266,12 +2571,12 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
         part = GetPanePart(part->pane->window);
         if (!part)
             return false;
-            
+
         bool insert_dock_row = false;
         int insert_row = part->pane->dock_row;
         int insert_dir = part->pane->dock_direction;
         int insert_layer = part->pane->dock_layer;
-        
+
         switch (part->pane->dock_direction)
         {
             case wxAUI_DOCK_TOP:
@@ -2307,7 +2612,7 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
                 if (new_row_pixels_y > (part->rect.height*20)/100)
                     new_row_pixels_y = (part->rect.height*20)/100;
 
-                
+
                 // determine if the mouse pointer is in a location that
                 // will cause a new row to be inserted.  The hot spot positions
                 // are along the borders of the center pane
@@ -2337,7 +2642,7 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
         }
 
         if (insert_dock_row)
-        { 
+        {
             DoInsertDockRow(panes, insert_dir, insert_layer, insert_row);
             drop.Dock().Direction(insert_dir).
                         Layer(insert_layer).
@@ -2345,25 +2650,25 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
                         Position(0);
             return ProcessDockResult(target, drop);
         }
-        
+
         // determine the mouse offset and the pane size, both in the
         // direction of the dock itself, and perpendicular to the dock
-        
+
         int offset, size;
-        
+
         if (part->orientation == wxVERTICAL)
         {
             offset = pt.y - part->rect.y;
-            size = part->rect.GetHeight(); 
+            size = part->rect.GetHeight();
         }
          else
         {
             offset = pt.x - part->rect.x;
             size = part->rect.GetWidth();
         }
-        
+
         int drop_position = part->pane->dock_pos;
-        
+
         // if we are in the top/left part of the pane,
         // insert the pane before the pane being hovered over
         if (offset <= size/2)
@@ -2402,143 +2707,140 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
 
 void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event))
 {
-#ifdef __WXMSW__
-    if (!m_hint_wnd || m_hint_fadeamt >= 50)
+    if (!m_hint_wnd || m_hint_fadeamt >= m_hint_fademax)
     {
         m_hint_fadetimer.Stop();
         return;
     }
-    
-    m_hint_fadeamt += 5;
-    MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt);
+
+    m_hint_fadeamt += 4;
+#if wxCHECK_VERSION(2,7,0)
+    m_hint_wnd->SetTransparent(m_hint_fadeamt);
+#else
+    if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
+        ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(m_hint_fadeamt);
 #endif
 }
 
 void wxFrameManager::ShowHint(const wxRect& rect)
 {
-    #ifdef __WXMSW__
-    
-    // First, determine if the operating system can handle transparency.
-    // Transparency is available on Win2000 and above
-    
-    static int os_type = -1;
-    static int ver_major = -1;
-    
-    if (os_type == -1)
-        os_type = ::wxGetOsVersion(&ver_major);
-
-    // If the transparent flag is set, and the OS supports it,
-    // go ahead and use a transparent hint
-    
-    if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 &&
-        os_type == wxWINDOWS_NT && ver_major >= 5)
+    if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0
+        && m_hint_wnd
+        // Finally, don't use a venetian blind effect if it's been specifically disabled
+        && !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) &&
+             (m_flags & wxAUI_MGR_DISABLE_VENETIAN_BLINDS))
+       )
     {
         if (m_last_hint == rect)
             return;
         m_last_hint = rect;
-        
-        int initial_fade = 50;
-        if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
-            initial_fade = 0;
-            
-        if (m_hint_wnd == NULL)
-        {
-            wxPoint pt = rect.GetPosition();
-            wxSize size = rect.GetSize();
-            m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, pt, size,
-                                     wxFRAME_TOOL_WINDOW |
-                                     wxFRAME_FLOAT_ON_PARENT |
-                                     wxFRAME_NO_TASKBAR |
-                                     wxNO_BORDER);
-
-            MakeWindowTransparent(m_hint_wnd, initial_fade);
-            m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
+
+        m_hint_fadeamt = m_hint_fademax;
+        if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
+            && !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) &&
+                 (m_flags & wxAUI_MGR_DISABLE_VENETIAN_BLINDS_FADE))
+            )
+            m_hint_fadeamt = 0;
+
+        m_hint_wnd->SetSize(rect);
+
+        if (! m_hint_wnd->IsShown())
             m_hint_wnd->Show();
 
-            // if we are dragging a floating pane, set the focus
-            // back to that floating pane (otherwise it becomes unfocused)
-            if (m_action == actionDragFloatingPane && m_action_window)
-                m_action_window->SetFocus();
+        // if we are dragging a floating pane, set the focus
+        // back to that floating pane (otherwise it becomes unfocused)
+        if (m_action == actionDragFloatingPane && m_action_window)
+            m_action_window->SetFocus();
 
-        }
-         else
-        {
-            wxPoint pt = rect.GetPosition();
-            wxSize size = rect.GetSize();
-            MakeWindowTransparent(m_hint_wnd, initial_fade);
-            m_hint_wnd->SetSize(pt.x, pt.y, rect.width, rect.height);
-        }
-        
-        if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
+#if wxCHECK_VERSION(2,7,0)
+        m_hint_wnd->SetTransparent(m_hint_fadeamt);
+#else
+        if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
+            ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(m_hint_fadeamt);
+#endif
+        m_hint_wnd->Raise();
+
+
+        if (m_hint_fadeamt != m_hint_fademax) //  Only fade if we need to
         {
             // start fade in timer
-            m_hint_fadeamt = 0;
             m_hint_fadetimer.SetOwner(this, 101);
             m_hint_fadetimer.Start(5);
         }
-        
-        return;
     }
-    #endif
 
-    if (m_last_hint != rect)
+    else  // Not using a transparent hint window...
     {
-        // remove the last hint rectangle
-        m_last_hint = rect;
-        m_frame->Refresh();
-        m_frame->Update();
-    }
-    
-    wxScreenDC screendc;
-    wxRegion clip(1, 1, 10000, 10000);
 
-    // clip all floating windows, so we don't draw over them
-    int i, pane_count;
-    for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
-    {
-        wxPaneInfo& pane = m_panes.Item(i);
+        if (m_last_hint != rect)
+        {
+            // remove the last hint rectangle
+            m_last_hint = rect;
+            m_frame->Refresh();
+            m_frame->Update();
+        }
 
-        if (pane.IsFloating() &&
-            pane.frame->IsShown())
+        wxScreenDC screendc;
+        wxRegion clip(1, 1, 10000, 10000);
+
+        // clip all floating windows, so we don't draw over them
+        int i, pane_count;
+        for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
         {
-            wxRect rect = pane.frame->GetRect();
-            #ifdef __WXGTK__
-            // wxGTK returns the client size, not the whole frame size
-            rect.width += 15;
-            rect.height += 35;
-            rect.Inflate(5);
-            #endif
+            wxPaneInfo& pane = m_panes.Item(i);
 
-            clip.Subtract(rect);
+            if (pane.IsFloating() &&
+                pane.frame->IsShown())
+            {
+                wxRect rect = pane.frame->GetRect();
+#ifdef __WXGTK__
+                // wxGTK returns the client size, not the whole frame size
+                rect.width += 15;
+                rect.height += 35;
+                rect.Inflate(5);
+#endif
+
+                clip.Subtract(rect);
+            }
         }
-    }
 
-    screendc.SetClippingRegion(clip);
+        // As we can only hide the hint by redrawing the managed window, we
+        // need to clip the region to the managed window too or we get
+        // nasty redrawn problems.
+        clip.Intersect(m_frame->GetRect());
 
-    wxBitmap stipple = wxPaneCreateStippleBitmap();
-    wxBrush brush(stipple);
-    screendc.SetBrush(brush);
-    screendc.SetPen(*wxTRANSPARENT_PEN);
+        screendc.SetClippingRegion(clip);
+
+        wxBitmap stipple = wxPaneCreateStippleBitmap();
+        wxBrush brush(stipple);
+        screendc.SetBrush(brush);
+        screendc.SetPen(*wxTRANSPARENT_PEN);
 
-    screendc.DrawRectangle(rect.x, rect.y, 5, rect.height);
-    screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5);
-    screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height);
-    screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5);
+        screendc.DrawRectangle(rect.x, rect.y, 5, rect.height);
+        screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5);
+        screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height);
+        screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5);
+    }
 }
 
 void wxFrameManager::HideHint()
-{   
-    // hides a transparent window hint (currently wxMSW only)
-    #ifdef __WXMSW__
+{
+    // hides a transparent window hint, if there is one
     if (m_hint_wnd)
     {
-        MakeWindowTransparent(m_hint_wnd, 0);
+        if (m_hint_wnd->IsShown())
+            m_hint_wnd->Show(false);
+#if wxCHECK_VERSION(2,7,0)
+        m_hint_wnd->SetTransparent(0);
+#else
+        if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
+        ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(0);
+#endif
         m_hint_fadetimer.Stop();
         m_last_hint = wxRect();
         return;
     }
-    #endif
-    
+
     // hides a painted hint by redrawing the frame window
     if (!m_last_hint.IsEmpty())
     {
@@ -2573,6 +2875,7 @@ void wxFrameManager::DrawHintRect(wxWindow* pane_window,
     wxDockUIPartArray uiparts;
     wxPaneInfo hint = GetPane(pane_window);
     hint.name = wxT("__HINT__");
+    hint.Show();
 
     if (!hint.IsOk())
         return;
@@ -2618,7 +2921,7 @@ void wxFrameManager::DrawHintRect(wxWindow* pane_window,
             break;
         }
     }
-    
+
     delete sizer;
 
     if (rect.IsEmpty())
@@ -2637,22 +2940,59 @@ void wxFrameManager::OnFloatingPaneMoveStart(wxWindow* wnd)
     // try to find the pane
     wxPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
-    
-    #ifdef __WXMSW__
+
+#if wxCHECK_VERSION(2,7,0)
     if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
-        MakeWindowTransparent(pane.frame, 150);
-    #endif
+        pane.frame->SetTransparent(150);
+#endif
 }
 
-void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
+void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir)
 {
     // try to find the pane
     wxPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
-    
+
     wxPoint pt = ::wxGetMousePosition();
+
+#if 0
+    // Adapt pt to direction
+    if (dir == wxNORTH)
+    {
+        // move to pane's upper border
+        wxPoint pos( 0,0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.y = pos.y;
+        // and some more pixels for the title bar
+        pt.y -= 5;
+    } else
+    if (dir == wxWEST)
+    {
+        // move to pane's left border
+        wxPoint pos( 0,0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.x = pos.x;
+    } else
+    if (dir == wxEAST)
+    {
+        // move to pane's right border
+        wxPoint pos( wnd->GetSize().x, 0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.x = pos.x;
+    } else
+    if (dir == wxSOUTH)
+    {
+        // move to pane's bottom border
+        wxPoint pos( 0, wnd->GetSize().y );
+        pos = wnd->ClientToScreen( pos );
+        pt.y = pos.y;
+    }
+#else
+    wxUnusedVar(dir);
+#endif
+
     wxPoint client_pt = m_frame->ScreenToClient(pt);
-    
+
     // calculate the offset from the upper left-hand corner
     // of the frame to the mouse pointer
     wxPoint frame_pos = pane.frame->GetPosition();
@@ -2667,7 +3007,7 @@ void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
             wxPaneInfoArray panes;
             wxDockUIPartArray uiparts;
             wxPaneInfo hint = pane;
-            
+
             CopyDocksAndPanes(docks, panes, m_docks, m_panes);
 
             // find out where the new pane would be
@@ -2675,14 +3015,14 @@ void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
                 return;
             if (hint.IsFloating())
                 return;
-            
+
             pane = hint;
             m_action = actionDragToolbarPane;
             m_action_window = pane.window;
-            
+
             Update();
         }
-        
+
         return;
     }
 
@@ -2698,59 +3038,92 @@ void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd)
 
     DrawHintRect(wnd, client_pt, action_offset);
 
-    #ifdef __WXGTK__
+#ifdef __WXGTK__
     // this cleans up some screen artifacts that are caused on GTK because
     // we aren't getting the exact size of the window (see comment
     // in DrawHintRect)
     //Refresh();
-    #endif
-    
-    
+#endif
+
+
     // reduces flicker
     m_frame->Update();
 }
 
-void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd)
+void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir)
 {
     // try to find the pane
     wxPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
-    
+
     wxPoint pt = ::wxGetMousePosition();
+
+#if 0
+    // Adapt pt to direction
+    if (dir == wxNORTH)
+    {
+        // move to pane's upper border
+        wxPoint pos( 0,0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.y = pos.y;
+        // and some more pixels for the title bar
+        pt.y -= 10;
+    } else
+    if (dir == wxWEST)
+    {
+        // move to pane's left border
+        wxPoint pos( 0,0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.x = pos.x;
+    } else
+    if (dir == wxEAST)
+    {
+        // move to pane's right border
+        wxPoint pos( wnd->GetSize().x, 0 );
+        pos = wnd->ClientToScreen( pos );
+        pt.x = pos.x;
+    } else
+    if (dir == wxSOUTH)
+    {
+        // move to pane's bottom border
+        wxPoint pos( 0, wnd->GetSize().y );
+        pos = wnd->ClientToScreen( pos );
+        pt.y = pos.y;
+    }
+#else
+    wxUnusedVar(dir);
+#endif
+
     wxPoint client_pt = m_frame->ScreenToClient(pt);
-    
+
     // calculate the offset from the upper left-hand corner
     // of the frame to the mouse pointer
     wxPoint frame_pos = pane.frame->GetPosition();
     wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
-    
+
 
     // if a key modifier is pressed while dragging the frame,
     // don't dock the window
-    if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT))
+    if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT))
     {
-        HideHint();
-        return;
+        // do the drop calculation
+        DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
     }
 
-
-    // do the drop calculation
-    DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
-
     // if the pane is still floating, update it's floating
     // position (that we store)
     if (pane.IsFloating())
     {
         pane.floating_pos = pane.frame->GetPosition();
-        
-        #ifdef __WXMSW__
+
+#if wxCHECK_VERSION(2,7,0)
         if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
-            MakeWindowTransparent(pane.frame, 255);
-        #endif
+            pane.frame->SetTransparent(255);
+#endif
     }
-        
+
     Update();
-    
+
     HideHint();
 }
 
@@ -2759,43 +3132,57 @@ void wxFrameManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size)
     // try to find the pane
     wxPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
-    
+
     pane.floating_size = size;
 }
 
-void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd)
+
+void wxFrameManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt)
 {
     // try to find the pane
     wxPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
 
-    // reparent the pane window back to us and
-    // prepare the frame window for destruction
-    pane.window->Show(false);
-    pane.window->Reparent(m_frame);
-    pane.frame = NULL;
-    pane.Hide();
+
+    // fire pane close event
+    wxFrameManagerEvent e(wxEVT_AUI_PANECLOSE);
+    e.SetPane(&pane);
+    e.SetCanVeto(evt.CanVeto());
+    ProcessMgrEvent(e);
+
+    if (e.GetVeto())
+    {
+        evt.Veto();
+        return;
+    }
+     else 
+    {
+        ClosePane(pane);
+    }
 }
 
+
+
 void wxFrameManager::OnFloatingPaneActivated(wxWindow* wnd)
 {
     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
     {
         // try to find the pane
-        wxPaneInfo& pane = GetPane(wnd);
-        wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
+        wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found"));
 
         SetActivePane(m_panes, wnd);
         Repaint();
     }
 }
 
-// Render() draws all of the pane captions, sashes,
+// OnRender() draws all of the pane captions, sashes,
 // backgrounds, captions, grippers, pane borders and buttons.
 // It renders the entire user interface.
 
-void wxFrameManager::Render(wxDC* dc)
+void wxFrameManager::OnRender(wxFrameManagerEvent& evt)
 {
+    wxDC* dc = evt.GetDC();
+
 #ifdef __WXMAC__
     dc->Clear() ;
 #endif
@@ -2808,33 +3195,47 @@ void wxFrameManager::Render(wxDC* dc)
         // don't draw hidden pane items
         if (part.sizer_item && !part.sizer_item->IsShown())
             continue;
-        
+
         switch (part.type)
         {
             case wxDockUIPart::typeDockSizer:
             case wxDockUIPart::typePaneSizer:
-                m_art->DrawSash(*dc, part.orientation, part.rect);
+                m_art->DrawSash(*dc, m_frame, part.orientation, part.rect);
                 break;
             case wxDockUIPart::typeBackground:
-                m_art->DrawBackground(*dc, part.orientation, part.rect);
+                m_art->DrawBackground(*dc, m_frame, part.orientation, part.rect);
                 break;
             case wxDockUIPart::typeCaption:
-                m_art->DrawCaption(*dc, part.pane->caption, part.rect, *part.pane);
+                m_art->DrawCaption(*dc, m_frame, part.pane->caption, part.rect, *part.pane);
                 break;
             case wxDockUIPart::typeGripper:
-                m_art->DrawGripper(*dc, part.rect, *part.pane);
-                break;     
+                m_art->DrawGripper(*dc, m_frame, part.rect, *part.pane);
+                break;
             case wxDockUIPart::typePaneBorder:
-                m_art->DrawBorder(*dc, part.rect, *part.pane);
+                m_art->DrawBorder(*dc, m_frame, part.rect, *part.pane);
                 break;
             case wxDockUIPart::typePaneButton:
-                m_art->DrawPaneButton(*dc, part.button->button_id,
+                m_art->DrawPaneButton(*dc, m_frame, part.button->button_id,
                         wxAUI_BUTTON_STATE_NORMAL, part.rect, *part.pane);
                 break;
         }
     }
 }
 
+
+// Render() fire a render event, which is normally handled by
+// wxFrameManager::OnRender().  This allows the render function to
+// be overridden via the render event.  This can be useful for paintin
+// custom graphics in the main window. Default behavior can be
+// invoked in the overridden function by calling OnRender()
+
+void wxFrameManager::Render(wxDC* dc)
+{
+    wxFrameManagerEvent e(wxEVT_AUI_RENDER);
+    e.SetDC(dc);
+    ProcessMgrEvent(e);
+}
+
 void wxFrameManager::Repaint(wxDC* dc)
 {
 #ifdef __WXMAC__
@@ -2887,13 +3288,14 @@ void wxFrameManager::OnEraseBackground(wxEraseEvent& event)
 #endif
 }
 
-void wxFrameManager::OnSize(wxSizeEvent& WXUNUSED(event))
+void wxFrameManager::OnSize(wxSizeEvent& event)
 {
     if (m_frame)
     {
         DoFrameLayout();
         Repaint();
     }
+    event.Skip();
 }
 
 
@@ -2929,7 +3331,7 @@ void wxFrameManager::OnSetCursor(wxSetCursorEvent& event)
             cursor = wxCursor(wxCURSOR_SIZING);
         }
     }
-    
+
     event.SetCursor(cursor);
 }
 
@@ -2941,7 +3343,7 @@ void wxFrameManager::UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
     wxDockUIPart* hit_test = HitTest(event.GetX(), event.GetY());
 
     int state = wxAUI_BUTTON_STATE_NORMAL;
-    
+
     if (hit_test == button_ui_part)
     {
         if (event.LeftDown())
@@ -2949,7 +3351,7 @@ void wxFrameManager::UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
              else
             state = wxAUI_BUTTON_STATE_HOVER;
     }
-     else
+    else
     {
         if (event.LeftDown())
             state = wxAUI_BUTTON_STATE_HOVER;
@@ -2964,7 +3366,7 @@ void wxFrameManager::UpdateButtonOnScreen(wxDockUIPart* button_ui_part,
     if (pt.x != 0 || pt.y != 0)
         cdc.SetDeviceOrigin(pt.x, pt.y);
 
-    m_art->DrawPaneButton(cdc,
+    m_art->DrawPaneButton(cdc, m_frame,
               button_ui_part->button->button_id,
               state,
               button_ui_part->rect,
@@ -3129,13 +3531,13 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
                 wxPaneInfo& p = *dock.panes.Item(i);
                 if (p.window == pane.window)
                     pane_position = i;
-                
+
                 // while we're at it, subtract the pane sash
                 // width from the dock width, because this would
                 // skew our proportion calculations
                 if (i > 0)
                     dock_pixels -= sash_size;
-             
+
                 // also, the whole size (including decorations) of
                 // all fixed panes must also be subtracted, because they
                 // are not part of the proportion calculation
@@ -3151,7 +3553,7 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
                     total_proportion += p.dock_proportion;
                 }
             }
-            
+
             // find a pane in our dock to 'steal' space from or to 'give'
             // space to -- this is essentially what is done when a pane is
             // resized; the pane should usually be the first non-fixed pane
@@ -3166,12 +3568,12 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
                     break;
                 }
             }
-            
-            
+
+
             // demand that the pane being resized is found in this dock
             // (this assert really never should be raised)
             wxASSERT_MSG(pane_position != -1, wxT("Pane not found in dock"));
-            
+
             // prevent division by zero
             if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1)
             {
@@ -3181,10 +3583,10 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
 
             // calculate the new proportion of the pane
             int new_proportion = (new_pixsize*total_proportion)/dock_pixels;
-            
+
             // default minimum size
             int min_size = 0;
-            
+
             // check against the pane's minimum size, if specified. please note
             // that this is not enough to ensure that the minimum size will
             // not be violated, because the whole frame might later be shrunk,
@@ -3192,7 +3594,7 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
             if (pane.min_size.IsFullySpecified())
             {
                 min_size = 0;
-                
+
                 if (pane.HasBorder())
                     min_size += (pane_border_size*2);
 
@@ -3208,8 +3610,8 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
                     min_size += pane.min_size.x;
                 }
             }
-            
-            
+
+
             // for some reason, an arithmatic error somewhere is causing
             // the proportion calculations to always be off by 1 pixel;
             // for now we will add the 1 pixel on, but we really should
@@ -3217,33 +3619,33 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
             min_size++;
 
             int min_proportion = (min_size*total_proportion)/dock_pixels;
-                
+
             if (new_proportion < min_proportion)
                 new_proportion = min_proportion;
-            
-            
-            
+
+
+
             int prop_diff = new_proportion - pane.dock_proportion;
 
             // borrow the space from our neighbor pane to the
             // right or bottom (depending on orientation)
             dock.panes.Item(borrow_pane)->dock_proportion -= prop_diff;
             pane.dock_proportion = new_proportion;
-            
+
             // repaint
             Update();
             Repaint(NULL);
         }
     }
-     else if (m_action == actionClickButton)
+    else if (m_action == actionClickButton)
     {
         m_hover_button = NULL;
-        m_frame->ReleaseMouse();     
+        m_frame->ReleaseMouse();
         UpdateButtonOnScreen(m_action_part, event);
 
         // make sure we're still over the item that was originally clicked
         if (m_action_part == HitTest(event.GetX(), event.GetY()))
-        { 
+        {
             // fire button-click event
             wxFrameManagerEvent e(wxEVT_AUI_PANEBUTTON);
             e.SetPane(m_action_part->pane);
@@ -3251,21 +3653,21 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
             ProcessMgrEvent(e);
         }
     }
-     else if (m_action == actionClickCaption)
+    else if (m_action == actionClickCaption)
     {
         m_frame->ReleaseMouse();
     }
-     else if (m_action == actionDragFloatingPane)
+    else if (m_action == actionDragFloatingPane)
     {
         m_frame->ReleaseMouse();
     }
-     else if (m_action == actionDragToolbarPane)
+    else if (m_action == actionDragToolbarPane)
     {
         m_frame->ReleaseMouse();
 
         wxPaneInfo& pane = GetPane(m_action_window);
         wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
-    
+
         // save the new positions
         wxDockInfoPtrArray docks;
         FindDocks(m_docks, pane.dock_direction,
@@ -3273,19 +3675,19 @@ void wxFrameManager::OnLeftUp(wxMouseEvent& event)
         if (docks.GetCount() == 1)
         {
             wxDockInfo& dock = *docks.Item(0);
-            
+
             wxArrayInt pane_positions, pane_sizes;
             GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
-            
+
             int i, dock_pane_count = dock.panes.GetCount();
             for (i = 0; i < dock_pane_count; ++i)
                 dock.panes.Item(i)->dock_pos = pane_positions[i];
         }
-        
+
         pane.state &= ~wxPaneInfo::actionPane;
         Update();
     }
-     else
+    else
     {
         event.Skip();
     }
@@ -3302,13 +3704,13 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
     // sure that only real mouse moves will get anywhere in this method;
     // this appears to be a bug somewhere, and I don't know where the
     // mouse move event is being generated.  only verified on MSW
-    
+
     wxPoint mouse_pos = event.GetPosition();
     if (m_last_mouse_move == mouse_pos)
         return;
     m_last_mouse_move = mouse_pos;
 
-    
+
     if (m_action == actionResize)
     {
         wxPoint pos = m_action_part->rect.GetPosition();
@@ -3326,23 +3728,23 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
         DrawResizeHint(dc, rect);
         m_action_hintrect = rect;
     }
-     else if (m_action == actionClickCaption)
+    else if (m_action == actionClickCaption)
     {
         int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
         int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
-        
+
         // caption has been clicked.  we need to check if the mouse
         // is now being dragged. if it is, we need to change the
         // mouse action to 'drag'
         if (abs(event.m_x - m_action_start.x) > drag_x_threshold ||
-            abs(event.m_y - m_action_start.y) > drag_y_threshold)     
+            abs(event.m_y - m_action_start.y) > drag_y_threshold)
         {
             wxPaneInfo* pane_info = m_action_part->pane;
 
             if (!pane_info->IsToolbar())
             {
                 if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
-                    pane_info->IsFloatable()) 
+                    pane_info->IsFloatable())
                 {
                     m_action = actionDragFloatingPane;
 
@@ -3355,7 +3757,7 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
                     Update();
 
                     m_action_window = pane_info->frame;
-                    
+
                     // action offset is used here to make it feel "natural" to the user
                     // to drag a docked pane and suddenly have it become a floating frame.
                     // Sometimes, however, the offset where the user clicked on the docked
@@ -3373,13 +3775,13 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
             }
         }
     }
-     else if (m_action == actionDragFloatingPane)
+    else if (m_action == actionDragFloatingPane)
     {
         wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
         m_action_window->Move(pt.x - m_action_offset.x,
                              pt.y - m_action_offset.y);
     }
-     else if (m_action == actionDragToolbarPane)
+    else if (m_action == actionDragToolbarPane)
     {
         wxPaneInfo& pane = GetPane(m_action_window);
         wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
@@ -3388,7 +3790,7 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
 
         wxPoint pt = event.GetPosition();
         DoDrop(m_docks, m_panes, pane, pt, m_action_offset);
-        
+
         // if DoDrop() decided to float the pane, set up
         // the floating pane's initial position
         if (pane.IsFloating())
@@ -3397,13 +3799,13 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
             pane.floating_pos = wxPoint(pt.x - m_action_offset.x,
                                         pt.y - m_action_offset.y);
         }
-        
+
         // this will do the actiual move operation;
         // in the case that the pane has been floated,
         // this call will create the floating pane
         // and do the reparenting
         Update();
-        
+
         // if the pane has been floated, change the mouse
         // action actionDragFloatingPane so that subsequent
         // EVT_MOTION() events will move the floating pane
@@ -3413,8 +3815,8 @@ void wxFrameManager::OnMotion(wxMouseEvent& event)
             m_action = actionDragFloatingPane;
             m_action_window = pane.frame;
         }
-    } 
-     else
+    }
+    else
     {
         wxDockUIPart* part = HitTest(event.GetX(), event.GetY());
         if (part && part->type == wxDockUIPart::typePaneButton)
@@ -3457,8 +3859,8 @@ void wxFrameManager::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
 
 void wxFrameManager::OnChildFocus(wxChildFocusEvent& event)
 {
-    // when a child pane has it's focus set, we should change the 
-    // pane's active state to reflect this. (this is only true if 
+    // when a child pane has it's focus set, we should change the
+    // pane's active state to reflect this. (this is only true if
     // active panes are allowed by the owner)
     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
     {
@@ -3468,21 +3870,33 @@ void wxFrameManager::OnChildFocus(wxChildFocusEvent& event)
             m_frame->Refresh();
         }
     }
+
+    event.Skip();
 }
 
 
 // OnPaneButton() is an event handler that is called
 // when a pane button has been pressed.
-void wxFrameManager::OnPaneButton(wxFrameManagerEvent& event)
+void wxFrameManager::OnPaneButton(wxFrameManagerEvent& evt)
 {
-    wxPaneInfo& pane = *(event.pane);
-    
-    if (event.button == wxPaneInfo::buttonClose)
+    wxASSERT_MSG(evt.pane, wxT("Pane Info passed to wxFrameManager::OnPaneButton must be non-null"));
+
+    wxPaneInfo& pane = *(evt.pane);
+
+    if (evt.button == wxPaneInfo::buttonClose)
     {
-        pane.Hide();
-        Update();
+        // fire pane close event
+        wxFrameManagerEvent e(wxEVT_AUI_PANECLOSE);
+        e.SetPane(evt.pane);
+        ProcessMgrEvent(e);
+
+        if (!e.GetVeto())
+        {
+            ClosePane(pane);
+            Update();
+        }
     }
-     else if (event.button == wxPaneInfo::buttonPin)
+     else if (evt.button == wxPaneInfo::buttonPin)
     {
         if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
             pane.IsFloatable())