X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/94633ad9f171fefbe96b7cde1aa0a29090e627bc..de5fadb41534fca448bd68d3ff942f80efa87f76:/src/gtk1/window.cpp diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index 21dbf1774a..dbbd436919 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -54,8 +54,7 @@ #include -#include -#include +#include "wx/gtk/private.h" #include #include #include @@ -65,6 +64,12 @@ #include "wx/gtk/win_gtk.h" +#ifdef __WXGTK20__ + #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d)) +#else + #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d)) +#endif + //----------------------------------------------------------------------------- // documentation on internals //----------------------------------------------------------------------------- @@ -385,34 +390,34 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) if (win->m_hasScrolling) { - GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget); + 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 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 ); + 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) ); + 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->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 (scroll_window->hscrollbar_visible) + { + dh += hscroll_req.height; + dh += scroll_class->scrollbar_spacing; + } +} int dx = 0; int dy = 0; @@ -775,6 +780,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, } */ +#ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); if (win->GetThemeEnabled()) @@ -794,74 +800,15 @@ static int gtk_window_expose_callback( GtkWidget *widget, (char *)"base", 0, 0, -1, -1); } +#endif win->GetUpdateRegion().Union( gdk_event->area.x, gdk_event->area.y, gdk_event->area.width, gdk_event->area.height ); - if (gdk_event->count == 0) - { - win->m_clipPaintRegion = TRUE; - - wxWindowDC dc(win); - dc.SetClippingRegion(win->GetUpdateRegion()); - wxEraseEvent eevent( win->GetId(), &dc ); - eevent.SetEventObject( win ); -#if 1 - (void)win->GetEventHandler()->ProcessEvent(eevent); -#else // 0 - if (!win->GetEventHandler()->ProcessEvent(eevent)) - { - wxClientDC dc( win ); - dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) ); - dc.SetPen( *wxTRANSPARENT_PEN ); - - wxRegionIterator upd( win->GetUpdateRegion() ); - while (upd) - { - dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); - upd ++; - } - } -#endif // 1/0 - - wxNcPaintEvent eventNc( win->GetId() ); - eventNc.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( eventNc ); - - wxPaintEvent event( win->GetId() ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); - - win->GetUpdateRegion().Clear(); - - win->m_clipPaintRegion = FALSE; - } - - /* The following code will result in all window-less widgets - being redrawn if the wxWindows class is given a chance to - paint *anything* because it will then be allowed to paint - over the window-less widgets */ - GList *children = pizza->children; - while (children) - { - GtkPizzaChild *child = (GtkPizzaChild*) children->data; - children = children->next; - - GdkEventExpose child_event = *gdk_event; - - if (GTK_WIDGET_NO_WINDOW (child->widget) && - GTK_WIDGET_DRAWABLE (child->widget) /* && - gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ ) - { - child_event.area.x = child->widget->allocation.x; - child_event.area.y = child->widget->allocation.y; - child_event.area.width = child->widget->allocation.width; - child_event.area.height = child->widget->allocation.height; - gtk_widget_event (child->widget, (GdkEvent*) &child_event); - } - } + // Actual redrawing takes place in idle time. + win->Update(); return TRUE; } @@ -870,11 +817,11 @@ static int gtk_window_expose_callback( GtkWidget *widget, // "event" of m_wxwindow //----------------------------------------------------------------------------- -/* GTK thinks it is clever and filters out a certain amount of "unneeded" - expose events. We need them, of course, so we override the main event - procedure in GtkWidget by giving our own handler for all system events. - There, we look for expose events ourselves whereas all other events are - handled normally. */ +// GTK thinks it is clever and filters out a certain amount of "unneeded" +// expose events. We need them, of course, so we override the main event +// procedure in GtkWidget by giving our own handler for all system events. +// There, we look for expose events ourselves whereas all other events are +// handled normally. gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, @@ -893,8 +840,8 @@ gint gtk_window_event_event_callback( GtkWidget *widget, // "draw" of m_wxwindow //----------------------------------------------------------------------------- -/* This callback is a complete replacement of the gtk_pizza_draw() function, - which disabled. */ +// This callback is a complete replacement of the gtk_pizza_draw() function, +// which disabled. static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, @@ -905,6 +852,8 @@ static void gtk_window_draw_callback( GtkWidget *widget, if (g_isIdle) wxapp_install_idle_handler(); + // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if + // there are no child windows. if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) && (win->GetChildren().GetCount() == 0)) { @@ -924,6 +873,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, } */ +#ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); if (win->GetThemeEnabled()) @@ -951,62 +901,29 @@ static void gtk_window_draw_callback( GtkWidget *widget, gdk_window_clear_area( pizza->bin_window, rect->x, rect->y, rect->width, rect->height); } - - win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height ); - - win->m_clipPaintRegion = TRUE; - - wxWindowDC dc(win); - dc.SetClippingRegion(win->GetUpdateRegion()); - wxEraseEvent eevent( win->GetId(), &dc ); - eevent.SetEventObject( win ); - -#if 1 - (void)win->GetEventHandler()->ProcessEvent(eevent); -#else - if (!win->GetEventHandler()->ProcessEvent(eevent)) - { - if (!win->GetEventHandler()->ProcessEvent(eevent)) - { - wxClientDC dc( win ); - dc.SetBrush( wxBrush( win->GetBackgroundColour(), wxSOLID ) ); - dc.SetPen( *wxTRANSPARENT_PEN ); - - wxRegionIterator upd( win->GetUpdateRegion() ); - while (upd) - { - dc.DrawRectangle( upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); - upd ++; - } - } - } #endif - wxNcPaintEvent eventNc( win->GetId() ); - eventNc.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( eventNc ); - - wxPaintEvent event( win->GetId() ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); - - win->GetUpdateRegion().Clear(); - - win->m_clipPaintRegion = FALSE; + win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height ); + // Actual redrawing takes place in idle time. + + win->Update(); +#ifndef __WXUNIVERSAL__ + // Redraw child widgets GList *children = pizza->children; while (children) { - GtkPizzaChild *child = (GtkPizzaChild*) children->data; - children = children->next; + GtkPizzaChild *child = (GtkPizzaChild*) children->data; + children = children->next; - GdkRectangle child_area; - if (gtk_widget_intersect (child->widget, rect, &child_area)) - { - gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ ); - } + GdkRectangle child_area; + if (gtk_widget_intersect (child->widget, rect, &child_area)) + { + gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ ); + } } +#endif } //----------------------------------------------------------------------------- @@ -1300,20 +1217,15 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; - if (win->m_wxwindow) + if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus()) { - if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) ) - { - gtk_widget_grab_focus (win->m_wxwindow); - + gtk_widget_grab_focus( win->m_wxwindow ); /* - wxPrintf( wxT("GrabFocus from ") ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - wxPrintf( win->GetClassInfo()->GetClassName() ); - wxPrintf( wxT(".\n") ); + wxPrintf( wxT("GrabFocus from ") ); + if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) + wxPrintf( win->GetClassInfo()->GetClassName() ); + wxPrintf( wxT(".\n") ); */ - - } } wxEventType event_type = wxEVT_NULL; @@ -1736,10 +1648,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, g_focusWindow = win; #if 0 - wxPrintf( "OnSetFocus from " ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - wxPrintf( win->GetClassInfo()->GetClassName() ); - wxPrintf( ".\n" ); + wxLogDebug( wxT("OnSetFocus from %s\n"), win->GetName().c_str() ); #endif // notify the parent keeping track of focus for the kbd navigation @@ -1798,9 +1707,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, // "focus_out_event" //----------------------------------------------------------------------------- -static GtkWidget *gs_widgetLastFocus = NULL; - -static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win ) +static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1810,17 +1717,9 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED if (!win->m_hasVMT) return FALSE; if (g_blockEventsOnDrag) return FALSE; - // VZ: this is really weird but GTK+ seems to call us from inside - // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to - // this widget and then "focus_in". This is totally unexpected and - // completely breaks wxUniv code so ignore this dummy event (we can't - // be losing focus if we're about to acquire it!) - if ( widget == gs_widgetLastFocus ) - { - gs_widgetLastFocus = NULL; - - return FALSE; - } +#if 0 + wxLogDebug( wxT("OnKillFocus from %s"), win->GetName().c_str() ); +#endif if ( !g_activeFrameLostFocus && g_activeFrame ) { @@ -1846,13 +1745,6 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED g_focusWindow = (wxWindowGTK *)NULL; -#if 0 - wxPrintf( "OnKillFocus from " ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - wxPrintf( win->GetClassInfo()->GetClassName() ); - wxPrintf( ".\n" ); -#endif - #ifdef HAVE_XIM if (win->m_ic) gdk_im_end(); @@ -1970,7 +1862,9 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_ // "value_changed" from m_vAdjust //----------------------------------------------------------------------------- -static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win ) +static void gtk_window_vscroll_callback( GtkAdjustment *adjust, + SCROLLBAR_CBACK_ARG + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1986,14 +1880,7 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win win->m_oldVerticalPos = adjust->value; - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); - GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar ); - - wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; - if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; - else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; - else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP; - else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN; + wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget)); int value = (int)(adjust->value+0.5); @@ -2006,7 +1893,9 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win // "value_changed" from m_hAdjust //----------------------------------------------------------------------------- -static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win ) +static void gtk_window_hscroll_callback( GtkAdjustment *adjust, + SCROLLBAR_CBACK_ARG + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -2019,16 +1908,9 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindowGTK *win float diff = adjust->value - win->m_oldHorizontalPos; if (fabs(diff) < 0.2) return; - win->m_oldHorizontalPos = adjust->value; - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); - GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar ); + wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget)); - wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; - if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; - else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; - else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP; - else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN; + win->m_oldHorizontalPos = adjust->value; int value = (int)(adjust->value+0.5); @@ -2052,7 +1934,11 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget, g_blockEventsOnScroll = TRUE; + + // FIXME: there is no 'slider' field in GTK+ 2.0 any more +#ifndef __WXGTK20__ win->m_isScrolling = (gdk_event->window == widget->slider); +#endif return FALSE; } @@ -2454,7 +2340,8 @@ bool wxWindowGTK::Create( wxWindow *parent, gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); #ifndef __WXUNIVERSAL__ -#if (GTK_MINOR_VERSION > 0) + +#if GTK_CHECK_VERSION(1, 2, 0) GtkPizza *pizza = GTK_PIZZA(m_wxwindow); if (HasFlag(wxRAISED_BORDER)) @@ -2473,7 +2360,7 @@ bool wxWindowGTK::Create( wxWindow *parent, { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE ); } -#else // GTK_MINOR_VERSION == 0 +#else // GTK+ 1.0 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport); if (HasFlag(wxRAISED_BORDER)) @@ -2488,17 +2375,18 @@ bool wxWindowGTK::Create( wxWindow *parent, { gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE ); } -#endif // GTK_MINOR_VERSION +#endif // GTK+ > 1.0/<= 1.0 + #endif // __WXUNIVERSAL__ GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); m_acceptsFocus = TRUE; -#if (GTK_MINOR_VERSION == 0) +#if !GTK_CHECK_VERSION(1, 2, 0) // shut the viewport up gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ); gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ); -#endif // GTK_MINOR_VERSION == 0 +#endif // GTK+ 1.0 // I _really_ don't want scrollbars in the beginning m_vAdjust->lower = 0.0; @@ -2821,10 +2709,15 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags if (height == -1) m_height = 26; } - if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; - if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; - if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; - if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + 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 border = 0; int bottom_border = 0; @@ -2872,6 +2765,10 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags void wxWindowGTK::OnInternalIdle() { + // Update invalidated regions. + Update(); + + // Synthetize activate events. if ( g_sendActivateEvent != -1 ) { bool activate = g_sendActivateEvent != 0; @@ -3260,8 +3157,6 @@ void wxWindowGTK::SetFocus() { if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) { - // see comment in gtk_window_focus_out_callback() - gs_widgetLastFocus = m_wxwindow; gtk_widget_grab_focus (m_wxwindow); } } @@ -3273,21 +3168,13 @@ void wxWindowGTK::SetFocus() } else if (GTK_IS_CONTAINER(m_widget)) { - gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD ); + SET_CONTAINER_FOCUS( m_widget, GTK_DIR_TAB_FORWARD ); } else { // ? } } - -#if 0 - wxPrintf( "SetFocus finished in " ); - if (GetClassInfo() && GetClassInfo()->GetClassName()) - wxPrintf( GetClassInfo()->GetClassName() ); - wxPrintf( ".\n" ); -#endif - } bool wxWindowGTK::AcceptsFocus() const @@ -3384,8 +3271,8 @@ void wxWindowGTK::WarpPointer( int x, int y ) { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - /* we provide this function ourselves as it is - missing in GDK (top of this file) */ + // We provide this function ourselves as it is + // missing in GDK (top of this file). GdkWindow *window = (GdkWindow*) NULL; if (m_wxwindow) @@ -3412,86 +3299,144 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) { if (rect) { - gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window, - rect->x, rect->y, - rect->width, rect->height ); + // Schedule for later Updating in ::Update() or ::OnInternalIdle(). + m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height ); } else { - gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window ); + // Schedule for later Updating in ::Update() or ::OnInternalIdle(). + m_clearRegion.Clear(); + m_clearRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height ); } } - /* there is no GTK equivalent of "draw only, don't clear" so we - invent our own in the GtkPizza widget */ - - if (!rect) + if (rect) { if (m_wxwindow) { - -/* - GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - gboolean old_clear = pizza->clear_on_draw; - gtk_pizza_set_clear( pizza, FALSE ); - gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL ); - gtk_pizza_set_clear( pizza, old_clear ); -*/ - GdkEventExpose gdk_event; - gdk_event.type = GDK_EXPOSE; - gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window; - gdk_event.count = 0; - gdk_event.area.x = 0; - gdk_event.area.y = 0; - gdk_event.area.width = m_wxwindow->allocation.width; - gdk_event.area.height = m_wxwindow->allocation.height; - gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this ); + // Schedule for later Updating in ::Update() or ::OnInternalIdle(). + m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height ); } else { - gtk_widget_draw( m_widget, (GdkRectangle*) NULL ); + GdkRectangle gdk_rect; + gdk_rect.x = rect->x; + gdk_rect.y = rect->y; + gdk_rect.width = rect->width; + gdk_rect.height = rect->height; + gtk_widget_draw( m_widget, &gdk_rect ); } } else { - if (m_wxwindow) { -/* - GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - gboolean old_clear = pizza->clear_on_draw; - gtk_pizza_set_clear( pizza, FALSE ); + // Schedule for later Updating in ::Update() or ::OnInternalIdle(). + m_updateRegion.Clear(); + m_updateRegion.Union( 0, 0, m_wxwindow->allocation.width, m_wxwindow->allocation.height ); + } + else + { + gtk_widget_draw( m_widget, (GdkRectangle*) NULL ); + } + } +} - GdkRectangle gdk_rect; - gdk_rect.x = rect->x; - gdk_rect.y = rect->y; - gdk_rect.width = rect->width; - gdk_rect.height = rect->height; - gtk_widget_draw( m_wxwindow, &gdk_rect ); - gtk_window_draw_callback( m_wxwindow, &gdk_rect, this ); +void wxWindowGTK::Update() +{ + if (!m_updateRegion.IsEmpty()) + { + GtkSendPaintEvents(); + } +} - gtk_pizza_set_clear( pizza, old_clear ); -*/ +void wxWindowGTK::GtkSendPaintEvents() +{ + if (!m_wxwindow) + { + m_clearRegion.Clear(); + m_updateRegion.Clear(); + return; + } + + m_clipPaintRegion = TRUE; + + // if (!m_clearRegion.IsEmpty()) // always send an erase event + { + wxWindowDC dc( (wxWindow*)this ); + dc.SetClippingRegion( m_clearRegion ); + + wxEraseEvent erase_event( GetId(), &dc ); + erase_event.SetEventObject( this ); + + if (!GetEventHandler()->ProcessEvent(erase_event)) + { + wxRegionIterator upd( m_clearRegion ); + while (upd) + { + gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window, + upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); + upd ++; + } + } + m_clearRegion.Clear(); + } + + wxNcPaintEvent nc_paint_event( GetId() ); + nc_paint_event.SetEventObject( this ); + GetEventHandler()->ProcessEvent( nc_paint_event ); + + wxPaintEvent paint_event( GetId() ); + paint_event.SetEventObject( this ); + GetEventHandler()->ProcessEvent( paint_event ); + + m_clipPaintRegion = FALSE; + +#ifndef __WXUNIVERSAL__ + // The following code will result in all window-less widgets + // being redrawn because the wxWindows class is allowed to + // paint over the window-less widgets. + + GtkPizza *pizza = GTK_PIZZA(m_wxwindow); + + GList *children = pizza->children; + while (children) + { + GtkPizzaChild *child = (GtkPizzaChild*) children->data; + children = children->next; + + if (GTK_WIDGET_NO_WINDOW (child->widget) && + GTK_WIDGET_DRAWABLE (child->widget)) + { + // Get intersection of widget area and update region + wxRegion region( m_updateRegion ); + GdkEventExpose gdk_event; gdk_event.type = GDK_EXPOSE; - gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window; + gdk_event.window = pizza->bin_window; gdk_event.count = 0; - gdk_event.area.x = rect->x; - gdk_event.area.y = rect->y; - gdk_event.area.width = rect->width; - gdk_event.area.height = rect->height; - gtk_window_expose_callback( m_wxwindow, &gdk_event, (wxWindow *)this ); - } - else - { - GdkRectangle gdk_rect; - gdk_rect.x = rect->x; - gdk_rect.y = rect->y; - gdk_rect.width = rect->width; - gdk_rect.height = rect->height; - gtk_widget_draw( m_widget, &gdk_rect ); + + wxRegionIterator upd( m_updateRegion ); + while (upd) + { + GdkRectangle rect; + rect.x = upd.GetX(); + rect.y = upd.GetY(); + rect.width = upd.GetWidth(); + rect.height = upd.GetHeight(); + + if (gtk_widget_intersect (child->widget, &rect, &gdk_event.area)) + { + gtk_widget_event (child->widget, (GdkEvent*) &gdk_event); + } + + upd ++; + } } } +#endif + + m_updateRegion.Clear(); } void wxWindowGTK::Clear() @@ -3597,10 +3542,9 @@ GtkStyle *wxWindowGTK::GetWidgetStyle() if (m_widgetStyle) { GtkStyle *remake = gtk_style_copy( m_widgetStyle ); -#ifdef __WXGTK20__ - /* FIXME: is this necessary? */ - _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass); -#else + + // FIXME: no more klass in 2.0 +#ifndef __WXGTK20__ remake->klass = m_widgetStyle->klass; #endif @@ -3615,10 +3559,9 @@ GtkStyle *wxWindowGTK::GetWidgetStyle() def = gtk_widget_get_default_style(); m_widgetStyle = gtk_style_copy( def ); -#ifdef __WXGTK20__ - /* FIXME: is this necessary? */ - _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass); -#else + + // FIXME: no more klass in 2.0 +#ifndef __WXGTK20__ m_widgetStyle->klass = def->klass; #endif } @@ -3628,7 +3571,7 @@ GtkStyle *wxWindowGTK::GetWidgetStyle() void wxWindowGTK::SetWidgetStyle() { -#if DISABLE_STYLE_IF_BROKEN_THEM +#if DISABLE_STYLE_IF_BROKEN_THEME if (m_widget->style->engine_data) { static bool s_warningPrinted = FALSE; @@ -3646,8 +3589,7 @@ void wxWindowGTK::SetWidgetStyle() if (m_font != wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT )) { - gdk_font_unref( style->font ); - style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) ); + SET_STYLE_FONT(style, m_font.GetInternalFont( 1.0 )); } if (m_foregroundColour.Ok()) @@ -3757,6 +3699,9 @@ static gint gs_pop_y = 0; extern "C" void wxPopupMenuPositionCallback( GtkMenu *menu, gint *x, gint *y, +#ifdef __WXGTK20__ + gboolean * WXUNUSED(whatever), +#endif gpointer WXUNUSED(user_data) ) { // ensure that the menu appears entirely on screen @@ -3907,6 +3852,8 @@ void wxWindowGTK::DoReleaseMouse() wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") ); + g_captureWindow = (wxWindowGTK*) NULL; + GdkWindow *window = (GdkWindow*) NULL; if (m_wxwindow) window = GTK_PIZZA(m_wxwindow)->bin_window; @@ -3917,7 +3864,6 @@ void wxWindowGTK::DoReleaseMouse() return; gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME ); - g_captureWindow = (wxWindowGTK*) NULL; } /* static */ @@ -4089,13 +4035,39 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); + // No scrolling requested. if ((dx == 0) && (dy == 0)) return; + + if (!m_updateRegion.IsEmpty()) + { + m_updateRegion.Offset( dx, dy ); + + int cw = 0; + int ch = 0; + GetClientSize( &cw, &ch ); + m_updateRegion.Intersect( 0, 0, cw, ch ); + } + + if (!m_clearRegion.IsEmpty()) + { + m_clearRegion.Offset( dx, dy ); + + int cw = 0; + int ch = 0; + GetClientSize( &cw, &ch ); + m_clearRegion.Intersect( 0, 0, cw, ch ); + } + +#if 1 m_clipPaintRegion = TRUE; + gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy ); + m_clipPaintRegion = FALSE; -/* +#else + if (m_children.GetCount() > 0) { gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy ); @@ -4145,7 +4117,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) gdk_gc_unref( m_scrollGC ); } -*/ +#endif } // Find the wxWindow at the current mouse position, also returning the mouse