X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8e217128a047598380aa8483c472c822ea9ab9c9..cca602accb6910cd68cc7181b0a4a80f03a0b444:/src/gtk/window.cpp?ds=sidebyside diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 6dea5fdd64..80384e2535 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/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 @@ -268,7 +273,7 @@ gdk_window_warp_pointer (GdkWindow *window, GdkWindowPrivate *priv; if (!window) - window = (GdkWindow*) &gdk_root_parent; + window = GDK_ROOT_PARENT(); priv = (GdkWindowPrivate*) window; @@ -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; } //----------------------------------------------------------------------------- @@ -495,7 +503,7 @@ static long map_to_unmodified_wx_keysym( KeySym keysym ) case GDK_F12: key_code = WXK_F12; break; default: { - if (keysym <= 0xFF) + if ((keysym & 0xF000) == 0) { guint upper = gdk_keyval_to_upper( (guint)keysym ); keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */ @@ -594,7 +602,7 @@ static long map_to_wx_keysym( KeySym keysym ) case GDK_F12: key_code = WXK_F12; break; default: { - if (keysym <= 0xFF) + if ((keysym & 0xF000) == 0) { key_code = (guint)keysym; } @@ -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("columntitles")) + 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; - win->GetUpdateRegion().Clear(); + 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; + } + + 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("columntitles")) + 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*/ ); + } + } + } } //----------------------------------------------------------------------------- @@ -707,6 +794,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e if (!win->m_hasVMT) return FALSE; if (g_blockEventsOnDrag) return FALSE; + /* wxString tmp; tmp += (char)gdk_event->keyval; @@ -1643,6 +1731,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 +1757,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 +1928,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 +2061,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 +2098,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 +2114,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 +2236,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 +2298,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 +2403,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 +2431,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 +2492,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 +2568,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 +3032,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 +3222,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 +3234,7 @@ void wxWindow::SetWidgetStyle() m_widgetStyle = m_widget->style; return; } +#endif GtkStyle *style = GetWidgetStyle(); @@ -3251,6 +3422,10 @@ void wxWindow::CaptureMouse() if (!window) return; + wxCursor* cursor = & m_cursor; + if (!cursor->Ok()) + cursor = wxSTANDARD_CURSOR; + gdk_pointer_grab( window, FALSE, (GdkEventMask) (GDK_BUTTON_PRESS_MASK | @@ -3258,7 +3433,7 @@ void wxWindow::CaptureMouse() GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK), (GdkWindow *) NULL, - m_cursor.GetCursor(), + cursor->GetCursor(), (guint32)GDK_CURRENT_TIME ); g_captureWindow = this; } @@ -3447,7 +3622,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)