]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
fixed yet another memory leak in LoadGnomeDataFromKeyFile() (coverity checker CID 51)
[wxWidgets.git] / src / gtk / window.cpp
index 43673380dcd5605bf515548d060726a7c26f0d93..eda96a1e107c1b46e243f464da55b5dff1cf7b84 100644 (file)
@@ -24,6 +24,9 @@
 #include "wx/msgdlg.h"
 #include "wx/module.h"
 #include "wx/combobox.h"
+#if wxUSE_TOOLBAR_NATIVE
+#include "wx/toolbar.h"
+#endif
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
 #include "wx/math.h"
 #include <ctype.h>
 
+// FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0
+#include <gtk/gtkversion.h>
+#if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0)
+#undef GTK_DISABLE_DEPRECATED
+#endif
+
 #include "wx/gtk/private.h"
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkkeysyms.h>
@@ -400,7 +409,10 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win )
+static gboolean
+gtk_window_own_expose_callback( GtkWidget *widget,
+                                GdkEventExpose *gdk_event,
+                                wxWindowGTK *win )
 {
     if (gdk_event->count > 0) return FALSE;
 
@@ -468,9 +480,10 @@ void wxgtk_combo_size_request_callback(GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static int gtk_window_expose_callback( GtkWidget *widget,
-                                       GdkEventExpose *gdk_event,
-                                       wxWindow *win )
+static gboolean
+gtk_window_expose_callback( GtkWidget *widget,
+                            GdkEventExpose *gdk_event,
+                            wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -964,9 +977,10 @@ struct wxGtkIMData
 };
 
 extern "C" {
-static gint gtk_window_key_press_callback( GtkWidget *widget,
-                                           GdkEventKey *gdk_event,
-                                           wxWindow *win )
+static gboolean
+gtk_window_key_press_callback( GtkWidget *widget,
+                               GdkEventKey *gdk_event,
+                               wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1016,12 +1030,12 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         if (intercepted_by_IM)
         {
             wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM"));
-            return true;
+            return TRUE;
         }
     }
 
     if (return_after_IM)
-        return false;
+        return FALSE;
 
 #if wxUSE_ACCEL
     if (!ret)
@@ -1079,7 +1093,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 #if wxUSE_UNICODE
                 event.m_uniChar = event.m_keyCode;
 #endif
-            }               
+            }
 
             // Implement OnCharHook by checking ancestor top level windows
             wxWindow *parent = win;
@@ -1175,9 +1189,10 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 }
 
 extern "C" {
-static void gtk_wxwindow_commit_cb (GtkIMContext *context,
-                           const gchar  *str,
-                           wxWindow     *window)
+static void
+gtk_wxwindow_commit_cb (GtkIMContext *context,
+                        const gchar  *str,
+                        wxWindow     *window)
 {
     wxKeyEvent event( wxEVT_KEY_DOWN );
 
@@ -1223,8 +1238,8 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
             event.m_keyCode = *pstr - 'a' + 1;
 #if wxUSE_UNICODE
             event.m_uniChar = event.m_keyCode;
-#endif  
-        }               
+#endif
+        }
 
         if (parent)
         {
@@ -1247,9 +1262,10 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_key_release_callback( GtkWidget *widget,
-                                             GdkEventKey *gdk_event,
-                                             wxWindowGTK *win )
+static gboolean
+gtk_window_key_release_callback( GtkWidget *widget,
+                                 GdkEventKey *gdk_event,
+                                 wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1420,9 +1436,10 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_button_press_callback( GtkWidget *widget,
-                                              GdkEventButton *gdk_event,
-                                              wxWindowGTK *win )
+static gboolean
+gtk_window_button_press_callback( GtkWidget *widget,
+                                  GdkEventButton *gdk_event,
+                                  wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1610,9 +1627,10 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_button_release_callback( GtkWidget *widget,
-                                                GdkEventButton *gdk_event,
-                                                wxWindowGTK *win )
+static gboolean
+gtk_window_button_release_callback( GtkWidget *widget,
+                                    GdkEventButton *gdk_event,
+                                    wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1672,9 +1690,10 @@ static gint gtk_window_button_release_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_motion_notify_callback( GtkWidget *widget,
-                                               GdkEventMotion *gdk_event,
-                                               wxWindowGTK *win )
+static gboolean
+gtk_window_motion_notify_callback( GtkWidget *widget,
+                                   GdkEventMotion *gdk_event,
+                                   wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1733,6 +1752,15 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
     }
 
+    if ( !g_captureWindow )
+    {
+        wxSetCursorEvent cevent( event.m_x, event.m_y );
+        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        {
+            // Rewrite cursor handling here (away from idle).
+        }
+    }
+    
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         g_signal_stop_emission_by_name (widget, "motion_notify_event");
@@ -1748,9 +1776,10 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_wheel_callback (GtkWidget * widget,
-                                       GdkEventScroll * gdk_event,
-                                       wxWindowGTK * win)
+static gboolean
+gtk_window_wheel_callback (GtkWidget * widget,
+                           GdkEventScroll * gdk_event,
+                           wxWindowGTK * win)
 {
     DEBUG_MAIN_THREAD
 
@@ -1835,9 +1864,10 @@ static bool DoSendFocusEvents(wxWindow *win)
 }
 
 extern "C" {
-static gint gtk_window_focus_in_callback( GtkWidget *widget,
-                                          GdkEvent *WXUNUSED(event),
-                                          wxWindow *win )
+static gboolean
+gtk_window_focus_in_callback( GtkWidget *widget,
+                              GdkEventFocus *WXUNUSED(event),
+                              wxWindow *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1867,19 +1897,24 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
     }
 #endif // wxUSE_CARET
 
+    gboolean ret = FALSE;
+
     // does the window itself think that it has the focus?
     if ( !win->m_hasFocus )
     {
         // not yet, notify it
         win->m_hasFocus = true;
 
-        if ( DoSendFocusEvents(win) )
-        {
-           g_signal_stop_emission_by_name (widget, "focus_in_event");
-           return TRUE;
-        }
+        (void)DoSendFocusEvents(win);
+
+        ret = TRUE;
     }
 
+    // Disable default focus handling for custom windows
+    // since the default GTK+ handler issues a repaint
+    if (win->m_wxwindow)
+        return ret;
+
     return FALSE;
 }
 }
@@ -1889,7 +1924,10 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, wxWindowGTK *win )
+static gboolean
+gtk_window_focus_out_callback( GtkWidget *widget,
+                               GdkEventFocus *gdk_event,
+                               wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1923,6 +1961,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
     }
 #endif // wxUSE_CARET
 
+    gboolean ret = FALSE;
+
     // don't send the window a kill focus event if it thinks that it doesn't
     // have focus already
     if ( win->m_hasFocus )
@@ -1932,13 +1972,16 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
         event.SetEventObject( win );
 
-        // even if we did process the event in wx code, still let GTK itself
-        // process it too as otherwise bad things happen, especially in GTK2
-        // where the text control simply aborts the program if it doesn't get
-        // the matching focus out event
         (void)win->GetEventHandler()->ProcessEvent( event );
+
+        ret = TRUE;
     }
 
+    // Disable default focus handling for custom windows
+    // since the default GTK+ handler issues a repaint
+    if (win->m_wxwindow)
+        return ret;
+
     return FALSE;
 }
 }
@@ -1948,10 +1991,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static
-gint gtk_window_enter_callback( GtkWidget *widget,
-                                GdkEventCrossing *gdk_event,
-                                wxWindowGTK *win )
+static gboolean
+gtk_window_enter_callback( GtkWidget *widget,
+                           GdkEventCrossing *gdk_event,
+                           wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1978,6 +2021,15 @@ gint gtk_window_enter_callback( GtkWidget *widget,
     event.m_x = x + pt.x;
     event.m_y = y + pt.y;
 
+    if ( !g_captureWindow )
+    {
+        wxSetCursorEvent cevent( event.m_x, event.m_y );
+        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        {
+            // Rewrite cursor handling here (away from idle).
+        }
+    }
+    
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
        g_signal_stop_emission_by_name (widget, "enter_notify_event");
@@ -1993,7 +2045,10 @@ gint gtk_window_enter_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
+static gboolean
+gtk_window_leave_callback( GtkWidget *widget,
+                           GdkEventCrossing *gdk_event,
+                           wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -2108,9 +2163,10 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
-                                                 GdkEventButton *gdk_event,
-                                                 wxWindowGTK *win)
+static gboolean
+gtk_scrollbar_button_press_callback( GtkWidget *widget,
+                                     GdkEventButton *gdk_event,
+                                     wxWindowGTK *win)
 {
     DEBUG_MAIN_THREAD
 
@@ -2134,9 +2190,10 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
-                                                   GdkEventButton *WXUNUSED(gdk_event),
-                                                   wxWindowGTK *win)
+static gboolean
+gtk_scrollbar_button_release_callback( GtkRange *widget,
+                                       GdkEventButton *WXUNUSED(gdk_event),
+                                       wxWindowGTK *win)
 {
     DEBUG_MAIN_THREAD
 
@@ -2195,7 +2252,7 @@ wxWindow *wxWindowBase::DoFindFocus()
    been realized, so we do this directly after realization. */
 
 extern "C" {
-static gint
+static void
 gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 {
     DEBUG_MAIN_THREAD
@@ -2213,8 +2270,6 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent( event );
-
-    return FALSE;
 }
 }
 
@@ -2293,7 +2348,7 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
 /* Initialize XIM support */
 
 extern "C" {
-static gint
+static void
 gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
                                 wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
 {
@@ -2301,12 +2356,12 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
         wxapp_install_idle_handler();
 
 #ifdef HAVE_XIM
-    if (win->m_ic) return FALSE;
-    if (!widget) return FALSE;
-    if (!gdk_im_ready()) return FALSE;
+    if (win->m_ic) return;
+    if (!widget) return;
+    if (!gdk_im_ready()) return;
 
     win->m_icattr = gdk_ic_attr_new();
-    if (!win->m_icattr) return FALSE;
+    if (!win->m_icattr) return;
 
     gint width, height;
     GdkEventMask mask;
@@ -2376,8 +2431,6 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
               gdk_im_begin (win->m_ic, widget->window);
       }
 #endif // HAVE_XIM
-
-    return FALSE;
 }
 }
 
@@ -2709,7 +2762,7 @@ void wxWindowGTK::PostCreation()
             g_signal_connect (m_wxwindow, "expose_event",
                               G_CALLBACK (gtk_window_expose_callback), this);
 
-            // gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
+            gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
         }
 
         // Create input method handler
@@ -2733,10 +2786,20 @@ void wxWindowGTK::PostCreation()
         if (m_focusWidget == NULL)
             m_focusWidget = m_widget;
 
-        g_signal_connect (m_focusWidget, "focus_in_event",
+        if (m_wxwindow)
+        {
+            g_signal_connect (m_focusWidget, "focus_in_event",
+                          G_CALLBACK (gtk_window_focus_in_callback), this);
+            g_signal_connect (m_focusWidget, "focus_out_event",
+                                G_CALLBACK (gtk_window_focus_out_callback), this);
+        }
+        else
+        {
+            g_signal_connect_after (m_focusWidget, "focus_in_event",
                           G_CALLBACK (gtk_window_focus_in_callback), this);
-        g_signal_connect_after (m_focusWidget, "focus_out_event",
+            g_signal_connect_after (m_focusWidget, "focus_out_event",
                                 G_CALLBACK (gtk_window_focus_out_callback), this);
+        }
     }
 
     // connect to the various key and mouse handlers
@@ -2850,9 +2913,46 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         y = currentY;
     AdjustForParentClientOrigin(x, y, sizeFlags);
 
-    if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
+    // calculate the best size if we should auto size the window
+    if ( ((sizeFlags & wxSIZE_AUTO_WIDTH) && width == -1) ||
+         ((sizeFlags & wxSIZE_AUTO_HEIGHT) && height == -1) )
     {
-        /* don't set the size for children of wxNotebook, just take the values. */
+        const wxSize sizeBest = GetBestSize();
+        if ( (sizeFlags & wxSIZE_AUTO_WIDTH) && width == -1 )
+            width = sizeBest.x;
+        if ( (sizeFlags & wxSIZE_AUTO_HEIGHT) && height == -1 )
+            height = sizeBest.y;
+    }
+
+    if (width != -1)
+        m_width = width;
+    if (height != -1)
+        m_height = height;
+
+    int minWidth  = GetMinWidth(),
+        minHeight = GetMinHeight(),
+        maxWidth  = GetMaxWidth(),
+        maxHeight = GetMaxHeight();
+
+    if ((minWidth  != -1) && (m_width  < minWidth )) m_width  = minWidth;
+    if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
+    if ((maxWidth  != -1) && (m_width  > maxWidth )) m_width  = maxWidth;
+    if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
+
+#if wxUSE_TOOLBAR_NATIVE
+    if (wxDynamicCast(GetParent(), wxToolBar))
+    {
+       // don't take the x,y values, they're wrong because toolbar sets them
+       GtkWidget  *widget = GTK_WIDGET(m_widget);
+       gtk_widget_set_size_request (widget, m_width, m_height);
+       if (GTK_WIDGET_VISIBLE (widget))
+            gtk_widget_queue_resize (widget);
+    }
+    else 
+#endif
+    if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
+    {
+        // don't set the size for children of wxNotebook, just take the values.
         m_x = x;
         m_y = y;
         m_width = width;
@@ -2872,32 +2972,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
             m_y = y + pizza->yoffset;
         }
 
-        // calculate the best size if we should auto size the window
-        if ( ((sizeFlags & wxSIZE_AUTO_WIDTH) && width == -1) ||
-                ((sizeFlags & wxSIZE_AUTO_HEIGHT) && height == -1) )
-        {
-            const wxSize sizeBest = GetBestSize();
-            if ( (sizeFlags & wxSIZE_AUTO_WIDTH) && width == -1 )
-                width = sizeBest.x;
-            if ( (sizeFlags & wxSIZE_AUTO_HEIGHT) && height == -1 )
-                height = sizeBest.y;
-        }
-
-        if (width != -1)
-            m_width = width;
-        if (height != -1)
-            m_height = height;
-
-        int minWidth = GetMinWidth(),
-            minHeight = GetMinHeight(),
-            maxWidth = GetMaxWidth(),
-            maxHeight = GetMaxHeight();
-
-        if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
-        if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
-        if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
-        if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
-
         int left_border = 0;
         int right_border = 0;
         int top_border = 0;
@@ -3652,6 +3726,39 @@ void wxWindowGTK::WarpPointer( int x, int y )
         gdk_window_warp_pointer( window, x, y );
 }
 
+static bool wxScrollAdjust(GtkAdjustment* adj, double change)
+{
+    double value_start = adj->value;
+    double value = value_start + change;
+    double upper = adj->upper - adj->page_size;
+    if (value > upper)
+    {
+        value = upper;
+    }
+    // Lower bound will be checked by gtk_adjustment_set_value
+    gtk_adjustment_set_value(adj, value);
+    return adj->value != value_start;
+}
+
+bool wxWindowGTK::ScrollLines(int lines)
+{
+    return
+        m_vAdjust != NULL &&
+        wxScrollAdjust(m_vAdjust, lines * m_vAdjust->step_increment);
+}
+
+bool wxWindowGTK::ScrollPages(int pages)
+{
+    return
+        m_vAdjust != NULL &&
+        wxScrollAdjust(m_vAdjust, pages * m_vAdjust->page_increment);
+}
+
+void wxWindowGTK::SetVScrollAdjustment(GtkAdjustment* adj)
+{
+    wxASSERT(m_vAdjust == NULL);
+    m_vAdjust = adj;
+}
 
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {