Kirix Support Forums

wxEVT_MOUSE_CAPTURE_LOST??

Please post all general questions, comments, bug reports, and any other wxAUI feedback here.

wxEVT_MOUSE_CAPTURE_LOST??

Postby mikael.delsol on Tue Apr 03, 2007 10:19 am

Hi,
I overrided wxAuiManager, Manager, in order to use my own wxAuiFloatingFrame class.
So I overrided these methods :
Code: Select all
virtual wxAuiFloatingFrame* CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p);
void OnLeftDown(wxMouseEvent& evt);
void OnLeftUp(wxMouseEvent& evt);
void OnFindManager(wxAuiManagerEvent& evt);
void Update();

Moreover, I declared the methods with their events :
Code: Select all
BEGIN_EVENT_TABLE(Manager, wxAuiManager)
    EVT_LEFT_DOWN(Manager::OnLeftDown)
    EVT_LEFT_UP(Manager::OnLeftUp)
    EVT_AUI_FIND_MANAGER(Manager::OnFindManager)
END_EVENT_TABLE()

Firstly, I only copied the source code of each original method to test my Manager and when I move a pane added to the main window using my Manager, this error occurs:
Assert "wxAssertFailure" failed in DoNotifyWindowAboutCaptureLost(): window that captured the mouse didn't process wxEVT_MOUSE_CAPTURE_LOST

Can you help me?
Best regards
mikael.delsol
Registered User
 
Posts: 13
Joined: Fri Mar 02, 2007 11:22 am
Location: Montpellier, France

Postby Ben on Sun Apr 08, 2007 4:32 am

Hi,

My theory is that in your overridden class, you are not calling the base class in some methods-- probably the mouse ones.

If you post the code, I can give you more information.

Best,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Postby mikael.delsol on Tue Apr 10, 2007 3:13 am

Hello,
Thanks for your response.
Here are the main parts of my code :

In my Manager.h :
Code: Select all
class Manager : public wxAuiManager
{
public :
    Manager(wxWindow* managed_wnd = NULL, unsigned int flags = wxAUI_MGR_DEFAULT);
    ~Manager();

    virtual wxAuiFloatingFrame* CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p);
    void OnLeftDown(wxMouseEvent& evt);
    void OnLeftUp(wxMouseEvent& evt);
    void Update();

    DECLARE_EVENT_TABLE();
};


In my Manager.c : you'll see that I copied/pasted the source code of wxAuiManager.

Code: Select all
BEGIN_EVENT_TABLE(Manager, wxAuiManager)
    EVT_LEFT_DOWN(Manager::OnLeftDown)
    EVT_LEFT_UP(Manager::OnLeftUp)
END_EVENT_TABLE()

void Manager::OnLeftDown(wxMouseEvent& event)
{
    wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY());
    if (part)
    {
        if (part->type == wxAuiDockUIPart::typeDockSizer ||
            part->type == wxAuiDockUIPart::typePaneSizer)
        {
            if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
                return;
       
            // a dock may not be resized if it has a single
            // pane which is not resizable
            if (part->type == wxAuiDockUIPart::typeDockSizer && part->dock &&
                part->dock->panes.GetCount() == 1 &&
                part->dock->panes.Item(0)->IsFixed())
                    return;

            // panes that may not be resized should be ignored here
            if (part->pane && part->pane->IsFixed())
                return;

            m_action = actionResize;
            m_action_part = part;
            m_action_hintrect = wxRect();
            m_action_start = wxPoint(event.m_x, event.m_y);
            m_action_offset = wxPoint(event.m_x - part->rect.x,
                                      event.m_y - part->rect.y);
            m_frame->CaptureMouse();
        }
         else if (part->type == wxAuiDockUIPart::typePaneButton)
        {
            m_action = actionClickButton;
            m_action_part = part;
            m_action_start = wxPoint(event.m_x, event.m_y);
            m_frame->CaptureMouse();

            UpdateButtonOnScreen(part, event);
        }
         else if (part->type == wxAuiDockUIPart::typeCaption ||
                  part->type == wxAuiDockUIPart::typeGripper)
        {
            // if we are managing a wxAuiFloatingFrame window, then
            // we are an embedded wxAuiManager inside the wxAuiFloatingFrame.
            // We want to initiate a toolbar drag in our owner manager
            wxWindow* managed_wnd = GetManagedWindow();
           
            if (part->pane &&
                part->pane->window &&
                managed_wnd &&
                managed_wnd->IsKindOf(CLASSINFO(wxAuiFloatingFrame)))
            {
                wxAuiFloatingFrame* floating_frame = (wxAuiFloatingFrame*)managed_wnd;
                wxAuiManager* owner_mgr = floating_frame->GetOwnerManager();
                owner_mgr->StartPaneDrag(part->pane->window,
                                             wxPoint(event.m_x - part->rect.x,
                                                     event.m_y - part->rect.y));
                return;
            }
           
       
       
            if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
                return;

            if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
            {
                // set the caption as active
                SetActivePane(m_panes, part->pane->window);
                Repaint();
            }

            m_action = actionClickCaption;
            m_action_part = part;
            m_action_start = wxPoint(event.m_x, event.m_y);
            m_action_offset = wxPoint(event.m_x - part->rect.x,
                                      event.m_y - part->rect.y);
            m_frame->CaptureMouse();
        }
#ifdef __WXMAC__
        else
        {
            event.Skip();
        }
#endif
    }
#ifdef __WXMAC__
    else
    {
        event.Skip();
    }
#else
    event.Skip();
#endif
}


void Manager::OnLeftUp(wxMouseEvent& event)
{
    if (m_action == actionResize)
    {
        m_frame->ReleaseMouse();

        // get rid of the hint rectangle
        wxScreenDC dc;
        DrawResizeHint(dc, m_action_hintrect);

        // resize the dock or the pane
        if (m_action_part && m_action_part->type==wxAuiDockUIPart::typeDockSizer)
        {
            wxRect& rect = m_action_part->dock->rect;

            wxPoint new_pos(event.m_x - m_action_offset.x,
                            event.m_y - m_action_offset.y);

            switch (m_action_part->dock->dock_direction)
            {
                case wxAUI_DOCK_LEFT:
                    m_action_part->dock->size = new_pos.x - rect.x;
                    break;
                case wxAUI_DOCK_TOP:
                    m_action_part->dock->size = new_pos.y - rect.y;
                    break;
                case wxAUI_DOCK_RIGHT:
                    m_action_part->dock->size = rect.x + rect.width -
                                  new_pos.x - m_action_part->rect.GetWidth();
                    break;
                case wxAUI_DOCK_BOTTOM:
                    m_action_part->dock->size = rect.y + rect.height -
                                  new_pos.y - m_action_part->rect.GetHeight();
                    break;
            }

            Update();
            Repaint(NULL);
        }
         else if (m_action_part &&
                  m_action_part->type == wxAuiDockUIPart::typePaneSizer)
        {
            wxAuiDockInfo& dock = *m_action_part->dock;
            wxAuiPaneInfo& pane = *m_action_part->pane;

            int total_proportion = 0;
            int dock_pixels = 0;
            int new_pixsize = 0;

            int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE);
            int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
            int sash_size = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE);

            wxPoint new_pos(event.m_x - m_action_offset.x,
                            event.m_y - m_action_offset.y);

            // determine the pane rectangle by getting the pane part
            wxAuiDockUIPart* pane_part = GetPanePart(pane.window);
            wxASSERT_MSG(pane_part,
                       wxT("Pane border part not found -- shouldn't happen"));

            // determine the new pixel size that the user wants;
            // this will help us recalculate the pane's proportion
            if (dock.IsHorizontal())
                new_pixsize = new_pos.x - pane_part->rect.x;
                 else
                new_pixsize = new_pos.y - pane_part->rect.y;

            // determine the size of the dock, based on orientation
            if (dock.IsHorizontal())
                dock_pixels = dock.rect.GetWidth();
                 else
                dock_pixels = dock.rect.GetHeight();

            // determine the total proportion of all resizable panes,
            // and the total size of the dock minus the size of all
            // the fixed panes
            int i, dock_pane_count = dock.panes.GetCount();
            int pane_position = -1;
            for (i = 0; i < dock_pane_count; ++i)
            {
                wxAuiPaneInfo& 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
                if (p.IsFixed())
                {
                    if (dock.IsHorizontal())
                        dock_pixels -= p.best_size.x;
                         else
                        dock_pixels -= p.best_size.y;
                }
                 else
                {
                    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
            // to the right of the action pane
            int borrow_pane = -1;
            for (i = pane_position+1; i < dock_pane_count; ++i)
            {
                wxAuiPaneInfo& p = *dock.panes.Item(i);
                if (!p.IsFixed())
                {
                    borrow_pane = i;
                    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)
            {
                m_action = actionNone;
                return;
            }

            // 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,
            // causing the size of the pane to violate it's minimum size
            if (pane.min_size.IsFullySpecified())
            {
                min_size = 0;

                if (pane.HasBorder())
                    min_size += (pane_border_size*2);

                // calculate minimum size with decorations (border,caption)
                if (pane_part->orientation == wxVERTICAL)
                {
                    min_size += pane.min_size.y;
                    if (pane.HasCaption())
                        min_size += caption_size;
                }
                 else
                {
                    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
            // determine what's causing this.
            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)
    {
        m_hover_button = NULL;
        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
            wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON);
            e.SetManager(this);
            e.SetPane(m_action_part->pane);
            e.SetButton(m_action_part->button->button_id);
            ProcessMgrEvent(e);
        }
    }
    else if (m_action == actionClickCaption)
    {
        m_frame->ReleaseMouse();
    }
    else if (m_action == actionDragFloatingPane)
    {
        m_frame->ReleaseMouse();
    }
    else if (m_action == actionDragToolbarPane)
    {
        m_frame->ReleaseMouse();

        wxAuiPaneInfo& pane = GetPane(m_action_window);
        wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));

        // save the new positions
        wxAuiDockInfoPtrArray docks;
        FindDocks(m_docks, pane.dock_direction,
                  pane.dock_layer, pane.dock_row, docks);
        if (docks.GetCount() == 1)
        {
            wxAuiDockInfo& 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 &= ~wxAuiPaneInfo::actionPane;
        Update();
    }
    else
    {
        event.Skip();
    }

    m_action = actionNone;
    m_last_mouse_move = wxPoint(); // see comment in OnMotion()
}


Even if I change the returned object wxAuiManager by Manager in OnLeftDown method and wxAuiFloatingFrame by FloatingFrame (overriden class of wxAuiFloatingFrame), I have always the same error of wEVT_MOUSE_CAPTURE_LOST.

Thanks for your help
best
mikael.delsol
Registered User
 
Posts: 13
Joined: Fri Mar 02, 2007 11:22 am
Location: Montpellier, France

Postby Ben on Mon Apr 16, 2007 8:56 am

Hello,

First, a question: why don't you just call

Code: Select all
wxAuiManager::OnLeftDown(event)
in your derived class, instead of cutting and pasting all that code?

Second, the problem is caused by some kind of capture/uncapture code not being called where in the original it was called. This is a fair assumption given that the assert doesn't happen in the original.

So my suggestion is to try to find the capture/uncapture points, place some breakpoints and debug it.

All the best,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Postby mikael.delsol on Mon Apr 23, 2007 3:10 am

Hello,

I tried just to call OnLeftDown but if I want to fully use my wxAuiFloatingFrame derived class, FloatingFrame, I think I have to override all the methods which cal or use a wxAuiFloatingFrame object, isn't it ?
Moreover I don't see what I should override more about mouse event than LEFT_UP, or tell me.

I would realy like to use my FloatingFrame to control its behaviour.

So can you tell me more, or how would you do to be sure that it's my FloatingFrame that is used when we make a pane floating?

best,
mikael
mikael.delsol
Registered User
 
Posts: 13
Joined: Fri Mar 02, 2007 11:22 am
Location: Montpellier, France

Postby Ben on Tue Apr 24, 2007 1:17 am

Hi,

Can you post a stack trace of where the assert happens? I might be able to help you.

Thanks,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Postby mikael.delsol on Thu May 10, 2007 10:48 am

Hello,
What I can show you is the error generated when I switch to another window :
Image

Do you need more information?
thanks for your help
best
mikael.delsol
Registered User
 
Posts: 13
Joined: Fri Mar 02, 2007 11:22 am
Location: Montpellier, France

Postby Ben on Mon May 14, 2007 2:19 am

Hi Mikael,

Here's what I believe is happening. The mouse is being captured without being released. You need to make sure that the mouse is being released, otherwise this problem will happen. If you place breakpoints on each of the capture and release lines in wxAUI, you will see that they are being called properly. In your code, you must also ensure that the mouse is being released, otherwise this assert failure will happen.

All the best,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Return to wxAUI Questions, Thoughts & Feedback