]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mgl/window.cpp
mention wx[Flex]GridSizer too
[wxWidgets.git] / src / mgl / window.cpp
index 8f3bb0905a71900b8554ddb47a3d1325fabbf3a4..a76020c4ecbfc67f4392d0d5c1065e8ddad088d1 100644 (file)
@@ -64,9 +64,14 @@ winmng_t *g_winMng = NULL;
 MGLDevCtx *g_displayDC = NULL;
 
 // the window that has keyboard focus: 
-static wxWindowMGL *g_focusedWindow = NULL;
+static wxWindowMGL *gs_focusedWindow = NULL;
 // the window that is currently under mouse cursor:
-static wxWindowMGL *g_windowUnderMouse = NULL;
+static wxWindowMGL *gs_windowUnderMouse = NULL;
+// the window that has mouse capture
+static wxWindowMGL *gs_mouseCapture = NULL;
+// the frame that is currently active (i.e. its child has focus). It is
+// used to generate wxActivateEvents
+static wxWindowMGL *gs_activeFrame = NULL;
 
 // ---------------------------------------------------------------------------
 // constants
@@ -159,6 +164,15 @@ void wxDestroyMGL_WM()
     }
 }
 
+// Returns toplevel grandparent of given window:
+static wxWindowMGL* wxGetTopLevelParent(wxWindowMGL *win)
+{
+    wxWindowMGL *p = win;
+    while (p && !p->IsTopLevel())
+         p = p->GetParent();
+    return p;
+}
+
 // ---------------------------------------------------------------------------
 // MGL_WM hooks:
 // ---------------------------------------------------------------------------
@@ -166,7 +180,7 @@ void wxDestroyMGL_WM()
 static void wxWindowPainter(window_t *wnd, MGLDC *dc)
 {
     wxWindowMGL *w = (wxWindow*) wnd->userData;
-    if (w && !(w->GetStyle() & wxTRANSPARENT_WINDOW))
+    if ( w && !(w->GetWindowStyle() & wxTRANSPARENT_WINDOW) )
     {
         MGLDevCtx ctx(dc);
         w->HandlePaint(&ctx);
@@ -178,8 +192,11 @@ static void wxWindowPainter(window_t *wnd, MGLDC *dc)
 static ibool wxWindowMouseHandler(window_t *wnd, event_t *e)
 {
     wxWindowMGL *win = (wxWindowMGL*)MGL_wmGetWindowUserData(wnd);
-    wxPoint where = win->ScreenToClient(wxPoint(e->where_x, e->where_y));
+    wxPoint where;
     
+    MGL_wmCoordGlobalToLocal(win->GetHandle(), 
+                             e->where_x, e->where_y, &where.x, &where.y);
+
     if ( !win->IsEnabled() ) return FALSE;
     
     wxEventType type = wxEVT_NULL;
@@ -220,25 +237,44 @@ static ibool wxWindowMouseHandler(window_t *wnd, event_t *e)
             break;
 
         case EVT_MOUSEMOVE:
-            if ( win != g_windowUnderMouse )
+            if ( !gs_mouseCapture )
+            {
+                if ( win != gs_windowUnderMouse )
+                {
+                    if ( gs_windowUnderMouse )
+                    {
+                        wxMouseEvent event2(event);
+                        MGL_wmCoordGlobalToLocal(gs_windowUnderMouse->GetHandle(), 
+                                                 e->where_x, e->where_y, 
+                                                 &event2.m_x, &event2.m_y);
+
+                        event2.SetEventObject(gs_windowUnderMouse);
+                        event2.SetEventType(wxEVT_LEAVE_WINDOW);
+                        gs_windowUnderMouse->GetEventHandler()->ProcessEvent(event2);
+                    }
+
+                    wxMouseEvent event3(event);
+                    event3.SetEventType(wxEVT_ENTER_WINDOW);
+                    win->GetEventHandler()->ProcessEvent(event3);
+
+                    gs_windowUnderMouse = win;
+                }
+            }
+            else // gs_mouseCapture
             {
-                if ( g_windowUnderMouse )
+                bool inside = (where.x >= 0 && 
+                               where.y >= 0 &&
+                               where.x < win->GetSize().x &&
+                               where.y < win->GetSize().y);
+                if ( (inside && gs_windowUnderMouse != win) ||
+                     (!inside && gs_windowUnderMouse == win) )
                 {
-                    wxMouseEvent event2(event);
-                    wxPoint where2 = g_windowUnderMouse->ScreenToClient(
-                                            wxPoint(e->where_x, e->where_y));
-                    event2.m_x = where2.x;
-                    event2.m_y = where2.y;
-                    event2.SetEventObject(g_windowUnderMouse);
-                    event2.SetEventType(wxEVT_LEAVE_WINDOW);
-                    g_windowUnderMouse->GetEventHandler()->ProcessEvent(event2);
+                    wxMouseEvent evt(inside ? 
+                                     wxEVT_ENTER_WINDOW : wxEVT_LEAVE_WINDOW);
+                    evt.SetEventObject(win);
+                    win->GetEventHandler()->ProcessEvent(evt);
+                    gs_windowUnderMouse = inside ? win : NULL;
                 }
-                
-                wxMouseEvent event3(event);
-                event3.SetEventType(wxEVT_ENTER_WINDOW);
-                win->GetEventHandler()->ProcessEvent(event3);
-                
-                g_windowUnderMouse = win;
             }
             
             type = wxEVT_MOTION;
@@ -377,6 +413,8 @@ static long wxScanToKeyCode(event_t *event)
             break;
     }
 
+    #undef KEY
+
     return key;
 }
 
@@ -387,12 +425,13 @@ static long wxAsciiToKeyCode(event_t *event)
 
 static ibool wxWindowKeybHandler(window_t *wnd, event_t *e)
 {
-    wxEventType type = wxEVT_NULL;
     wxWindowMGL *win = (wxWindowMGL*)MGL_wmGetWindowUserData(wnd);
 
     if ( !win->IsEnabled() ) return FALSE;
 
-    wxPoint where = win->ScreenToClient(wxPoint(e->where_x, e->where_y));
+    wxPoint where;
+    MGL_wmCoordGlobalToLocal(win->GetHandle(), 
+                             e->where_x, e->where_y, &where.x, &where.y);
     
     wxKeyEvent event;
     event.SetEventObject(win);
@@ -491,10 +530,25 @@ wxWindowMGL::~wxWindowMGL()
 {
     m_isBeingDeleted = TRUE;
 
-    if ( g_focusedWindow == this )
+    if ( gs_mouseCapture == this )
+        ReleaseMouse();
+
+    if (gs_activeFrame == this)
+    {
+       gs_activeFrame = NULL;
+       // activate next frame in Z-order:
+       if ( m_wnd->prev )
+       {
+           wxWindowMGL *win = (wxWindowMGL*)m_wnd->prev->userData;
+           win->SetFocus();
+        }
+    }
+    
+    if ( gs_focusedWindow == this )
         KillFocus();
-    if ( g_windowUnderMouse == this )
-        g_windowUnderMouse = NULL;
+
+    if ( gs_windowUnderMouse == this )
+        gs_windowUnderMouse = NULL;
 
     // VS: destroy children first and _then_ detach *this from its parent.
     //     If we'd do it the other way around, children wouldn't be able
@@ -516,22 +570,11 @@ bool wxWindowMGL::Create(wxWindow *parent,
                          long style,
                          const wxString& name)
 {
-    // FIXME_MGL -- temporary!
-    //wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
-
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return FALSE;
 
-    if ( parent ) // FIXME_MGL temporary
+    if ( parent )
         parent->AddChild(this);
-    else
-        m_isShown=FALSE;// FIXME_MGL -- temporary, simulates wxTLW/wxFrame
-
-    if ( style & wxPOPUP_WINDOW )
-    {
-        // it is created hidden as other top level windows
-        m_isShown = FALSE;
-    }
 
     int x, y, w, h;
     x = pos.x, y = pos.y;
@@ -543,14 +586,25 @@ bool wxWindowMGL::Create(wxWindow *parent,
     h = HeightDefault(size.y);
     
     long mgl_style = 0;
+    window_t *wnd_parent = parent ? parent->GetHandle() : NULL;
+
     if ( !(style & wxNO_FULL_REPAINT_ON_RESIZE) )
+    {
         mgl_style |= MGL_WM_FULL_REPAINT_ON_RESIZE;
+    }
     if ( style & wxSTAY_ON_TOP )
+    {
         mgl_style |= MGL_WM_ALWAYS_ON_TOP;
+    }
+    if ( style & wxPOPUP_WINDOW )
+    {
+        mgl_style |= MGL_WM_ALWAYS_ON_TOP;
+        // it is created hidden as other top level windows
+        m_isShown = FALSE;
+        wnd_parent = NULL;
+    }
 
-    m_wnd = MGL_wmCreateWindow(g_winMng,
-                               parent ? parent->GetHandle() : NULL,
-                               x, y, w, h);
+    m_wnd = MGL_wmCreateWindow(g_winMng, wnd_parent, x, y, w, h);
 
     MGL_wmSetWindowFlags(m_wnd, mgl_style);
     MGL_wmSetWindowUserData(m_wnd, (void*) this);
@@ -560,7 +614,7 @@ bool wxWindowMGL::Create(wxWindow *parent,
 
     MGL_wmPushWindowEventHandler(m_wnd, wxWindowMouseHandler, EVT_MOUSEEVT, 0);
     MGL_wmPushWindowEventHandler(m_wnd, wxWindowKeybHandler, EVT_KEYEVT, 0);
-
+    
     return TRUE;
 }
 
@@ -570,25 +624,34 @@ bool wxWindowMGL::Create(wxWindow *parent,
 
 void wxWindowMGL::SetFocus()
 {
-    if (g_focusedWindow)
-        g_focusedWindow->KillFocus();
+    if ( gs_focusedWindow )
+        gs_focusedWindow->KillFocus();
     
-    g_focusedWindow = this;
+    gs_focusedWindow = this;
     
     MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT, wxMGL_CAPTURE_KEYB);
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
     wxCaret *caret = GetCaret();
-    if (caret)
+    if ( caret )
         caret->OnSetFocus();
 #endif // wxUSE_CARET
 
-    if ( IsTopLevel() )
+    wxWindowMGL *active = wxGetTopLevelParent(this);
+    if ( active != gs_activeFrame )
     {
-        wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
-        event.SetEventObject(this);
-        GetEventHandler()->ProcessEvent(event);
+        if ( gs_activeFrame )
+        {
+            wxActivateEvent event(wxEVT_ACTIVATE, FALSE, gs_activeFrame->GetId());
+            event.SetEventObject(gs_activeFrame);
+            gs_activeFrame->GetEventHandler()->ProcessEvent(event);
+        }
+
+        gs_activeFrame = active;
+        wxActivateEvent event(wxEVT_ACTIVATE, TRUE, gs_activeFrame->GetId());
+        event.SetEventObject(gs_activeFrame);
+        gs_activeFrame->GetEventHandler()->ProcessEvent(event);
     }
     
     wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
@@ -598,8 +661,8 @@ void wxWindowMGL::SetFocus()
 
 void wxWindowMGL::KillFocus()
 {
-    if ( g_focusedWindow != this ) return;
-    g_focusedWindow = NULL;
+    if ( gs_focusedWindow != this ) return;
+    gs_focusedWindow = NULL;
 
     if ( m_isBeingDeleted ) return;
     
@@ -614,6 +677,7 @@ void wxWindowMGL::KillFocus()
 
     if ( IsTopLevel() )
     {
+        // FIXME_MGL - this is wrong, see wxGTK!
         wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
         event.SetEventObject(this);
         GetEventHandler()->ProcessEvent(event);
@@ -630,7 +694,7 @@ void wxWindowMGL::KillFocus()
 // ----------------------------------------------------------------------------
 wxWindow *wxWindowBase::FindFocus()
 {
-    return (wxWindow*)g_focusedWindow;
+    return (wxWindow*)gs_focusedWindow;
 }
 
 bool wxWindowMGL::Show(bool show)
@@ -639,6 +703,17 @@ bool wxWindowMGL::Show(bool show)
         return FALSE;
 
     MGL_wmShowWindow(m_wnd, show);
+    
+    if (!show && gs_activeFrame == this)
+    {
+       // activate next frame in Z-order:
+       if ( m_wnd->prev )
+       {
+           wxWindowMGL *win = (wxWindowMGL*)m_wnd->prev->userData;
+           win->SetFocus();
+        }
+    }
+
     return TRUE;
 }
 
@@ -656,22 +731,24 @@ void wxWindowMGL::Lower()
 
 void wxWindowMGL::CaptureMouse()
 {
+    if ( gs_mouseCapture )
+        MGL_wmUncaptureEvents(gs_mouseCapture->m_wnd, wxMGL_CAPTURE_MOUSE);
+
+    gs_mouseCapture = this;
     MGL_wmCaptureEvents(m_wnd, EVT_MOUSEEVT, wxMGL_CAPTURE_MOUSE);
 }
 
 void wxWindowMGL::ReleaseMouse()
 {
+    wxASSERT_MSG( gs_mouseCapture == this, wxT("attempt to release mouse, but this window hasn't captured it") )
+    
     MGL_wmUncaptureEvents(m_wnd, wxMGL_CAPTURE_MOUSE);
+    gs_mouseCapture = NULL;
 }
 
 /* static */ wxWindow *wxWindowBase::GetCapture()
 {
-    for (captureentry_t *c = g_winMng->capturedEvents; c; c = c->next)
-    {
-        if ( c->id == wxMGL_CAPTURE_MOUSE )
-            return (wxWindow*)c->wnd->userData;
-    }
-    return NULL;
+    return (wxWindow*)gs_mouseCapture;
 }
 
 bool wxWindowMGL::SetCursor(const wxCursor& cursor)
@@ -790,27 +867,21 @@ void wxWindowMGL::DoGetPosition(int *x, int *y) const
 void wxWindowMGL::DoScreenToClient(int *x, int *y) const
 {
     int ax, ay;
-    wxPoint co = GetClientAreaOrigin();
-
-    MGL_wmCoordGlobalToLocal(m_wnd, m_wnd->x, m_wnd->y, &ax, &ay);
-    ax -= co.x;
-    ay -= co.y;
+    MGL_wmCoordGlobalToLocal(m_wnd, 0, 0, &ax, &ay);
     if (x)
-        *x = ax;
+        (*x) += ax;
     if (y)
-        *y = ay;
+        (*y) += ay;
 }
 
 void wxWindowMGL::DoClientToScreen(int *x, int *y) const
 {
     int ax, ay;
-    wxPoint co = GetClientAreaOrigin();
-
-    MGL_wmCoordGlobalToLocal(m_wnd, m_wnd->x+co.x, m_wnd->y+co.y, &ax, &ay);
+    MGL_wmCoordLocalToGlobal(m_wnd, 0, 0, &ax, &ay);
     if (x)
-        *x = ax;
+        (*x) += ax;
     if (y)
-        *y = ay;
+        (*y) += ay;
 }
 
 // Get size *available for subwindows* i.e. excluding menu bar etc.