]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
don't give an error when editing of the items label is cancelled (patch 1482176)
[wxWidgets.git] / src / gtk / window.cpp
index eda96a1e107c1b46e243f464da55b5dff1cf7b84..d7d79ebf1a2a0493bbfed6c08613095f1ca007a9 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        gtk/window.cpp
+// Name:        src/gtk/window.cpp
 // Purpose:
 // Author:      Robert Roebling
 // Id:          $Id$
 #endif
 
 #include "wx/window.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/app.h"
+    #include "wx/utils.h"
+    #include "wx/frame.h"
+#endif
+
 #include "wx/dcclient.h"
-#include "wx/frame.h"
-#include "wx/app.h"
 #include "wx/layout.h"
-#include "wx/utils.h"
 #include "wx/dialog.h"
 #include "wx/msgdlg.h"
 #include "wx/module.h"
 
 #include "wx/menu.h"
 #include "wx/statusbr.h"
-#include "wx/intl.h"
 #include "wx/settings.h"
-#include "wx/log.h"
 #include "wx/fontutil.h"
-#include "wx/stattext.h"
 
 #ifdef __WXDEBUG__
     #include "wx/thread.h"
@@ -270,7 +273,7 @@ gdk_window_warp_pointer (GdkWindow      *window,
                          gint            y)
 {
   if (!window)
-    window = GDK_ROOT_PARENT();
+    window = gdk_get_default_root_window();
 
   if (!GDK_WINDOW_DESTROYED(window))
   {
@@ -282,13 +285,6 @@ gdk_window_warp_pointer (GdkWindow      *window,
   }
 }
 
-//-----------------------------------------------------------------------------
-// idle system
-//-----------------------------------------------------------------------------
-
-extern void wxapp_install_idle_handler();
-extern bool g_isIdle;
-
 //-----------------------------------------------------------------------------
 // local code (see below)
 //-----------------------------------------------------------------------------
@@ -317,6 +313,35 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win)
     return (wxWindow *)NULL;
 }
 
+static void GetScrollbarWidth(GtkWidget* widget, int& w, int& h)
+{
+    GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
+    GtkScrolledWindowClass* scroll_class = GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT_GET_CLASS(scroll_window));
+    GtkRequisition scroll_req;
+
+    w = 0;
+    if (scroll_window->vscrollbar_visible)
+    {
+        scroll_req.width = 2;
+        scroll_req.height = 2;
+        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
+            (scroll_window->vscrollbar, &scroll_req );
+        w = scroll_req.width +
+            scroll_class->scrollbar_spacing;
+    }
+
+    h = 0;
+    if (scroll_window->hscrollbar_visible)
+    {
+        scroll_req.width = 2;
+        scroll_req.height = 2;
+        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
+            (scroll_window->hscrollbar, &scroll_req );
+        h = scroll_req.height +
+            scroll_class->scrollbar_spacing;
+    }
+}
+
 static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 {
     // wxUniversal widgets draw the borders and scrollbars themselves
@@ -329,33 +354,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
 
     if (win->m_hasScrolling)
     {
-        GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
-
-        GtkRequisition vscroll_req;
-        vscroll_req.width = 2;
-        vscroll_req.height = 2;
-        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
-            (scroll_window->vscrollbar, &vscroll_req );
-
-        GtkRequisition hscroll_req;
-        hscroll_req.width = 2;
-        hscroll_req.height = 2;
-        (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
-            (scroll_window->hscrollbar, &hscroll_req );
-
-        GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
-
-        if (scroll_window->vscrollbar_visible)
-        {
-            dw += vscroll_req.width;
-            dw += scroll_class->scrollbar_spacing;
-        }
-
-        if (scroll_window->hscrollbar_visible)
-        {
-            dh += hscroll_req.height;
-            dh += scroll_class->scrollbar_spacing;
-        }
+        GetScrollbarWidth(widget, dw, dh);
     }
 
     int dx = 0;
@@ -398,7 +397,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win )
         gdk_draw_rectangle( widget->window, gc, FALSE,
                          dx, dy,
                          widget->allocation.width-dw-1, widget->allocation.height-dh-1 );
-        gdk_gc_unref( gc );
+        g_object_unref (G_OBJECT (gc));
         return;
     }
 #endif // __WXUNIVERSAL__
@@ -659,11 +658,11 @@ static long wxTranslateKeySymToWXKey(KeySym keysym, bool isChar)
             break;
 
         case GDK_Prior:     // == GDK_Page_Up
-            key_code = WXK_PRIOR;
+            key_code = WXK_PAGEUP;
             break;
 
         case GDK_Next:      // == GDK_Page_Down
-            key_code = WXK_NEXT;
+            key_code = WXK_PAGEDOWN;
             break;
 
         case GDK_End:
@@ -742,11 +741,11 @@ static long wxTranslateKeySymToWXKey(KeySym keysym, bool isChar)
             break;
 
         case GDK_KP_Prior: // == GDK_KP_Page_Up
-            key_code = isChar ? WXK_PRIOR : WXK_NUMPAD_PRIOR;
+            key_code = isChar ? WXK_PAGEUP : WXK_NUMPAD_PAGEUP;
             break;
 
         case GDK_KP_Next: // == GDK_KP_Page_Down
-            key_code = isChar ? WXK_NEXT : WXK_NUMPAD_NEXT;
+            key_code = isChar ? WXK_PAGEDOWN : WXK_NUMPAD_PAGEDOWN;
             break;
 
         case GDK_KP_End:
@@ -844,10 +843,6 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
     event.m_rawFlags = 0;
 #if wxUSE_UNICODE
     event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
-    if ( gdk_event->type == GDK_KEY_PRESS ||  gdk_event->type == GDK_KEY_RELEASE )
-    {
-        event.m_uniChar = toupper(event.m_uniChar);
-    }
 #endif
     wxGetMousePosition( &x, &y );
     win->ScreenToClient( &x, &y );
@@ -955,6 +950,12 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
     wxFillOtherKeyEventFields(event, win, gdk_event);
 
     event.m_keyCode = key_code;
+#if wxUSE_UNICODE
+    if ( gdk_event->type == GDK_KEY_PRESS ||  gdk_event->type == GDK_KEY_RELEASE )
+    {
+        event.m_uniChar = key_code;
+    }
+#endif
 
     return true;
 }
@@ -1204,13 +1205,8 @@ gtk_wxwindow_commit_cb (GtkIMContext *context,
                                   window, window->m_imData->lastKeyEvent);
     }
 
-#if wxUSE_UNICODE
-    const wxWCharBuffer data = wxConvUTF8.cMB2WC( (char*)str );
-#else
-    const wxWCharBuffer wdata = wxConvUTF8.cMB2WC( (char*)str );
-    const wxCharBuffer data = wxConvLocal.cWC2MB( wdata );
-#endif // wxUSE_UNICODE
-    if( !(const wxChar*)data )
+    const wxWxCharBuffer data(wxGTK_CONV_BACK(str));
+    if( !data )
         return;
 
     bool ret = false;
@@ -1595,6 +1591,10 @@ gtk_window_button_press_callback( GtkWidget *widget,
     if ( !g_captureWindow )
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
 
+    // reset the event object and id in case win changed.
+    event.SetEventObject( win );
+    event.SetId( win->GetId() );
+
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         g_signal_stop_emission_by_name (widget, "button_press_event");
@@ -1675,6 +1675,10 @@ gtk_window_button_release_callback( GtkWidget *widget,
     if ( !g_captureWindow )
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
 
+    // reset the event object and id in case win changed.
+    event.SetEventObject( win );
+    event.SetId( win->GetId() );
+
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         g_signal_stop_emission_by_name (widget, "button_release_event");
@@ -1750,6 +1754,10 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
     else // no capture
     {
         win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
+
+        // reset the event object and id in case win changed.
+        event.SetEventObject( win );
+        event.SetId( win->GetId() );
     }
 
     if ( !g_captureWindow )
@@ -1760,7 +1768,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
             // Rewrite cursor handling here (away from idle).
         }
     }
-    
+
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         g_signal_stop_emission_by_name (widget, "motion_notify_event");
@@ -2029,7 +2037,7 @@ gtk_window_enter_callback( GtkWidget *widget,
             // Rewrite cursor handling here (away from idle).
         }
     }
-    
+
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
        g_signal_stop_emission_by_name (widget, "enter_notify_event");
@@ -2332,7 +2340,7 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
     {
         gint width, height;
 
-        gdk_window_get_size (widget->window, &width, &height);
+        gdk_drawable_get_size (widget->window, &width, &height);
         win->m_icattr->preedit_area.width = width;
         win->m_icattr->preedit_area.height = height;
         gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
@@ -2403,7 +2411,7 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
                 break;
             }
 
-            gdk_window_get_size (widget->window, &width, &height);
+            gdk_drawable_get_size (widget->window, &width, &height);
 
             attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
             attr->spot_location.x = 0;
@@ -2948,7 +2956,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
        if (GTK_WIDGET_VISIBLE (widget))
             gtk_widget_queue_resize (widget);
     }
-    else 
+    else
 #endif
     if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
     {
@@ -3095,135 +3103,76 @@ void wxWindowGTK::DoSetClientSize( int width, int height )
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    if (!m_wxwindow)
-    {
-        SetSize( width, height );
-    }
-    else
+    if (m_wxwindow)
     {
         int dw = 0;
         int dh = 0;
 
+        if (m_hasScrolling)
+        {
+            GetScrollbarWidth(m_widget, dw, dh);
+        }
+
 #ifndef __WXUNIVERSAL__
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
-            /* when using GTK 1.2 we set the shadow border size to 2 */
+            // shadow border size is 2
             dw += 2 * 2;
             dh += 2 * 2;
         }
         if (HasFlag(wxSIMPLE_BORDER))
         {
-            /* when using GTK 1.2 we set the simple border size to 1 */
+            // simple border size is 1
             dw += 1 * 2;
             dh += 1 * 2;
         }
 #endif // __WXUNIVERSAL__
 
-        if (m_hasScrolling)
-        {
-            GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-
-            GtkRequisition vscroll_req;
-            vscroll_req.width = 2;
-            vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
-                (scroll_window->vscrollbar, &vscroll_req );
-
-            GtkRequisition hscroll_req;
-            hscroll_req.width = 2;
-            hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
-                (scroll_window->hscrollbar, &hscroll_req );
-
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
-
-            if (scroll_window->vscrollbar_visible)
-            {
-                dw += vscroll_req.width;
-                dw += scroll_class->scrollbar_spacing;
-            }
-
-            if (scroll_window->hscrollbar_visible)
-            {
-                dh += hscroll_req.height;
-                dh += scroll_class->scrollbar_spacing;
-            }
-        }
-
-       SetSize( width+dw, height+dh );
+        width += dw;
+        height += dh;
     }
+
+    SetSize(width, height);
 }
 
 void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
 
-    if (!m_wxwindow)
-    {
-        if (width) (*width) = m_width;
-        if (height) (*height) = m_height;
-    }
-    else
+    int w = m_width;
+    int h = m_height;
+
+    if (m_wxwindow)
     {
         int dw = 0;
         int dh = 0;
 
+        if (m_hasScrolling)
+        {
+            GetScrollbarWidth(m_widget, dw, dh);
+        }
+
 #ifndef __WXUNIVERSAL__
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
-            /* when using GTK 1.2 we set the shadow border size to 2 */
+            // shadow border size is 2
             dw += 2 * 2;
             dh += 2 * 2;
         }
         if (HasFlag(wxSIMPLE_BORDER))
         {
-            /* when using GTK 1.2 we set the simple border size to 1 */
+            // simple border size is 1
             dw += 1 * 2;
             dh += 1 * 2;
         }
 #endif // __WXUNIVERSAL__
 
-        if (m_hasScrolling)
-        {
-            GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-
-            GtkRequisition vscroll_req;
-            vscroll_req.width = 2;
-            vscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
-                (scroll_window->vscrollbar, &vscroll_req );
-
-            GtkRequisition hscroll_req;
-            hscroll_req.width = 2;
-            hscroll_req.height = 2;
-            (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
-                (scroll_window->hscrollbar, &hscroll_req );
-
-            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
-
-            if (scroll_window->vscrollbar_visible)
-            {
-                dw += vscroll_req.width;
-                dw += scroll_class->scrollbar_spacing;
-            }
-
-            if (scroll_window->hscrollbar_visible)
-            {
-                dh += hscroll_req.height;
-                dh += scroll_class->scrollbar_spacing;
-            }
-        }
-
-        if (width) (*width) = m_width - dw;
-        if (height) (*height) = m_height - dh;
+        w -= dw;
+        h -= dh;
     }
 
-/*
-    printf( "GetClientSize, name %s ", GetName().c_str() );
-    if (width) printf( " width = %d", (*width) );
-    if (height) printf( " height = %d", (*height) );
-    printf( "\n" );
-*/
+    if (width) *width = w;
+    if (height) *height = h;
 }
 
 void wxWindowGTK::DoGetPosition( int *x, int *y ) const
@@ -3449,14 +3398,9 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
     PangoLayout *layout = pango_layout_new(context);
     pango_layout_set_font_description(layout, desc);
     {
-#if wxUSE_UNICODE
-        const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
-        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
-#else
-        const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
-        const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
-        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
-#endif
+        const wxCharBuffer data = wxGTK_CONV( string );
+        if ( data )
+            pango_layout_set_text(layout, data, strlen(data));
     }
 
     PangoRectangle rect;
@@ -3611,44 +3555,62 @@ void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
         wxapp_install_idle_handler();
 }
 
+bool wxWindowGTK::GTKWidgetNeedsMnemonic() const
+{
+    // none needed by default
+    return false;
+}
+
+void wxWindowGTK::GTKWidgetDoSetMnemonic(GtkWidget* WXUNUSED(w))
+{
+    // nothing to do by default since none is needed
+}
+
 void wxWindowGTK::RealizeTabOrder()
 {
     if (m_wxwindow)
     {
         if ( !m_children.empty() )
         {
-#if wxUSE_STATTEXT
             // we don't only construct the correct focus chain but also use
-            // this opportunity to update the mnemonic widgets for all labels
-            //
-            // it would be nice to extract this code from here and put it in
-            // stattext.cpp to reduce dependencies but there is no really easy
-            // way to do it unfortunately
-            wxStaticText *lastLabel = NULL;
-#endif // wxUSE_STATTEXT
+            // this opportunity to update the mnemonic widgets for the widgets
+            // that need them
 
             GList *chain = NULL;
+            wxWindowGTK* mnemonicWindow = NULL;
 
             for ( wxWindowList::const_iterator i = m_children.begin();
                   i != m_children.end();
                   ++i )
             {
                 wxWindowGTK *win = *i;
-#if wxUSE_STATTEXT
-                if ( lastLabel )
+
+                if ( mnemonicWindow )
                 {
                     if ( win->AcceptsFocusFromKeyboard() )
                     {
-                        GtkLabel *l = GTK_LABEL(lastLabel->m_widget);
-                        gtk_label_set_mnemonic_widget(l, win->m_widget);
-                        lastLabel = NULL;
+                        // wxComboBox et al. needs to focus on on a different
+                        // widget than m_widget, so if the main widget isn't
+                        // focusable try the connect widget
+                        GtkWidget* w = win->m_widget;
+                        if ( !GTK_WIDGET_CAN_FOCUS(w) )
+                        {
+                            w = win->GetConnectWidget();
+                            if ( !GTK_WIDGET_CAN_FOCUS(w) )
+                                w = NULL;
+                        }
+
+                        if ( w )
+                        {
+                            mnemonicWindow->GTKWidgetDoSetMnemonic(w);
+                            mnemonicWindow = NULL;
+                        }
                     }
                 }
-                else // check if this one is a label
+                else if ( win->GTKWidgetNeedsMnemonic() )
                 {
-                    lastLabel = wxDynamicCast(win, wxStaticText);
+                    mnemonicWindow = win;
                 }
-#endif // wxUSE_STATTEXT
 
                 chain = g_list_prepend(chain, win->m_widget);
             }
@@ -4133,7 +4095,7 @@ void wxWindowGTK::DoCaptureMouse()
 
     wxCHECK_RET( window, _T("CaptureMouse() failed") );
 
-    wxCursor* cursor = & m_cursor;
+    const wxCursor* cursor = &m_cursor;
     if (!cursor->Ok())
         cursor = wxSTANDARD_CURSOR;
 
@@ -4332,6 +4294,29 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
     m_clipPaintRegion = false;
 }
 
+void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle)
+{
+    //RN: Note that static controls usually have no border on gtk, so maybe
+    //it makes sense to treat that as simply no border at the wx level
+    //as well...
+    if (!(wxstyle & wxNO_BORDER) && !(wxstyle & wxBORDER_STATIC))
+    {
+        GtkShadowType gtkstyle;
+
+        if(wxstyle & wxBORDER_RAISED)
+            gtkstyle = GTK_SHADOW_OUT;
+        else if (wxstyle & wxBORDER_SUNKEN)
+            gtkstyle = GTK_SHADOW_IN;
+        else if (wxstyle & wxBORDER_DOUBLE)
+            gtkstyle = GTK_SHADOW_ETCHED_IN;
+        else //default
+            gtkstyle = GTK_SHADOW_IN;
+
+        gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(w),
+                                             gtkstyle );
+    }
+}
+
 void wxWindowGTK::SetWindowStyleFlag( long style )
 {
     // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already
@@ -4406,7 +4391,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
 
 bool wxWinModule::OnInit()
 {
-    // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
+    // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() );
     // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
 
     return true;
@@ -4415,6 +4400,5 @@ bool wxWinModule::OnInit()
 void wxWinModule::OnExit()
 {
     if (g_eraseGC)
-        gdk_gc_unref( g_eraseGC );
+        g_object_unref (G_OBJECT (g_eraseGC));
 }
-