]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Don't force the child's m_isShown state to match that of the parent in CocoaAddChild.
[wxWidgets.git] / src / gtk / window.cpp
index a113e7105fddd884147f1c9246714768fafe6572..eb36d67c61930c4f0919275393d07a9d185ef585 100644 (file)
@@ -25,7 +25,6 @@
     #include "wx/settings.h"
     #include "wx/msgdlg.h"
     #include "wx/textctrl.h"
-    #include "wx/radiobut.h"
     #include "wx/toolbar.h"
     #include "wx/combobox.h"
     #include "wx/layout.h"
@@ -991,6 +990,11 @@ gtk_window_key_press_callback( GtkWidget *widget,
     if (g_blockEventsOnDrag)
         return FALSE;
 
+    // GTK+ sends keypress events to the focus widget and then
+    // to all its parent and grandparent widget. We only want
+    // the key events from the focus widget.
+    if (!GTK_WIDGET_HAS_FOCUS(widget))
+        return FALSE;
 
     wxKeyEvent event( wxEVT_KEY_DOWN );
     bool ret = false;
@@ -1008,18 +1012,7 @@ gtk_window_key_press_callback( GtkWidget *widget,
         return_after_IM = true;
     }
 
-    // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw):
-    // When we get a key_press event here, it could be originate
-    // from the current widget or its child widgets.  However, only the widget
-    // with the INPUT FOCUS can generate the INITIAL key_press event.  That is,
-    // if the CURRENT widget doesn't have the FOCUS at all, this event definitely
-    // originated from its child widgets and shouldn't be passed to IM context.
-    // In fact, what a GTK+ IM should do is filtering keyEvents and convert them
-    // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS.  Besides, when current
-    // widgets has both IM context and input focus, the event should be filtered
-    // by gtk_im_context_filter_keypress().
-    // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns.
-    if ((!ret) && (win->m_imData != NULL) && ( wxWindow::FindFocus() == win ))
+    if ((!ret) && (win->m_imData != NULL))
     {
         // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
         // docs, if IM filter returns true, no further processing should be done.
@@ -1440,11 +1433,6 @@ gtk_window_button_press_callback( GtkWidget *widget,
 
     g_lastButtonNumber = gdk_event->button;
 
-    if (win->m_wxwindow && (g_focusWindow != win) && win->IsFocusable())
-    {
-        gtk_widget_grab_focus( win->m_wxwindow );
-    }
-
     // GDK sends surplus button down events
     // before a double click event. We
     // need to filter these out.
@@ -1575,10 +1563,10 @@ gtk_window_button_press_callback( GtkWidget *widget,
     if ( ret )
         return TRUE;
 
-    if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && 
-        (g_focusWindow != win) && win->IsFocusable())
+    if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() &&
+        (g_focusWindow != win) /* && win->IsFocusable() */)
     {
-        gtk_widget_grab_focus( win->m_wxwindow );
+        win->SetFocus();
     }
 
     if (event_type == wxEVT_RIGHT_DOWN)
@@ -2014,9 +2002,10 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
 
         const int orient = wxWindow::OrientFromScrollDir(
                                         win->ScrollDirFromRange(range));
-        wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
-        event.SetEventObject(win);
-        win->GTKProcessEvent(event);
+        wxScrollWinEvent evt(wxEVT_SCROLLWIN_THUMBRELEASE,
+                                win->GetScrollPos(orient), orient);
+        evt.SetEventObject(win);
+        win->GTKProcessEvent(evt);
     }
 }
 
@@ -2107,6 +2096,27 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
     }
 }
 
+//-----------------------------------------------------------------------------
+// "grab_broken"
+//-----------------------------------------------------------------------------
+
+#if GTK_CHECK_VERSION(2, 8, 0)
+static gboolean
+gtk_window_grab_broken( GtkWidget*,
+                        GdkEventGrabBroken *event,
+                        wxWindow *win )
+{
+    // Mouse capture has been lost involuntarily, notify the application
+    if(!event->keyboard && wxWindow::GetCapture() == win)
+    {
+        wxMouseCaptureLostEvent evt( win->GetId() );
+        evt.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( evt );
+    }
+    return false;
+}
+#endif
+
 } // extern "C"
 
 // ----------------------------------------------------------------------------
@@ -2219,7 +2229,6 @@ void wxWindowGTK::Init()
     m_hasScrolling = false;
     m_isScrolling = false;
     m_mouseButtonDown = false;
-    m_blockScrollEvent = false;
 
     // initialize scrolling stuff
     for ( int dir = 0; dir < ScrollDir_Max; dir++ )
@@ -2521,6 +2530,26 @@ void wxWindowGTK::PostCreation()
         // Catch native resize events
         g_signal_connect (m_wxwindow, "size_allocate",
                           G_CALLBACK (gtk_window_size_callback), this);
+#if GTK_CHECK_VERSION(2, 8, 0)
+        if (!gtk_check_version(2,8,0))
+        {
+            // Make sure we can notify the app when mouse capture is lost
+            g_signal_connect (m_wxwindow, "grab_broken_event",
+                          G_CALLBACK (gtk_window_grab_broken), this);
+        }
+#endif
+    }
+
+    if ( connect_widget != m_wxwindow )
+    {
+#if GTK_CHECK_VERSION(2, 8, 0)
+        if (!gtk_check_version(2,8,0))
+        {
+            // Make sure we can notify app code when mouse capture is lost
+            g_signal_connect (connect_widget, "grab_broken_event",
+                        G_CALLBACK (gtk_window_grab_broken), this);
+        }
+#endif
     }
 
 #if wxUSE_COMBOBOX
@@ -2811,7 +2840,7 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    if (wxUpdateUIEvent::CanUpdate(this))
+    if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
@@ -2869,7 +2898,7 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
 
     int dx = 0;
     int dy = 0;
-    if (m_parent && m_parent->m_wxwindow)
+    if (!IsTopLevel() && m_parent && m_parent->m_wxwindow)
     {
         GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
         dx = gtk_pizza_get_xoffset( pizza );
@@ -3021,9 +3050,7 @@ int wxWindowGTK::GetCharHeight() const
     wxFont font = GetFont();
     wxCHECK_MSG( font.Ok(), 12, wxT("invalid font") );
 
-    PangoContext *context = NULL;
-    if (m_widget)
-        context = gtk_widget_get_pango_context( m_widget );
+    PangoContext* context = gtk_widget_get_pango_context(m_widget);
 
     if (!context)
         return 0;
@@ -3049,9 +3076,7 @@ int wxWindowGTK::GetCharWidth() const
     wxFont font = GetFont();
     wxCHECK_MSG( font.Ok(), 8, wxT("invalid font") );
 
-    PangoContext *context = NULL;
-    if (m_widget)
-        context = gtk_widget_get_pango_context( m_widget );
+    PangoContext* context = gtk_widget_get_pango_context(m_widget);
 
     if (!context)
         return 0;
@@ -3152,22 +3177,30 @@ void wxWindowGTK::SetFocus()
 
     if (m_wxwindow)
     {
+        // wxWindow::SetFocus() should really set the focus to
+        // this control, whatever the flags are
+        if (!GTK_WIDGET_CAN_FOCUS(m_wxwindow))
+            GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+
         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
         {
             gtk_widget_grab_focus (m_wxwindow);
         }
     }
-    else if (m_widget)
+    else
     {
+        // wxWindow::SetFocus() should really set the focus to
+        // this control, whatever the flags are
+        if (!GTK_WIDGET_CAN_FOCUS(m_widget))
+            GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS);
+
         if (GTK_IS_CONTAINER(m_widget))
         {
-#if wxUSE_RADIOBTN
-            if (IsKindOf(CLASSINFO(wxRadioButton)))
+            if (GTK_IS_RADIO_BUTTON(m_widget))
             {
                 gtk_widget_grab_focus (m_widget);
                 return;
             }
-#endif // wxUSE_RADIOBTN
 
             gtk_widget_child_focus( m_widget, GTK_DIR_TAB_FORWARD );
         }
@@ -4069,6 +4102,14 @@ void wxWindowGTK::DoReleaseMouse()
     gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
 }
 
+void wxWindowGTK::GTKReleaseMouseAndNotify()
+{
+    DoReleaseMouse();
+    wxMouseCaptureLostEvent evt(GetId());
+    evt.SetEventObject( this );
+    GetEventHandler()->ProcessEvent( evt );
+}
+
 /* static */
 wxWindow *wxWindowBase::GetCapture()
 {
@@ -4080,25 +4121,14 @@ bool wxWindowGTK::IsRetained() const
     return false;
 }
 
-void wxWindowGTK::BlockScrollEvent()
-{
-    wxASSERT(!m_blockScrollEvent);
-    m_blockScrollEvent = true;
-}
-
-void wxWindowGTK::UnblockScrollEvent()
-{
-    wxASSERT(m_blockScrollEvent);
-    m_blockScrollEvent = false;
-}
-
 void wxWindowGTK::SetScrollbar(int orient,
                                int pos,
                                int thumbVisible,
                                int range,
                                bool WXUNUSED(update))
 {
-    GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)];
+    const int dir = ScrollDirFromOrient(orient);
+    GtkRange* const sb = m_scrollBar[dir];
     wxCHECK_RET( sb, _T("this window is not scrollable") );
 
     if (range > 0)
@@ -4112,17 +4142,20 @@ void wxWindowGTK::SetScrollbar(int orient,
         thumbVisible = 1;
     }
 
-    if (pos > range - thumbVisible)
-        pos = range - thumbVisible;
-    if (pos < 0)
-        pos = 0;
     GtkAdjustment * const adj = sb->adjustment;
     adj->step_increment = 1;
     adj->page_increment =
     adj->page_size = thumbVisible;
-    adj->upper = range;
-    SetScrollPos(orient, pos);
-    gtk_adjustment_changed(adj);
+    adj->value = pos;
+
+    g_signal_handlers_block_by_func(
+        sb, (void*)gtk_scrollbar_value_changed, this);
+
+    gtk_range_set_range(sb, 0, range);
+    m_scrollPos[dir] = sb->adjustment->value;
+
+    g_signal_handlers_unblock_by_func(
+        sb, (void*)gtk_scrollbar_value_changed, this);
 }
 
 void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
@@ -4135,21 +4168,14 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
     //   will not move smoothly while tracking when using wxScrollHelper.
     if (GetScrollPos(orient) != pos)
     {
-        GtkAdjustment* adj = sb->adjustment;
-        const int max = int(adj->upper - adj->page_size);
-        if (pos > max)
-            pos = max;
-        if (pos < 0)
-            pos = 0;
-        m_scrollPos[dir] = adj->value = pos;
-
-        g_signal_handlers_block_by_func(m_scrollBar[dir],
-            (gpointer)gtk_scrollbar_value_changed, this);
+        g_signal_handlers_block_by_func(
+            sb, (void*)gtk_scrollbar_value_changed, this);
 
-        gtk_adjustment_value_changed(adj);
+        gtk_range_set_value(sb, pos);
+        m_scrollPos[dir] = sb->adjustment->value;
 
-        g_signal_handlers_unblock_by_func(m_scrollBar[dir],
-            (gpointer)gtk_scrollbar_value_changed, this);
+        g_signal_handlers_unblock_by_func(
+            sb, (void*)gtk_scrollbar_value_changed, this);
     }
 }
 
@@ -4239,7 +4265,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
     // No scrolling requested.
     if ((dx == 0) && (dy == 0)) return;
-    
+
     m_clipPaintRegion = true;
 
     if (GetLayoutDirection() == wxLayout_RightToLeft)
@@ -4285,8 +4311,11 @@ void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
             gtkstyle = GTK_SHADOW_OUT;
         else if (wxstyle & wxBORDER_SUNKEN)
             gtkstyle = GTK_SHADOW_IN;
+#if 0
+        // Now obsolete
         else if (wxstyle & wxBORDER_DOUBLE)
             gtkstyle = GTK_SHADOW_ETCHED_IN;
+#endif
         else //default
             gtkstyle = GTK_SHADOW_IN;