]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/popupcmn.cpp
added debug/release DLL configurations so that VC++ chooses the right one when buildi...
[wxWidgets.git] / src / common / popupcmn.cpp
index 6571388a34a1db8a3d334f2ed0f12160ecdda2d1..e4c673e313951da0b8babf9979947ef7551f89e3 100644 (file)
     #include "wx/univ/renderer.h"
 #endif // __WXUNIVERSAL__
 
-// there is no src/mgl/popupwin.cpp to put this in, so we do it here - BTW we
-// probably could do it for all ports here just as well
-#if defined(__WXMGL__)
-    IMPLEMENT_DYNAMIC_CLASS(wxPopupWindow, wxWindow)
-#endif // __WXMSW__
+#ifdef __WXGTK__
+    #include <gtk/gtk.h>
+#endif
+#ifdef __WXX11__
+#include "wx/x11/private.h"
+#endif
 
+IMPLEMENT_DYNAMIC_CLASS(wxPopupWindow, wxWindow)
 IMPLEMENT_DYNAMIC_CLASS(wxPopupTransientWindow, wxPopupWindow)
 
 #if wxUSE_COMBOBOX && defined(__WXUNIVERSAL__)
@@ -83,27 +85,15 @@ public:
     wxPopupFocusHandler(wxPopupTransientWindow *popup)
     {
         m_popup = popup;
-
-#ifdef __WXGTK__
-        // ignore the next few OnKillFocus() calls
-        m_creationTime = time(NULL);
-#endif // __WXGTK__
     }
 
 protected:
-    // event handlers
     void OnKillFocus(wxFocusEvent& event);
     void OnKeyDown(wxKeyEvent& event);
 
 private:
     wxPopupTransientWindow *m_popup;
 
-    // hack around wxGTK bug: we always get several kill focus events
-    // immediately after creation!
-#ifdef __WXGTK__
-    time_t m_creationTime;
-#endif // __WXGTK__
-
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxPopupFocusHandler)
 };
@@ -136,7 +126,7 @@ wxPopupWindowBase::~wxPopupWindowBase()
 
 bool wxPopupWindowBase::Create(wxWindow* WXUNUSED(parent), int WXUNUSED(flags))
 {
-    return TRUE;
+    return true;
 }
 
 void wxPopupWindowBase::Position(const wxPoint& ptOrigin,
@@ -198,37 +188,47 @@ wxPopupTransientWindow::wxPopupTransientWindow(wxWindow *parent, int style)
 wxPopupTransientWindow::~wxPopupTransientWindow()
 {
     PopHandlers();
-
-    delete m_handlerFocus;
-    delete m_handlerPopup;
 }
 
 void wxPopupTransientWindow::PopHandlers()
 {
     if ( m_child )
     {
-        if ( !m_child->RemoveEventHandler(m_handlerPopup) )
+        if ( m_handlerPopup && !m_child->RemoveEventHandler(m_handlerPopup) )
         {
             // something is very wrong and someone else probably deleted our
             // handler - so don't risk deleting it second time
             m_handlerPopup = NULL;
         }
 
-        m_child->ReleaseMouse();
+        // m_child->ReleaseMouse();
         m_child = NULL;
     }
 
+#ifdef __WXMSW__
     if ( m_focus )
     {
-#ifndef __WXX11__
-        if ( !m_focus->RemoveEventHandler(m_handlerFocus) )
+        if ( m_handlerFocus && !m_focus->RemoveEventHandler(m_handlerFocus) )
         {
             // see above
             m_handlerFocus = NULL;
         }
-#endif
-        m_focus = NULL;
     }
+#else
+    if ( m_handlerFocus && !RemoveEventHandler(m_handlerFocus) )
+    {
+        // see above
+        m_handlerFocus = NULL;
+    }
+#endif
+
+    // delete the handlers, they'll be created as necessary in Popup()
+    delete m_handlerPopup;
+    m_handlerPopup = NULL;
+    delete m_handlerFocus;
+    m_handlerFocus = NULL;
+
+    m_focus = NULL;
 }
 
 void wxPopupTransientWindow::Popup(wxWindow *winFocus)
@@ -243,36 +243,92 @@ void wxPopupTransientWindow::Popup(wxWindow *winFocus)
         m_child = this;
     }
 
-    // we can't capture mouse before the window is shown in wxGTK, so do it
-    // first
     Show();
 
     delete m_handlerPopup;
     m_handlerPopup = new wxPopupWindowHandler(this);
 
-    m_child->CaptureMouse();
+    // m_child->CaptureMouse();
     m_child->PushEventHandler(m_handlerPopup);
 
     m_focus = winFocus ? winFocus : this;
     m_focus->SetFocus();
 
-#ifndef __WXX11__
-
 #ifdef __WXMSW__
     // MSW doesn't allow to set focus to the popup window, but we need to
     // subclass the window which has the focus, and not winFocus passed in or
     // otherwise everything else breaks down
     m_focus = FindFocus();
     if ( m_focus )
-#endif // __WXMSW__
     {
         delete m_handlerFocus;
         m_handlerFocus = new wxPopupFocusHandler(this);
 
         m_focus->PushEventHandler(m_handlerFocus);
     }
+#else
+    // GTK+ catches the activate events from the popup
+    // window, not the focus events from the child window
+    delete m_handlerFocus;
+    m_handlerFocus = new wxPopupFocusHandler(this);
+    PushEventHandler(m_handlerFocus);
+#endif // __WXMSW__
 
-#endif // !__WXX11__
+}
+
+bool wxPopupTransientWindow::Show( bool show )
+{
+#ifdef __WXGTK__
+    if (!show)
+    {
+        gdk_pointer_ungrab( (guint32)GDK_CURRENT_TIME );
+
+        gtk_grab_remove( m_widget );
+    }
+#endif
+
+#ifdef __WXX11__
+    if (!show)
+    {
+        XUngrabPointer( wxGlobalDisplay(), CurrentTime );
+    }
+#endif
+
+    bool ret = wxPopupWindow::Show( show );
+
+#ifdef __WXGTK__
+    if (show)
+    {
+        gtk_grab_add( m_widget );
+
+        gdk_pointer_grab( m_widget->window, TRUE,
+                          (GdkEventMask)
+                            (GDK_BUTTON_PRESS_MASK |
+                             GDK_BUTTON_RELEASE_MASK |
+                             GDK_POINTER_MOTION_HINT_MASK |
+                             GDK_POINTER_MOTION_MASK),
+                          (GdkWindow *) NULL,
+                          (GdkCursor *) NULL,
+                          (guint32)GDK_CURRENT_TIME );
+    }
+#endif
+
+#ifdef __WXX11__
+    if (show)
+    {
+        Window xwindow = (Window) m_clientWindow;
+
+        /* int res =*/ XGrabPointer(wxGlobalDisplay(), xwindow,
+            True,
+            ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
+            GrabModeAsync,
+            GrabModeAsync,
+            None,
+            None,
+            CurrentTime );
+    }
+#endif
+    return ret;
 }
 
 void wxPopupTransientWindow::Dismiss()
@@ -297,7 +353,7 @@ void wxPopupTransientWindow::OnDismiss()
 bool wxPopupTransientWindow::ProcessLeftDown(wxMouseEvent& WXUNUSED(event))
 {
     // no special processing here
-    return FALSE;
+    return false;
 }
 
 #if wxUSE_COMBOBOX && defined(__WXUNIVERSAL__)
@@ -326,7 +382,7 @@ bool wxPopupComboWindow::Create(wxComboControl *parent)
 void wxPopupComboWindow::PositionNearCombo()
 {
     // the origin point must be in screen coords
-    wxPoint ptOrigin = m_combo->ClientToScreen(wxPoint(0, 0));
+    wxPoint ptOrigin = m_combo->ClientToScreen(wxPoint(0,0));
 
 #if 0 //def __WXUNIVERSAL__
     // account for the fact that (0, 0) is not the top left corner of the
@@ -448,16 +504,6 @@ void wxPopupWindowHandler::OnLeftDown(wxMouseEvent& event)
 
 void wxPopupFocusHandler::OnKillFocus(wxFocusEvent& event)
 {
-#ifdef __WXGTK__
-    // ignore the next OnKillFocus() call
-    if ( time(NULL) < m_creationTime + 1 )
-    {
-        event.Skip();
-
-        return;
-    }
-#endif // __WXGTK__
-
     // when we lose focus we always disappear - unless it goes to the popup (in
     // which case we don't really lose it)
     wxWindow *win = event.GetWindow();