]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/popupcmn.cpp
use wx/math.h for math constants - avoids redifinition warnings
[wxWidgets.git] / src / common / popupcmn.cpp
index b1e1eeade7c0d842a0611b5e240ec64fa23f90dd..85124079c688c3d66f14132e14724879d77adc58 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     06.01.01
 // RCS-ID:      $Id$
 // Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// License:     wxWindows license
+// License:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
@@ -17,7 +17,7 @@
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "popupwinbase.h"
 #endif
 
@@ -28,7 +28,7 @@
     #pragma hdrstop
 #endif
 
-#if wxUSE_POPUPWIN && !defined(__WXMOTIF__)
+#if wxUSE_POPUPWIN
 
 #include "wx/popupwin.h"
 
     #include "wx/univ/renderer.h"
 #endif // __WXUNIVERSAL__
 
-// there is no src/{msw,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(__WXMSW__) || defined(__WXMGL__)
-    IMPLEMENT_DYNAMIC_CLASS(wxPopupWindow, wxWindow)
-#endif // __WXMSW__
+#ifdef __WXGTK__
+    #include <gtk/gtk.h>
+#endif
 
+IMPLEMENT_DYNAMIC_CLASS(wxPopupWindow, wxWindow)
 IMPLEMENT_DYNAMIC_CLASS(wxPopupTransientWindow, wxPopupWindow)
 
 #if wxUSE_COMBOBOX && defined(__WXUNIVERSAL__)
@@ -74,6 +73,7 @@ private:
     wxPopupTransientWindow *m_popup;
 
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxPopupWindowHandler)
 };
 
 class wxPopupFocusHandler : public wxEvtHandler
@@ -82,28 +82,26 @@ public:
     wxPopupFocusHandler(wxPopupTransientWindow *popup)
     {
         m_popup = popup;
-
-#ifdef __WXGTK__
-        // ignore the next few OnKillFocus() calls
-        m_creationTime = time(NULL);
-#endif // __WXGTK__
     }
 
 protected:
     // event handlers
+#ifdef __WXMSW__
+    // Under MSW, we catch the kill focus event
     void OnKillFocus(wxFocusEvent& event);
+#else
+    // Under GTK+, event a transient popup window
+    // is a toplevel window so we need to catch
+    // deactivate events
+    void OnActivate(wxActivateEvent &event);
+#endif
     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)
 };
 
 // ----------------------------------------------------------------------------
@@ -115,7 +113,11 @@ BEGIN_EVENT_TABLE(wxPopupWindowHandler, wxEvtHandler)
 END_EVENT_TABLE()
 
 BEGIN_EVENT_TABLE(wxPopupFocusHandler, wxEvtHandler)
+#ifdef __WXMSW__
     EVT_KILL_FOCUS(wxPopupFocusHandler::OnKillFocus)
+#else
+    EVT_ACTIVATE(wxPopupFocusHandler::OnActivate)
+#endif
     EVT_KEY_DOWN(wxPopupFocusHandler::OnKeyDown)
 END_EVENT_TABLE()
 
@@ -134,7 +136,7 @@ wxPopupWindowBase::~wxPopupWindowBase()
 
 bool wxPopupWindowBase::Create(wxWindow* WXUNUSED(parent), int WXUNUSED(flags))
 {
-    return TRUE;
+    return true;
 }
 
 void wxPopupWindowBase::Position(const wxPoint& ptOrigin,
@@ -196,16 +198,13 @@ 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
@@ -216,17 +215,30 @@ void wxPopupTransientWindow::PopHandlers()
         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)
@@ -241,8 +253,6 @@ 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;
@@ -254,23 +264,43 @@ void wxPopupTransientWindow::Popup(wxWindow *winFocus)
     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__
+
+}
+
+bool wxPopupTransientWindow::Show( bool show )
+{
+#ifdef __WXGTK__
+    if (!show)
+        gtk_grab_remove( m_widget );
+#endif
+
+    bool ret = wxPopupWindow::Show( show );
+    
+#ifdef __WXGTK__
+    if (show)
+        gtk_grab_add( m_widget );
+#endif
 
-#endif // !__WXX11__
+    return ret;
 }
 
 void wxPopupTransientWindow::Dismiss()
@@ -295,7 +325,7 @@ void wxPopupTransientWindow::OnDismiss()
 bool wxPopupTransientWindow::ProcessLeftDown(wxMouseEvent& WXUNUSED(event))
 {
     // no special processing here
-    return FALSE;
+    return false;
 }
 
 #if wxUSE_COMBOBOX && defined(__WXUNIVERSAL__)
@@ -304,6 +334,10 @@ bool wxPopupTransientWindow::ProcessLeftDown(wxMouseEvent& WXUNUSED(event))
 // wxPopupComboWindow
 // ----------------------------------------------------------------------------
 
+BEGIN_EVENT_TABLE(wxPopupComboWindow, wxPopupTransientWindow)
+    EVT_KEY_DOWN(wxPopupComboWindow::OnKeyDown)
+END_EVENT_TABLE()
+
 wxPopupComboWindow::wxPopupComboWindow(wxComboControl *parent)
                   : wxPopupTransientWindow(parent)
 {
@@ -341,6 +375,11 @@ void wxPopupComboWindow::OnDismiss()
     m_combo->OnDismiss();
 }
 
+void wxPopupComboWindow::OnKeyDown(wxKeyEvent& event)
+{
+    m_combo->ProcessEvent(event);
+}
+
 #endif // wxUSE_COMBOBOX && defined(__WXUNIVERSAL__)
 
 // ----------------------------------------------------------------------------
@@ -435,18 +474,9 @@ void wxPopupWindowHandler::OnLeftDown(wxMouseEvent& event)
 // wxPopupFocusHandler
 // ----------------------------------------------------------------------------
 
+#ifdef __WXMSW__
 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();
@@ -459,6 +489,13 @@ void wxPopupFocusHandler::OnKillFocus(wxFocusEvent& event)
 
     m_popup->DismissAndNotify();
 }
+#else
+void wxPopupFocusHandler::OnActivate(wxActivateEvent &event)
+{
+    if (event.GetActive())
+        m_popup->DismissAndNotify();
+}
+#endif
 
 void wxPopupFocusHandler::OnKeyDown(wxKeyEvent& event)
 {