]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
tweaks
[wxWidgets.git] / src / gtk / window.cpp
index 65b0886c758f52a941255bec85a3d1bfeda1b67d..abd0171fe187c669ab565c4c1ab1ff07aafa9f93 100644 (file)
@@ -78,8 +78,6 @@
     #undef HAVE_XIM
 #endif
 
-extern GtkContainerClass *pizza_parent_class;
-
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
@@ -404,13 +402,9 @@ gtk_window_own_expose_callback( GtkWidget *widget,
                                 GdkEventExpose *gdk_event,
                                 wxWindowGTK *win )
 {
-    if (gdk_event->count > 0) return FALSE;
-
-    draw_frame( widget, win );
-
-    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
-    return TRUE;
+    if (gdk_event->count == 0)
+        draw_frame(widget, win);
+    return false;
 }
 }
 
@@ -486,6 +480,7 @@ gtk_window_expose_callback( GtkWidget *widget,
     GtkPizza *pizza = GTK_PIZZA( widget );
     if (gdk_event->window != pizza->bin_window) return FALSE;
 
+
 #if 0
     if (win->GetName())
     {
@@ -515,10 +510,7 @@ gtk_window_expose_callback( GtkWidget *widget,
 
     win->GtkSendPaintEvents();
 
-
     // Let parent window draw window-less widgets
-    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
     return FALSE;
 }
 }
@@ -1244,7 +1236,7 @@ gtk_window_key_release_callback( GtkWidget *widget,
         return FALSE;
     }
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 }
 
@@ -1282,6 +1274,13 @@ template<typename T> void InitMouseEvent(wxWindowGTK *win,
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = (wxCoord)gdk_event->x - pt.x;
     event.m_y = (wxCoord)gdk_event->y - pt.y;
+    
+    if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft))
+    {
+        // origin in the upper right corner
+        int window_width = gtk_pizza_get_rtl_offset( GTK_PIZZA(win->m_wxwindow) );
+        event.m_x = window_width - event.m_x;
+    }
 
     event.SetEventObject( win );
     event.SetId( win->GetId() );
@@ -1330,8 +1329,8 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
     if (win->m_wxwindow)
     {
         GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-        xx += pizza->xoffset;
-        yy += pizza->yoffset;
+        xx += gtk_pizza_get_xoffset( pizza );
+        yy += gtk_pizza_get_yoffset( pizza );
     }
 
     wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
@@ -1390,6 +1389,12 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
 // common event handlers helpers
 // ----------------------------------------------------------------------------
 
+bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const
+{
+    // nothing special at this level
+    return GetEventHandler()->ProcessEvent(event);
+}
+
 int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
 {
     DEBUG_MAIN_THREAD
@@ -1594,7 +1599,7 @@ gtk_window_button_press_callback( GtkWidget *widget,
     event.SetEventObject( win );
     event.SetId( win->GetId() );
 
-    if (win->GetEventHandler()->ProcessEvent( event ))
+    if (win->GTKProcessEvent( event ))
     {
         return TRUE;
     }
@@ -1613,7 +1618,7 @@ gtk_window_button_press_callback( GtkWidget *widget,
             win->GetId(),
             win->ClientToScreen(event.GetPosition()));
         evtCtx.SetEventObject(win);
-        return win->GetEventHandler()->ProcessEvent(evtCtx);
+        return win->GTKProcessEvent(evtCtx);
     }
 
     return FALSE;
@@ -1666,7 +1671,7 @@ gtk_window_button_release_callback( GtkWidget *widget,
     event.SetEventObject( win );
     event.SetId( win->GetId() );
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1711,7 +1716,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
                                                         : wxEVT_LEAVE_WINDOW);
             InitMouseEvent(win, eventM, gdk_event);
             eventM.SetEventObject(win);
-            win->GetEventHandler()->ProcessEvent(eventM);
+            win->GTKProcessEvent(eventM);
         }
     }
     else // no capture
@@ -1726,15 +1731,13 @@ gtk_window_motion_notify_callback( GtkWidget *widget,
     if ( !g_captureWindow )
     {
         wxSetCursorEvent cevent( event.m_x, event.m_y );
-        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        if (win->GTKProcessEvent( cevent ))
         {
-            // Rewrite cursor handling here (away from idle).
             win->SetCursor( cevent.GetCursor() );
-            win->GTKUpdateCursor();
         }
     }
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1779,7 +1782,7 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
     event.SetId( win->GetId() );
     event.SetTimestamp( gdk_event->time );
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1790,7 +1793,7 @@ static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win)
 {
     wxContextMenuEvent event(wxEVT_CONTEXT_MENU, win->GetId(), wxPoint(-1, -1));
     event.SetEventObject(win);
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1901,7 +1904,7 @@ gtk_window_focus_out_callback( GtkWidget *widget,
         wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
         event.SetEventObject( win );
 
-        (void)win->GetEventHandler()->ProcessEvent( event );
+        (void)win->GTKProcessEvent( event );
 
         ret = TRUE;
     }
@@ -1943,15 +1946,13 @@ gtk_window_enter_callback( GtkWidget *widget,
     if ( !g_captureWindow )
     {
         wxSetCursorEvent cevent( event.m_x, event.m_y );
-        if (win->GetEventHandler()->ProcessEvent( cevent ))
+        if (win->GTKProcessEvent( cevent ))
         {
-            // Rewrite cursor handling here (away from idle).
             win->SetCursor( cevent.GetCursor() );
-            win->GTKUpdateCursor();
         }
     }
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1990,7 +1991,7 @@ gtk_window_leave_callback( GtkWidget *widget,
     event.m_x = x + pt.x;
     event.m_y = y + pt.y;
 
-    return win->GetEventHandler()->ProcessEvent(event);
+    return win->GTKProcessEvent(event);
 }
 
 //-----------------------------------------------------------------------------
@@ -2015,7 +2016,7 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
         event.SetEventObject(win);
 
         win->m_blockValueChanged[dir] = true;
-        win->GetEventHandler()->ProcessEvent(event);
+        win->GTKProcessEvent(event);
         win->m_blockValueChanged[dir] = false;
     }
 }
@@ -2052,7 +2053,7 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win)
                                         win->ScrollDirFromRange(range));
         wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
         event.SetEventObject(win);
-        win->GetEventHandler()->ProcessEvent(event);
+        win->GTKProcessEvent(event);
     }
 }
 
@@ -2104,7 +2105,7 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
-    win->GetEventHandler()->ProcessEvent( event );
+    win->GTKProcessEvent( event );
 }
 
 //-----------------------------------------------------------------------------
@@ -2113,7 +2114,7 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
 static
 void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
-                               GtkAllocation *WXUNUSED(alloc),
+                               GtkAllocation *alloc,
                                wxWindow *win )
 {
     if (g_isIdle)
@@ -2125,6 +2126,19 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
     if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
         return;
 
+#if 0
+        wxPrintf( wxT("size_allocate ") );
+        if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
+            wxPrintf( win->GetClassInfo()->GetClassName() );
+        wxPrintf( wxT(" %d %d %d %d\n"),
+                alloc->x,
+                alloc->y,
+                alloc->width,
+                alloc->height );
+#endif
+                
+    GTK_PIZZA(win->m_wxwindow)->m_width = win->GetClientSize().x;
+
     win->m_oldClientWidth = client_width;
     win->m_oldClientHeight = client_height;
 
@@ -2132,7 +2146,7 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
     {
         wxSizeEvent event( win->GetSize(), win->GetId() );
         event.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( event );
+        win->GTKProcessEvent( event );
     }
 }
 
@@ -2288,8 +2302,8 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
     /* the window might have been scrolled already, do we
        have to adapt the position */
     GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
-    child->m_x += pizza->xoffset;
-    child->m_y += pizza->yoffset;
+    child->m_x += gtk_pizza_get_xoffset( pizza );
+    child->m_y += gtk_pizza_get_yoffset( pizza );
 
     gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
                      GTK_WIDGET(child->m_widget),
@@ -2451,7 +2465,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
 #ifndef __WXUNIVERSAL__
     GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-
+    
     if (HasFlag(wxRAISED_BORDER))
     {
         gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
@@ -2586,12 +2600,11 @@ void wxWindowGTK::PostCreation()
         {
             // these get reported to wxWidgets -> wxPaintEvent
 
-            gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
-
             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 ) );
+            if (GetLayoutDirection() == wxLayout_LeftToRight)
+                gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
         }
 
         // Create input method handler
@@ -2666,7 +2679,7 @@ void wxWindowGTK::PostCreation()
                           this);
     }
 #ifdef GTK_IS_FILE_CHOOSER_BUTTON
-    else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
+    else if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
     {
         // If we connect to the "size_request" signal of a GtkFileChooserButton
         // then that control won't be sized properly when placed inside sizers
@@ -2689,6 +2702,8 @@ void wxWindowGTK::PostCreation()
 
     m_hasVMT = true;
 
+    SetLayoutDirection(wxLayout_Default);
+
     // unless the window was created initially hidden (i.e. Hide() had been
     // called before Create()), we should show it at GTK+ level as well
     if ( IsShown() )
@@ -2728,7 +2743,9 @@ bool wxWindowGTK::Destroy()
 
 void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
 {
+    // inform the parent to perform the move
     gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
+    
 }
 
 void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
@@ -2736,10 +2753,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
     wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") );
 
-/*
-    printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
-*/
-
     if (m_resizing) return; /* I don't like recursions */
     m_resizing = true;
 
@@ -2783,8 +2796,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
        // 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
@@ -2801,13 +2812,13 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
         if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
         {
-            if (x != -1) m_x = x + pizza->xoffset;
-            if (y != -1) m_y = y + pizza->yoffset;
+            if (x != -1) m_x = x + gtk_pizza_get_xoffset( pizza );
+            if (y != -1) m_y = y + gtk_pizza_get_yoffset( pizza );
         }
         else
         {
-            m_x = x + pizza->xoffset;
-            m_y = y + pizza->yoffset;
+            m_x = x + gtk_pizza_get_xoffset( pizza );
+            m_y = y + gtk_pizza_get_yoffset( pizza );
         }
 
         int left_border = 0;
@@ -3018,6 +3029,10 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const
 
         w -= dw;
         h -= dh;
+        if (w < 0)
+            w = 0;
+        if (h < 0)
+            h = 0;
     }
 
     if (width) *width = w;
@@ -3033,8 +3048,30 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const
     if (m_parent && m_parent->m_wxwindow)
     {
         GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
-        dx = pizza->xoffset;
-        dy = pizza->yoffset;
+        dx = gtk_pizza_get_xoffset( pizza );
+        dy = gtk_pizza_get_yoffset( pizza );
+    }
+
+    if (m_x == -1 && m_y == -1)
+    {
+        GdkWindow *source = (GdkWindow *) NULL;
+        if (m_wxwindow)
+            source = GTK_PIZZA(m_wxwindow)->bin_window;
+        else
+            source = m_widget->window;
+
+        if (source)
+        {
+            int org_x = 0;
+            int org_y = 0;
+            gdk_window_get_origin( source, &org_x, &org_y );
+
+            if (GetParent())
+                GetParent()->ScreenToClient(&org_x, &org_y);
+
+            ((wxWindowGTK*) this)->m_x = org_x;
+            ((wxWindowGTK*) this)->m_y = org_y;
+       }
     }
 
     if (x) (*x) = m_x - dx;
@@ -3066,7 +3103,15 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const
         }
     }
 
-    if (x) *x += org_x;
+
+    if (x)
+    {
+        if (GetLayoutDirection() == wxLayout_RightToLeft)
+            *x = (GetClientSize().x - *x) + org_x;
+        else 
+            *x += org_x;
+    }
+    
     if (y) *y += org_y;
 }
 
@@ -3095,7 +3140,13 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const
         }
     }
 
-    if (x) *x -= org_x;
+    if (x)
+    {
+        if (GetLayoutDirection() == wxLayout_RightToLeft)
+            *x = (GetClientSize().x - *x) - org_x;
+        else 
+            *x -= org_x;
+    }
     if (y) *y -= org_y;
 }
 
@@ -3392,6 +3443,8 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
     /* reverse: prevent GTK from deleting the widget arbitrarily */
     gtk_widget_unref( m_widget );
 
+    SetLayoutDirection(wxLayout_Default);
+
     return true;
 }
 
@@ -3426,6 +3479,63 @@ void wxWindowGTK::RemoveChild(wxWindowBase *child)
         wxapp_install_idle_handler();
 }
 
+/* static */
+wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget)
+{
+    return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL
+                ? wxLayout_RightToLeft
+                : wxLayout_LeftToRight;
+}
+
+/* static */
+void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir)
+{
+    wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") );
+
+    gtk_widget_set_direction(GTK_WIDGET(widget),
+                             dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL
+                                                         : GTK_TEXT_DIR_LTR);
+}
+
+wxLayoutDirection wxWindowGTK::GetLayoutDirection() const
+{
+    return GTKGetLayout(m_widget);
+}
+
+void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir)
+{
+    if ( dir == wxLayout_Default )
+    {
+        const wxWindow *const parent = GetParent();
+        if ( parent )
+        {
+            // inherit layout from parent.
+            dir = parent->GetLayoutDirection();
+        }
+        else // no parent, use global default layout
+        {
+            dir = wxTheApp->GetLayoutDirection();
+        }
+    }
+
+    if ( dir == wxLayout_Default )
+        return;
+
+    GTKSetLayout(m_widget, dir);
+    
+    if (m_wxwindow)
+        GTKSetLayout(m_wxwindow, dir);
+}
+
+wxCoord
+wxWindowGTK::AdjustForLayoutDirection(wxCoord x,
+                                      wxCoord WXUNUSED(width),
+                                      wxCoord WXUNUSED(widthTotal)) const
+{
+    // We now mirrors the coordinates of RTL windows in GtkPizza
+    return x;
+}
+
 void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move)
 {
     wxWindowBase::DoMoveInTabOrder(win, move);
@@ -3536,15 +3646,12 @@ void wxWindowGTK::Lower()
 
 bool wxWindowGTK::SetCursor( const wxCursor &cursor )
 {
-    wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
-
-    if (cursor == m_cursor)
-       return false;
+    if ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) )
+        return false;
 
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    GTKUpdateCursor();
 
-    return wxWindowBase::SetCursor( cursor.Ok() ? cursor : *wxSTANDARD_CURSOR );
+    return true;
 }
 
 void wxWindowGTK::GTKUpdateCursor()
@@ -3655,13 +3762,15 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
             gdk_rect.y = rect->y;
             gdk_rect.width = rect->width;
             gdk_rect.height = rect->height;
+            if (GetLayoutDirection() == wxLayout_RightToLeft)
+                gdk_rect.x = GetClientSize().x - gdk_rect.x - gdk_rect.width;
             p = &gdk_rect;
         }
         else // invalidate everything
         {
             p = NULL;
         }
-
+        
         gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE );
     }
 }
@@ -3695,6 +3804,20 @@ void wxWindowGTK::GtkUpdate()
     }
 }
 
+bool wxWindowGTK::DoIsExposed( int x, int y ) const
+{
+    return m_updateRegion.Contains(x, y) != wxOutRegion;
+}
+
+
+bool wxWindowGTK::DoIsExposed( int x, int y, int w, int h ) const
+{
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+        return m_updateRegion.Contains(x-w, y, w, h) != wxOutRegion;
+    else
+        return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
+}
+
 void wxWindowGTK::GtkSendPaintEvents()
 {
     if (!m_wxwindow)
@@ -3706,6 +3829,34 @@ void wxWindowGTK::GtkSendPaintEvents()
     // Clip to paint region in wxClientDC
     m_clipPaintRegion = true;
 
+    wxRegion maybe_rtl_region = m_updateRegion;
+    
+#if 0
+    if (GetLayoutDirection() == wxLayout_RightToLeft)
+    {
+        maybe_rtl_region.Clear();
+        
+        gint width;
+        gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window,
+                                 NULL, NULL, &width, NULL, NULL );
+        
+        wxRegionIterator upd( m_updateRegion );
+        while (upd)
+        {
+            wxRect rect;
+            rect.x = upd.GetX();
+            rect.y = upd.GetY();
+            rect.width = upd.GetWidth();
+            rect.height = upd.GetHeight();
+            
+            rect.x = width - rect.x - rect.width;
+            maybe_rtl_region.Union( rect );
+            
+            ++upd;
+        }
+    }
+#endif
+    
     // widget to draw on
     GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
 
@@ -3741,8 +3892,9 @@ void wxWindowGTK::GtkSendPaintEvents()
         }
     }
     else
-
     {
+        m_updateRegion = maybe_rtl_region;
+    
         wxWindowDC dc( (wxWindow*)this );
         dc.SetClippingRegion( m_updateRegion );
 
@@ -3752,6 +3904,8 @@ void wxWindowGTK::GtkSendPaintEvents()
         GetEventHandler()->ProcessEvent(erase_event);
     }
 
+    m_updateRegion = maybe_rtl_region;
+        
     wxNcPaintEvent nc_paint_event( GetId() );
     nc_paint_event.SetEventObject( this );
     GetEventHandler()->ProcessEvent( nc_paint_event );