X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/809934d22ad2e97d67655ecb4b06b29b5d2a361d..117082d17b73a920f22af12cd55315d1147ccd99:/src/gtk1/window.cpp?ds=inline diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index befad324ff..74e06e0af0 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -46,10 +46,13 @@ #include #include #include -#include - #include +#include +#include + +#include "wx/gtk/win_gtk.h" + //----------------------------------------------------------------------------- // documentation on internals //----------------------------------------------------------------------------- @@ -208,6 +211,8 @@ extern bool g_mainThreadLocked; // debug //----------------------------------------------------------------------------- +#define DISABLE_STYLE_IF_BROKEN_THEME 1 + #ifdef __WXDEBUG__ #if wxUSE_THREADS @@ -379,10 +384,13 @@ static void draw_frame( GtkWidget *widget, wxWindow *win ) // "expose_event" of m_widget //----------------------------------------------------------------------------- -static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win ) +gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win ) { - if (gdk_event->count > 0) return; + if (gdk_event->count > 0) return FALSE; + draw_frame( widget, win ); + + return TRUE; } //----------------------------------------------------------------------------- @@ -608,12 +616,15 @@ static long map_to_wx_keysym( KeySym keysym ) // "expose_event" of m_wxwindow //----------------------------------------------------------------------------- -static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win ) +static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win ) { DEBUG_MAIN_THREAD + if (g_isIdle) + wxapp_install_idle_handler(); + /* - if (win->GetName() == wxT("grid window")) + if (win->GetName() == wxT("panel")) { wxPrintf( wxT("OnExpose from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -625,46 +636,95 @@ static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExp } */ - win->GetUpdateRegion().Union( gdk_event->area.x, - gdk_event->area.y, - gdk_event->area.width, - gdk_event->area.height ); + if (!win->m_queuedFullRedraw) + { + win->GetUpdateRegion().Union( gdk_event->area.x, + gdk_event->area.y, + gdk_event->area.width, + gdk_event->area.height ); - if (gdk_event->count > 0) - return; + if (gdk_event->count == 0) + { + wxEraseEvent eevent( win->GetId() ); + eevent.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent(eevent); - if (!win->m_hasVMT) - return; + wxPaintEvent event( win->GetId() ); + event.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( event ); - wxEraseEvent eevent( win->GetId() ); - eevent.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent(eevent); + win->GetUpdateRegion().Clear(); + } + + /* 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 */ + + GtkPizza *pizza = GTK_PIZZA (widget); + + GList *children = pizza->children; + while (children) + { + GtkPizzaChild *child = (GtkPizzaChild*) children->data; + children = children->next; - wxPaintEvent event( win->GetId() ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); + 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); + } + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// "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. */ + +gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, wxWindow *win ) +{ + if (event->type == GDK_EXPOSE) + { + gint ret = gtk_window_expose_callback( widget, event, win ); + return ret; + } - win->GetUpdateRegion().Clear(); + return FALSE; } //----------------------------------------------------------------------------- // "draw" of m_wxwindow //----------------------------------------------------------------------------- -static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), - GdkRectangle *rect, wxWindow *win ) +/* This callback is a complete replacement of the gtk_pizza_draw() function, + which disabled. */ + +static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win ) { DEBUG_MAIN_THREAD if (g_isIdle) wxapp_install_idle_handler(); - if ((rect->x == 0) && (rect->y == 0) && (rect->width <= 1) && (rect->height <= 1)) - return; - /* - if (win->GetName() == wxT("grid window")) + if (win->GetName() == wxT("panel")) { wxPrintf( wxT("OnDraw from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -675,22 +735,49 @@ static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), (int)rect->height ); } */ - - win->GetUpdateRegion().Union( rect->x, rect->y, - rect->width, rect->height ); + + GtkPizza *pizza = GTK_PIZZA (widget); + + if (!win->m_queuedFullRedraw) + { + + if (!(GTK_WIDGET_APP_PAINTABLE (widget)) && + (pizza->clear_on_draw)) + { + 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 ); - if (!win->m_hasVMT) - return; + win->m_clipPaintRegion = TRUE; + + wxEraseEvent eevent( win->GetId() ); + eevent.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent(eevent); - wxEraseEvent eevent( win->GetId() ); - eevent.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent(eevent); + wxPaintEvent event( win->GetId() ); + event.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( event ); - wxPaintEvent event( win->GetId() ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); + win->GetUpdateRegion().Clear(); + + win->m_clipPaintRegion = FALSE; + + + GList *children = pizza->children; + while (children) + { + GtkPizzaChild *child = (GtkPizzaChild*) children->data; + children = children->next; - win->GetUpdateRegion().Clear(); + GdkRectangle child_area; + if (gtk_widget_intersect (child->widget, rect, &child_area)) + { + gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ ); + } + } + } } //----------------------------------------------------------------------------- @@ -1643,6 +1730,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget, if (g_isIdle) wxapp_install_idle_handler(); + g_blockEventsOnScroll = TRUE; win->m_isScrolling = (gdk_event->window == widget->slider); @@ -1668,7 +1756,7 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget, if (win->m_isScrolling) { - wxEventType command = wxEVT_SCROLL_THUMBRELEASE; + wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE; int value = -1; int dir = -1; @@ -1839,8 +1927,8 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget), if ((colormap = gtk_widget_get_colormap (widget)) != gtk_widget_get_default_colormap ()) { - attrmask |= GDK_IC_PREEDIT_COLORMAP; - attr->preedit_colormap = colormap; + attrmask |= GDK_IC_PREEDIT_COLORMAP; + attr->preedit_colormap = colormap; } attrmask |= GDK_IC_PREEDIT_FOREGROUND; @@ -1972,6 +2060,9 @@ void wxWindow::Init() m_isFrame = FALSE; m_acceptsFocus = FALSE; + m_clipPaintRegion = FALSE; + m_queuedFullRedraw = FALSE; + m_cursor = *wxSTANDARD_CURSOR; #ifdef HAVE_XIM @@ -2006,21 +2097,12 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id, } m_insertCallback = wxInsertChildInWindow; - + m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name ); -#endif - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); -#ifdef __WXDEBUG__ - debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name ); - debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name ); -#endif - GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass ); scroll_class->scrollbar_spacing = 0; @@ -2031,10 +2113,6 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id, m_wxwindow = gtk_pizza_new(); -#ifdef __WXDEBUG__ - debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name ); -#endif - gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); #if (GTK_MINOR_VERSION > 0) @@ -2157,10 +2235,11 @@ wxWindow::~wxWindow() if (m_widgetStyle) { +#if DISABLE_STYLE_IF_BROKEN_THEME // don't delete if it's a pixmap theme style if (!m_widgetStyle->engine_data) gtk_style_unref( m_widgetStyle ); - +#endif m_widgetStyle = (GtkStyle*) NULL; } @@ -2218,6 +2297,12 @@ void wxWindow::PostCreation() if (!m_noExpose) { /* these get reported to wxWindows -> wxPaintEvent */ + + gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE ); + + gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event", + GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this ); + gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event", GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this ); @@ -2317,6 +2402,24 @@ bool wxWindow::Destroy() void wxWindow::DoMoveWindow(int x, int y, int width, int height) { + if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window) + { + /* Normally, GTK will send expose events only for the regions + which actually got exposed. Sadly, wxMSW invalidates + the whole window so we have to do that, too. We could + simply add a complete refresh, but we would then get + the normal GTK expose events in surplus, so we shut + off the expose events and schedule a full redraw to + be done in OnInternalIdle, where we restore the handling + of expose events. */ + + m_queuedFullRedraw = TRUE; + + GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window ); + mask = (GdkEventMask)(mask & ~GDK_EXPOSURE_MASK); + gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask ); + } + gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height ); } @@ -2327,7 +2430,7 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags ) if (m_resizing) return; /* I don't like recursions */ m_resizing = TRUE; - + if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */ { /* don't set the size for children of wxNotebook, just take the values. */ @@ -2388,6 +2491,12 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags ) if (m_hasScrolling) { + /* Sometimes the client area changes size without the + whole windows's size changing, but if the whole + windows's size doesn't change, no wxSizeEvent will + normally be sent. Here we add an extra test if + the client test has been changed and this will + be used then. */ GetClientSize( &m_oldClientWidth, &m_oldClientHeight ); } @@ -2458,6 +2567,33 @@ void wxWindow::OnInternalIdle() } UpdateWindowUI(); + + if (m_queuedFullRedraw) + { + /* See also wxWindow::DoMoveWindow for explanation of this code. What + we test here is if the requested size of the window is the same as + the actual size of window, in which case all expose events that resulted + from resizing the window have been sent (and discarded) and we can + now do our full redraw and switch on expose event handling again. */ + + bool child_already_resized = FALSE; + if (m_isFrame) + child_already_resized = gtk_pizza_child_resized( GTK_PIZZA(m_wxwindow->parent), m_wxwindow ); + else + child_already_resized = gtk_pizza_child_resized( GTK_PIZZA(m_widget->parent), m_widget ); + + if (child_already_resized) + { + m_queuedFullRedraw = FALSE; + m_updateRegion.Clear(); + m_updateRegion.Union( 0,0,m_width,m_height ); + gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL ); + + GdkEventMask mask = gdk_window_get_events( GTK_PIZZA(m_wxwindow)->bin_window ); + mask = (GdkEventMask)(mask | GDK_EXPOSURE_MASK); + gdk_window_set_events( GTK_PIZZA(m_wxwindow)->bin_window, mask ); + } + } } void wxWindow::DoGetSize( int *width, int *height ) const @@ -2895,37 +3031,69 @@ void wxWindow::Refresh( bool eraseBackground, const wxRect *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, this ); + } else + { gtk_widget_draw( m_widget, (GdkRectangle*) NULL ); + } } else { - GdkRectangle gdk_rect; - gdk_rect.x = rect->x; - gdk_rect.y = rect->y; - gdk_rect.width = rect->width; - gdk_rect.height = rect->height; if (m_wxwindow) { +/* GtkPizza *pizza = GTK_PIZZA(m_wxwindow); gboolean old_clear = pizza->clear_on_draw; gtk_pizza_set_clear( pizza, FALSE ); + 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 ); 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 = 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, 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 ); + } } } @@ -3053,6 +3221,7 @@ GtkStyle *wxWindow::GetWidgetStyle() void wxWindow::SetWidgetStyle() { +#if DISABLE_STYLE_IF_BROKEN_THEM if (m_widget->style->engine_data) { static bool s_warningPrinted = FALSE; @@ -3064,6 +3233,7 @@ void wxWindow::SetWidgetStyle() m_widgetStyle = m_widget->style; return; } +#endif GtkStyle *style = GetWidgetStyle(); @@ -3447,7 +3617,9 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) if ((dx == 0) && (dy == 0)) return; + m_clipPaintRegion = TRUE; gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy ); + m_clipPaintRegion = FALSE; /* if (m_children.GetCount() > 0)