X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/30083ad8e7c0eb9ea3dcf4f2588149eeb7fe3e32..c782096417f0fd9de6c6d47b23174233ec6bcf57:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a9a67e6c68..e8b8ed1719 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -190,8 +190,10 @@ // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern bool g_blockEventsOnScroll; +// Don't allow event propagation during drag +bool g_blockEventsOnDrag; +// Don't allow mouse event propagation during scroll +bool g_blockEventsOnScroll; extern wxCursor g_globalCursor; // mouse capture state: the window which has it and if the mouse is currently @@ -422,6 +424,8 @@ void wxgtk_window_size_request_callback(GtkWidget *widget, } } +#if wxUSE_COMBOBOX + extern "C" { static void wxgtk_combo_size_request_callback(GtkWidget *widget, @@ -457,6 +461,8 @@ void wxgtk_combo_size_request_callback(GtkWidget *widget, } } +#endif // wxUSE_COMBOBOX + //----------------------------------------------------------------------------- // "expose_event" of m_wxwindow //----------------------------------------------------------------------------- @@ -469,8 +475,6 @@ gtk_window_expose_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - // This callback gets called in drawing-idle time under // GTK 2.0, so we don't need to defer anything to idle // time anymore. @@ -982,8 +986,6 @@ gtk_window_key_press_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (!win->m_hasVMT) return FALSE; if (g_blockEventsOnDrag) @@ -1114,30 +1116,6 @@ gtk_window_key_press_callback( GtkWidget *widget, } } - // win is a control: tab can be propagated up - if ( !ret && - ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) && -// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may -// have this style, yet choose not to process this particular TAB in which -// case TAB must still work as a navigational character -// JS: enabling again to make consistent with other platforms -// (with wxTE_PROCESS_TAB you have to call Navigate to get default -// navigation behaviour) -#if wxUSE_TEXTCTRL - (! (win->HasFlag(wxTE_PROCESS_TAB) && win->IsKindOf(CLASSINFO(wxTextCtrl)) )) && -#endif - win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) ) - { - wxNavigationKeyEvent new_event; - new_event.SetEventObject( win->GetParent() ); - // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB - new_event.SetDirection( (gdk_event->keyval == GDK_Tab) ); - // CTRL-TAB changes the (parent) window, i.e. switch notebook page - new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) ); - new_event.SetCurrentFocus( win ); - ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); - } - return ret; } } @@ -1157,9 +1135,13 @@ gtk_wxwindow_commit_cb (GtkIMContext *context, wxFillOtherKeyEventFields(event, window, window->m_imData->lastKeyEvent); } + else + { + event.SetEventObject( window ); + } - const wxWxCharBuffer data(wxGTK_CONV_BACK_SYS(str)); - if( !data ) + const wxString data(wxGTK_CONV_BACK_SYS(str)); + if( data.empty() ) return; bool ret = false; @@ -1169,7 +1151,7 @@ gtk_wxwindow_commit_cb (GtkIMContext *context, while (parent && !parent->IsTopLevel()) parent = parent->GetParent(); - for( const wxChar* pstr = data; *pstr; pstr++ ) + for( wxString::const_iterator pstr = data.begin(); pstr != data.end(); ++pstr ) { #if wxUSE_UNICODE event.m_uniChar = *pstr; @@ -1177,7 +1159,7 @@ gtk_wxwindow_commit_cb (GtkIMContext *context, event.m_keyCode = *pstr < 256 ? event.m_uniChar : 0; wxLogTrace(TRACE_KEYS, _T("IM sent character '%c'"), event.m_uniChar); #else - event.m_keyCode = *pstr; + event.m_keyCode = (char)*pstr; #endif // wxUSE_UNICODE // To conform to the docs we need to translate Ctrl-alpha @@ -1224,8 +1206,6 @@ gtk_window_key_release_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (!win->m_hasVMT) return FALSE; @@ -1257,22 +1237,15 @@ template void InitMouseEvent(wxWindowGTK *win, T *gdk_event) { event.SetTimestamp( gdk_event->time ); - event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); - event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); - event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); - event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); - event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); - event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); - event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); - if (event.GetEventType() == wxEVT_MOUSEWHEEL) - { - event.m_linesPerAction = 3; - event.m_wheelDelta = 120; - if (((GdkEventButton*)gdk_event)->button == 4) - event.m_wheelRotation = 120; - else if (((GdkEventButton*)gdk_event)->button == 5) - event.m_wheelRotation = -120; - } + event.m_shiftDown = gdk_event->state & GDK_SHIFT_MASK; + event.m_controlDown = gdk_event->state & GDK_CONTROL_MASK; + event.m_altDown = gdk_event->state & GDK_MOD1_MASK; + event.m_metaDown = gdk_event->state & GDK_MOD2_MASK; + event.m_leftDown = gdk_event->state & GDK_BUTTON1_MASK; + event.m_middleDown = gdk_event->state & GDK_BUTTON2_MASK; + event.m_rightDown = gdk_event->state & GDK_BUTTON3_MASK; + event.m_aux1Down = gdk_event->state & GDK_BUTTON4_MASK; + event.m_aux2Down = gdk_event->state & GDK_BUTTON5_MASK; wxPoint pt = win->GetClientAreaOrigin(); event.m_x = (wxCoord)gdk_event->x - pt.x; @@ -1402,8 +1375,6 @@ int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (!m_hasVMT) return FALSE; if (g_blockEventsOnDrag) @@ -1469,11 +1440,6 @@ gtk_window_button_press_callback( GtkWidget *widget, g_lastButtonNumber = gdk_event->button; - if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus()) - { - gtk_widget_grab_focus( win->m_wxwindow ); - } - // GDK sends surplus button down events // before a double click event. We // need to filter these out. @@ -1571,13 +1537,6 @@ gtk_window_button_press_callback( GtkWidget *widget, ; } } - else if (gdk_event->button == 4 || gdk_event->button == 5) - { - if (gdk_event->type == GDK_BUTTON_PRESS ) - { - event_type = wxEVT_MOUSEWHEEL; - } - } if ( event_type == wxEVT_NULL ) { @@ -1611,6 +1570,12 @@ gtk_window_button_press_callback( GtkWidget *widget, if ( ret ) return TRUE; + if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && + (g_focusWindow != win) /* && win->IsFocusable() */) + { + win->SetFocus(); + } + if (event_type == wxEVT_RIGHT_DOWN) { // generate a "context menu" event: this is similar to right mouse @@ -1683,9 +1648,9 @@ gtk_window_button_release_callback( GtkWidget *widget, event.SetId( win->GetId() ); bool ret = win->GTKProcessEvent(event); - + g_lastMouseEvent = NULL; - + return ret; } @@ -1762,7 +1727,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget, } //----------------------------------------------------------------------------- -// "scroll_event", (mouse wheel event) +// "scroll_event" (mouse wheel event) //----------------------------------------------------------------------------- static gboolean @@ -1770,8 +1735,6 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (gdk_event->direction != GDK_SCROLL_UP && gdk_event->direction != GDK_SCROLL_DOWN) { @@ -1779,15 +1742,7 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) } wxMouseEvent event(wxEVT_MOUSEWHEEL); - // Can't use InitMouse macro because scroll events don't have button - event.SetTimestamp( gdk_event->time ); - event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); - event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); - event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); - event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); - event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); - event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); - event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); + InitMouseEvent(win, event, gdk_event); event.m_linesPerAction = 3; event.m_wheelDelta = 120; if (gdk_event->direction == GDK_SCROLL_UP) @@ -1795,14 +1750,6 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) else event.m_wheelRotation = -120; - wxPoint pt = win->GetClientAreaOrigin(); - event.m_x = (wxCoord)gdk_event->x - pt.x; - event.m_y = (wxCoord)gdk_event->y - pt.y; - - event.SetEventObject( win ); - event.SetId( win->GetId() ); - event.SetTimestamp( gdk_event->time ); - return win->GTKProcessEvent(event); } @@ -1828,8 +1775,6 @@ gtk_window_focus_in_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (win->m_imData) gtk_im_context_focus_in(win->m_imData->context); @@ -1880,8 +1825,6 @@ gtk_window_focus_out_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - if (win->m_imData) gtk_im_context_focus_out(win->m_imData->context); @@ -1904,12 +1847,14 @@ gtk_window_focus_out_callback( GtkWidget *widget, } #endif // wxUSE_CARET - gboolean ret = FALSE; - // don't send the window a kill focus event if it thinks that it doesn't // have focus already if ( win->m_hasFocus ) { + // the event handler might delete the window when it loses focus, so + // check whether this is a custom window before calling it + const bool has_wxwindow = win->m_wxwindow != NULL; + win->m_hasFocus = false; wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); @@ -1917,14 +1862,34 @@ gtk_window_focus_out_callback( GtkWidget *widget, (void)win->GTKProcessEvent( event ); - ret = TRUE; + // Disable default focus handling for custom windows + // since the default GTK+ handler issues a repaint + if ( has_wxwindow ) + { + return TRUE; + } } - // Disable default focus handling for custom windows - // since the default GTK+ handler issues a repaint - if (win->m_wxwindow) - return ret; + // continue with normal processing + return FALSE; +} +static gboolean +wx_window_focus_callback(GtkWidget *widget, + GtkDirectionType direction, + wxWindowGTK *win) +{ + // the default handler for focus signal in GtkPizza (or, rather, in + // GtkScrolledWindow from which GtkPizza inherits this behaviour) sets + // focus to the window itself even if it doesn't accept focus, i.e. has no + // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing + // the signal from reaching gtk_scrolled_window_focus() if we don't have + // any children which might accept focus (we know we don't accept the focus + // ourselves as this signal is only connected in this case) + if ( win->GetChildren().empty() ) + g_signal_stop_emission_by_name(widget, "focus"); + + // we didn't change the focus return FALSE; } @@ -1981,8 +1946,6 @@ gtk_window_leave_callback( GtkWidget *widget, if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE; wxMouseEvent event( wxEVT_LEAVE_WINDOW ); - event.SetTimestamp( gdk_event->time ); - event.SetEventObject( win ); int x = 0; int y = 0; @@ -1990,17 +1953,7 @@ gtk_window_leave_callback( GtkWidget *widget, gdk_window_get_pointer( widget->window, &x, &y, &state ); - event.m_shiftDown = (state & GDK_SHIFT_MASK) != 0; - event.m_controlDown = (state & GDK_CONTROL_MASK) != 0; - event.m_altDown = (state & GDK_MOD1_MASK) != 0; - event.m_metaDown = (state & GDK_MOD2_MASK) != 0; - event.m_leftDown = (state & GDK_BUTTON1_MASK) != 0; - event.m_middleDown = (state & GDK_BUTTON2_MASK) != 0; - event.m_rightDown = (state & GDK_BUTTON3_MASK) != 0; - - wxPoint pt = win->GetClientAreaOrigin(); - event.m_x = x + pt.x; - event.m_y = y + pt.y; + InitMouseEvent(win, event, gdk_event); return win->GTKProcessEvent(event); } @@ -2026,9 +1979,7 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win) wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient); event.SetEventObject(win); - win->m_blockValueChanged[dir] = true; win->GTKProcessEvent(event); - win->m_blockValueChanged[dir] = false; } } @@ -2041,8 +1992,6 @@ gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win) { DEBUG_MAIN_THREAD - // don't need to install idle handler, its done from "event" signal - g_blockEventsOnScroll = true; win->m_mouseButtonDown = true; @@ -2096,17 +2045,11 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w // "realize" from m_widget //----------------------------------------------------------------------------- -/* We cannot set colours and fonts before the widget has - been realized, so we do this directly after realization. */ - static void gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win ) { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); - if (win->m_imData) { GtkPizza *pizza = GTK_PIZZA( m_widget ); @@ -2114,6 +2057,16 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win ) pizza->bin_window ); } + // We cannot set colours and fonts before the widget + // been realized, so we do this directly after realization + // or otherwise in idle time + + if (win->m_needsStyleChange) + { + win->SetBackgroundStyle(win->GetBackgroundStyle()); + win->m_needsStyleChange = false; + } + wxWindowCreateEvent event( win ); event.SetEventObject( win ); win->GTKProcessEvent( event ); @@ -2128,9 +2081,6 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation *alloc, wxWindow *win ) { - if (g_isIdle) - wxapp_install_idle_handler(); - int client_width = 0; int client_height = 0; win->GetClientSize( &client_width, &client_height ); @@ -2154,6 +2104,27 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), } } +//----------------------------------------------------------------------------- +// "grab_broken" +//----------------------------------------------------------------------------- + +#ifdef __WXGTK210__ +static void +gtk_window_grab_broken( GtkWidget *m_widget, + GdkEventGrabBroken *event, + wxWindow *win ) +{ + // Mouse capture has been lost involuntarily, notify the application + if( !event->keyboard && win && wxWindow::GetCapture() == win ) + { + wxMouseCaptureLostEvent evt( win->GetId() ); + evt.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( evt ); + } +} +#endif + + } // extern "C" // ---------------------------------------------------------------------------- @@ -2187,7 +2158,7 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child ) child->m_y += gtk_pizza_get_yoffset( pizza ); gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow), - GTK_WIDGET(child->m_widget), + child->m_widget, child->m_x, child->m_y, child->m_width, @@ -2219,6 +2190,8 @@ wxMouseState wxGetMouseState() ms.SetLeftDown(mask & GDK_BUTTON1_MASK); ms.SetMiddleDown(mask & GDK_BUTTON2_MASK); ms.SetRightDown(mask & GDK_BUTTON3_MASK); + ms.SetAux1Down(mask & GDK_BUTTON4_MASK); + ms.SetAux2Down(mask & GDK_BUTTON5_MASK); ms.SetControlDown(mask & GDK_CONTROL_MASK); ms.SetShiftDown(mask & GDK_SHIFT_MASK); @@ -2253,9 +2226,7 @@ void wxWindowGTK::Init() m_width = 0; m_height = 0; - m_sizeSet = false; m_hasVMT = false; - m_needParent = true; m_isBeingDeleted = false; m_showOnIdle= false; @@ -2273,7 +2244,6 @@ void wxWindowGTK::Init() { m_scrollBar[dir] = NULL; m_scrollPos[dir] = 0; - m_blockValueChanged[dir] = false; } m_oldClientWidth = @@ -2281,9 +2251,8 @@ void wxWindowGTK::Init() m_resizing = false; - m_insertCallback = (wxInsertChildFunction) NULL; + m_insertCallback = wxInsertChildInWindow; - m_acceptsFocus = false; m_hasFocus = false; m_clipPaintRegion = false; @@ -2327,68 +2296,95 @@ bool wxWindowGTK::Create( wxWindow *parent, return false; } - m_insertCallback = wxInsertChildInWindow; - - m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); - GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - - GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) ); - scroll_class->scrollbar_spacing = 0; - - if (HasFlag(wxALWAYS_SHOW_SB)) + if (!HasFlag(wxHSCROLL) && !HasFlag(wxVSCROLL)) { - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS ); + m_wxwindow = gtk_pizza_new_no_scroll(); - scrolledWindow->hscrollbar_visible = TRUE; - scrolledWindow->vscrollbar_visible = TRUE; +#ifndef __WXUNIVERSAL__ + if (HasFlag(wxSIMPLE_BORDER)) + gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1); + else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER)) + gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2); +#endif // __WXUNIVERSAL__ + + m_widget = m_wxwindow; } else { - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - } - - m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar); - m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar); - if (GetLayoutDirection() == wxLayout_RightToLeft) - gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE ); - - m_wxwindow = gtk_pizza_new(); + m_wxwindow = gtk_pizza_new(); #ifndef __WXUNIVERSAL__ - if (HasFlag(wxSIMPLE_BORDER)) - gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1); - else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER)) - gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2); + if (HasFlag(wxSIMPLE_BORDER)) + gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1); + else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER)) + gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2); #endif // __WXUNIVERSAL__ - gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); + m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); - GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); - m_acceptsFocus = true; + GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - // connect various scroll-related events - for ( int dir = 0; dir < ScrollDir_Max; dir++ ) - { - // these handlers block mouse events to any window during scrolling - // such as motion events and prevent GTK and wxWidgets from fighting - // over where the slider should be - g_signal_connect(m_scrollBar[dir], "button_press_event", + GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) ); + scroll_class->scrollbar_spacing = 0; + + // There is a conflict with default bindings at GTK+ + // level between scrolled windows and notebooks both of which want to use + // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal + // direction and notebooks for changing pages -- we decide that if we don't + // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it + // means we can get working keyboard navigation in notebooks + if ( !HasFlag(wxHSCROLL) ) + { + GtkBindingSet * + bindings = gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget)); + if ( bindings ) + { + gtk_binding_entry_remove(bindings, GDK_Page_Up, GDK_CONTROL_MASK); + gtk_binding_entry_remove(bindings, GDK_Page_Down, GDK_CONTROL_MASK); + } + } + + if (HasFlag(wxALWAYS_SHOW_SB)) + { + gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS ); + + scrolledWindow->hscrollbar_visible = TRUE; + scrolledWindow->vscrollbar_visible = TRUE; + } + else + { + gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); + } + + m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar); + m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar); + if (GetLayoutDirection() == wxLayout_RightToLeft) + gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE ); + + gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); + + // connect various scroll-related events + for ( int dir = 0; dir < ScrollDir_Max; dir++ ) + { + // these handlers block mouse events to any window during scrolling + // such as motion events and prevent GTK and wxWidgets from fighting + // over where the slider should be + g_signal_connect(m_scrollBar[dir], "button_press_event", G_CALLBACK(gtk_scrollbar_button_press_event), this); - g_signal_connect(m_scrollBar[dir], "button_release_event", + g_signal_connect(m_scrollBar[dir], "button_release_event", G_CALLBACK(gtk_scrollbar_button_release_event), this); - gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after", + gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this); - g_signal_handler_block(m_scrollBar[dir], handler_id); + g_signal_handler_block(m_scrollBar[dir], handler_id); - // these handlers get notified when scrollbar slider moves - g_signal_connect(m_scrollBar[dir], "value_changed", + // these handlers get notified when scrollbar slider moves + g_signal_connect_after(m_scrollBar[dir], "value_changed", G_CALLBACK(gtk_scrollbar_value_changed), this); - } + } - gtk_widget_show( m_wxwindow ); + gtk_widget_show( m_wxwindow ); + } if (m_parent) m_parent->DoAddChild( this ); @@ -2434,7 +2430,7 @@ wxWindowGTK::~wxWindowGTK() // delete before the widgets to avoid a crash on solaris delete m_imData; - if (m_wxwindow) + if (m_wxwindow && (m_wxwindow != m_widget)) { gtk_widget_destroy( m_wxwindow ); m_wxwindow = (GtkWidget*) NULL; @@ -2449,7 +2445,10 @@ wxWindowGTK::~wxWindowGTK() bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos, const wxSize &size ) { - wxCHECK_MSG( !m_needParent || parent, false, wxT("Need complete parent.") ); + if ( GTKNeedsParent() ) + { + wxCHECK_MSG( parent, false, wxT("Must have non-NULL parent") ); + } // Use either the given size, or the default if -1 is given. // See wxWindowBase for these functions. @@ -2516,6 +2515,14 @@ void wxWindowGTK::PostCreation() } } + if ( !AcceptsFocusFromKeyboard() ) + { + SetCanFocus(false); + + g_signal_connect(m_widget, "focus", + G_CALLBACK(wx_window_focus_callback), this); + } + // connect to the various key and mouse handlers GtkWidget *connect_widget = GetConnectWidget(); @@ -2532,8 +2539,29 @@ void wxWindowGTK::PostCreation() // Catch native resize events g_signal_connect (m_wxwindow, "size_allocate", G_CALLBACK (gtk_window_size_callback), this); +#ifdef __WXGTK210__ + if (!gtk_check_version(2,8,0)) + { + // Make sure we can notify the app when mouse capture is lost + g_signal_connect (m_wxwindow, "grab_broken_event", + G_CALLBACK (gtk_window_grab_broken), this); + } +#endif } + if ( connect_widget != m_wxwindow ) + { +#ifdef __WXGTK210__ + if (!gtk_check_version(2,8,0)) + { + // Make sure we can notify app code when mouse capture is lost + g_signal_connect (connect_widget, "grab_broken_event", + G_CALLBACK (gtk_window_grab_broken), this); + } +#endif + } + +#if wxUSE_COMBOBOX if (GTK_IS_COMBO(m_widget)) { GtkCombo *gcombo = GTK_COMBO(m_widget); @@ -2541,17 +2569,18 @@ void wxWindowGTK::PostCreation() g_signal_connect (gcombo->entry, "size_request", G_CALLBACK (wxgtk_combo_size_request_callback), this); - } + } else +#endif // wxUSE_COMBOBOX #ifdef GTK_IS_FILE_CHOOSER_BUTTON - else if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) + 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 // (this can be tested removing this elseif and running XRC or WIDGETS samples) // FIXME: what should be done here ? - } + } else #endif - else if ( !IsTopLevel() ) // top level windows use their own callback + if ( !IsTopLevel() ) // top level windows use their own callback { // This is needed if we want to add our windows into native // GTK controls, such as the toolbar. With this callback, the @@ -2612,6 +2641,23 @@ void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) } +void wxWindowGTK::ConstrainSize() +{ +#ifdef __WXGPE__ + // GPE's window manager doesn't like size hints at all, esp. when the user + // has to use the virtual keyboard, so don't constrain size there + if (!IsTopLevel()) +#endif + { + const wxSize minSize = GetMinSize(); + const wxSize maxSize = GetMaxSize(); + if (minSize.x > 0 && m_width < minSize.x) m_width = minSize.x; + if (minSize.y > 0 && m_height < minSize.y) m_height = minSize.y; + if (maxSize.x > 0 && m_width > maxSize.x) m_width = maxSize.x; + if (maxSize.y > 0 && m_height > maxSize.y) m_height = maxSize.y; + } +} + void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") ); @@ -2644,21 +2690,13 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags if (height != -1) m_height = height; - 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; + ConstrainSize(); #if wxUSE_TOOLBAR_NATIVE if (wxDynamicCast(GetParent(), wxToolBar)) { // don't take the x,y values, they're wrong because toolbar sets them - GtkWidget *widget = GTK_WIDGET(m_widget); + GtkWidget *widget = m_widget; gtk_widget_set_size_request (widget, m_width, m_height); } else @@ -2701,12 +2739,12 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags right_border += default_border->right; top_border += default_border->top; bottom_border += default_border->bottom; - g_free( default_border ); + gtk_border_free( default_border ); } } - DoMoveWindow( m_x-top_border, - m_y-left_border, + DoMoveWindow( m_x - left_border, + m_y - top_border, m_width+left_border+right_border, m_height+top_border+bottom_border ); } @@ -2789,7 +2827,7 @@ void wxWindowGTK::OnInternalIdle() windows above so that checking for the current cursor is not possible. */ - if (m_wxwindow) + if (m_wxwindow && (m_wxwindow != m_widget)) { GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window; if (window) @@ -2827,25 +2865,9 @@ void wxWindowGTK::DoSetClientSize( int width, int height ) { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (m_wxwindow) - { - int dw = 0; - int dh = 0; - - if (m_hasScrolling) - { - GetScrollbarWidth(m_widget, dw, dh); - } - - const int border = GTK_CONTAINER(m_wxwindow)->border_width; - dw += 2 * border; - dh += 2 * border; - - width += dw; - height += dh; - } - - SetSize(width, height); + const wxSize size = GetSize(); + const wxSize clientSize = GetClientSize(); + SetSize(width + (size.x - clientSize.x), height + (size.y - clientSize.y)); } void wxWindowGTK::DoGetClientSize( int *width, int *height ) const @@ -2906,8 +2928,8 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const int org_y = 0; gdk_window_get_origin( source, &org_x, &org_y ); - if (GetParent()) - GetParent()->ScreenToClient(&org_x, &org_y); + if (m_parent) + m_parent->ScreenToClient(&org_x, &org_y); wx_const_cast(wxWindowGTK*, this)->m_x = org_x; wx_const_cast(wxWindowGTK*, this)->m_y = org_y; @@ -3021,40 +3043,13 @@ bool wxWindowGTK::Show( bool show ) return true; } -static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable) +void wxWindowGTK::DoEnable( bool enable ) { - win->OnParentEnable(enable); - - // Recurse, so that children have the opportunity to Do The Right Thing - // and reset colours that have been messed up by a parent's (really ancestor's) - // Enable call - for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); - node; - node = node->GetNext() ) - { - wxWindow *child = node->GetData(); - if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame))) - wxWindowNotifyEnable(child, enable); - } -} - -bool wxWindowGTK::Enable( bool enable ) -{ - wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") ); - - if (!wxWindowBase::Enable(enable)) - { - // nothing to do - return false; - } + wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); gtk_widget_set_sensitive( m_widget, enable ); - if ( m_wxwindow ) + if (m_wxwindow && (m_wxwindow != m_widget)) gtk_widget_set_sensitive( m_wxwindow, enable ); - - wxWindowNotifyEnable(this, enable); - - return true; } int wxWindowGTK::GetCharHeight() const @@ -3204,11 +3199,13 @@ void wxWindowGTK::SetFocus() { if (GTK_IS_CONTAINER(m_widget)) { +#if wxUSE_RADIOBTN if (IsKindOf(CLASSINFO(wxRadioButton))) { gtk_widget_grab_focus (m_widget); return; } +#endif // wxUSE_RADIOBTN gtk_widget_child_focus( m_widget, GTK_DIR_TAB_FORWARD ); } @@ -3245,9 +3242,20 @@ void wxWindowGTK::SetFocus() } } -bool wxWindowGTK::AcceptsFocus() const +void wxWindowGTK::SetCanFocus(bool canFocus) { - return m_acceptsFocus && wxWindowBase::AcceptsFocus(); + if ( canFocus ) + GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS(m_widget, GTK_CAN_FOCUS); + + if ( m_wxwindow && (m_widget != m_wxwindow) ) + { + if ( canFocus ) + GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS(m_wxwindow, GTK_CAN_FOCUS); + } } bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) @@ -3297,11 +3305,8 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) void wxWindowGTK::DoAddChild(wxWindowGTK *child) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") ); - wxASSERT_MSG( (child != NULL), wxT("invalid child window") ); - wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") ); - /* add to list */ AddChild( child ); @@ -3313,22 +3318,20 @@ void wxWindowGTK::AddChild(wxWindowBase *child) { wxWindowBase::AddChild(child); m_dirtyTabOrder = true; - if (g_isIdle) - wxapp_install_idle_handler(); + wxTheApp->WakeUpIdle(); } void wxWindowGTK::RemoveChild(wxWindowBase *child) { wxWindowBase::RemoveChild(child); m_dirtyTabOrder = true; - if (g_isIdle) - wxapp_install_idle_handler(); + wxTheApp->WakeUpIdle(); } /* static */ wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget) { - return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL + return gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL ? wxLayout_RightToLeft : wxLayout_LeftToRight; } @@ -3338,7 +3341,7 @@ void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir) { wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") ); - gtk_widget_set_direction(GTK_WIDGET(widget), + gtk_widget_set_direction(widget, dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); } @@ -3369,7 +3372,7 @@ void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir) GTKSetLayout(m_widget, dir); - if (m_wxwindow) + if (m_wxwindow && (m_wxwindow != m_widget)) GTKSetLayout(m_wxwindow, dir); } @@ -3386,8 +3389,31 @@ void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move) { wxWindowBase::DoMoveInTabOrder(win, move); m_dirtyTabOrder = true; - if (g_isIdle) - wxapp_install_idle_handler(); + wxTheApp->WakeUpIdle(); +} + +bool wxWindowGTK::DoNavigateIn(int flags) +{ + if ( flags & wxNavigationKeyEvent::WinChange ) + { + wxFAIL_MSG( _T("not implemented") ); + + return false; + } + else // navigate inside the container + { + wxWindow *parent = wxGetTopLevelParent((wxWindow *)this); + wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") ); + + GtkDirectionType dir; + dir = flags & wxNavigationKeyEvent::IsForward ? GTK_DIR_TAB_FORWARD + : GTK_DIR_TAB_BACKWARD; + + gboolean rc; + g_signal_emit_by_name(parent->m_widget, "focus", dir, &rc); + + return rc == TRUE; + } } bool wxWindowGTK::GTKWidgetNeedsMnemonic() const @@ -3637,7 +3663,7 @@ void wxWindowGTK::GtkUpdate() { if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window) gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE ); - if (m_widget && m_widget->window) + if (m_widget && m_widget->window && (m_wxwindow != m_widget)) gdk_window_process_updates( m_widget->window, FALSE ); // for consistency with other platforms (and also because it's convenient @@ -3789,17 +3815,9 @@ void wxWindowGTK::DoSetToolTip( wxToolTip *tip ) m_tooltip->Apply( (wxWindow *)this ); } -void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const wxChar *tip ) +void wxWindowGTK::ApplyToolTip( GtkTooltips *tips, const gchar *tip ) { - if (tip) - { - wxString tmp( tip ); - gtk_tooltips_set_tip( tips, GetConnectWidget(), wxGTK_CONV(tmp), (gchar*) NULL ); - } - else - { - gtk_tooltips_set_tip( tips, GetConnectWidget(), NULL, NULL); - } + gtk_tooltips_set_tip(tips, GetConnectWidget(), tip, NULL); } #endif // wxUSE_TOOLTIPS @@ -3869,45 +3887,54 @@ GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle) pango_font_description_copy( m_font.GetNativeFontInfo()->description ); } + int flagsNormal = 0, + flagsPrelight = 0, + flagsActive = 0, + flagsInsensitive = 0; + if ( m_foregroundColour.Ok() ) { const GdkColor *fg = m_foregroundColour.GetColor(); - style->fg[GTK_STATE_NORMAL] = *fg; - style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG; + style->fg[GTK_STATE_NORMAL] = + style->text[GTK_STATE_NORMAL] = *fg; + flagsNormal |= GTK_RC_FG | GTK_RC_TEXT; - style->fg[GTK_STATE_PRELIGHT] = *fg; - style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG; + style->fg[GTK_STATE_PRELIGHT] = + style->text[GTK_STATE_PRELIGHT] = *fg; + flagsPrelight |= GTK_RC_FG | GTK_RC_TEXT; - style->fg[GTK_STATE_ACTIVE] = *fg; - style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG; + style->fg[GTK_STATE_ACTIVE] = + style->text[GTK_STATE_ACTIVE] = *fg; + flagsActive |= GTK_RC_FG | GTK_RC_TEXT; } if ( m_backgroundColour.Ok() ) { const GdkColor *bg = m_backgroundColour.GetColor(); - style->bg[GTK_STATE_NORMAL] = *bg; + style->bg[GTK_STATE_NORMAL] = style->base[GTK_STATE_NORMAL] = *bg; - style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags) - (style->color_flags[GTK_STATE_NORMAL] | GTK_RC_BG | GTK_RC_BASE); + flagsNormal |= GTK_RC_BG | GTK_RC_BASE; - style->bg[GTK_STATE_PRELIGHT] = *bg; + style->bg[GTK_STATE_PRELIGHT] = style->base[GTK_STATE_PRELIGHT] = *bg; - style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) - (style->color_flags[GTK_STATE_PRELIGHT] | GTK_RC_BG | GTK_RC_BASE); + flagsPrelight |= GTK_RC_BG | GTK_RC_BASE; - style->bg[GTK_STATE_ACTIVE] = *bg; + style->bg[GTK_STATE_ACTIVE] = style->base[GTK_STATE_ACTIVE] = *bg; - style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags) - (style->color_flags[GTK_STATE_ACTIVE] | GTK_RC_BG | GTK_RC_BASE); + flagsActive |= GTK_RC_BG | GTK_RC_BASE; - style->bg[GTK_STATE_INSENSITIVE] = *bg; + style->bg[GTK_STATE_INSENSITIVE] = style->base[GTK_STATE_INSENSITIVE] = *bg; - style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags) - (style->color_flags[GTK_STATE_INSENSITIVE] | GTK_RC_BG | GTK_RC_BASE); + flagsInsensitive |= GTK_RC_BG | GTK_RC_BASE; } + style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)flagsNormal; + style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)flagsPrelight; + style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)flagsActive; + style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)flagsInsensitive; + return style; } @@ -3938,11 +3965,16 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) if (style == wxBG_STYLE_CUSTOM) { - GdkWindow *window = (GdkWindow*) NULL; - if (m_wxwindow) + GdkWindow *window; + if ( m_wxwindow ) + { window = GTK_PIZZA(m_wxwindow)->bin_window; + } else - window = GetConnectWidget()->window; + { + GtkWidget * const w = GetConnectWidget(); + window = w ? w->window : NULL; + } if (window) { @@ -3955,9 +3987,11 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) #endif m_needsStyleChange = false; } - else + else // window not realized yet + { // Do in OnIdle, because the window is not yet available m_needsStyleChange = true; + } // Don't apply widget style, or we get a grey background } @@ -4073,6 +4107,14 @@ void wxWindowGTK::DoReleaseMouse() gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME ); } +void wxWindowGTK::GTKReleaseMouseAndNotify() +{ + DoReleaseMouse(); + wxMouseCaptureLostEvent evt(GetId()); + evt.SetEventObject( this ); + GetEventHandler()->ProcessEvent( evt ); +} + /* static */ wxWindow *wxWindowBase::GetCapture() { @@ -4102,8 +4144,8 @@ void wxWindowGTK::SetScrollbar(int orient, int range, bool WXUNUSED(update)) { - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); + GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; + wxCHECK_RET( sb, _T("this window is not scrollable") ); if (range > 0) { @@ -4120,7 +4162,7 @@ void wxWindowGTK::SetScrollbar(int orient, pos = range - thumbVisible; if (pos < 0) pos = 0; - GtkAdjustment* adj = m_scrollBar[ScrollDirFromOrient(orient)]->adjustment; + GtkAdjustment * const adj = sb->adjustment; adj->step_increment = 1; adj->page_increment = adj->page_size = thumbVisible; @@ -4131,15 +4173,15 @@ void wxWindowGTK::SetScrollbar(int orient, void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) { - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); + const int dir = ScrollDirFromOrient(orient); + GtkRange * const sb = m_scrollBar[dir]; + wxCHECK_RET( sb, _T("this window is not scrollable") ); // This check is more than an optimization. Without it, the slider // will not move smoothly while tracking when using wxScrollHelper. if (GetScrollPos(orient) != pos) { - const int dir = ScrollDirFromOrient(orient); - GtkAdjustment* adj = m_scrollBar[dir]->adjustment; + GtkAdjustment* adj = sb->adjustment; const int max = int(adj->upper - adj->page_size); if (pos > max) pos = max; @@ -4147,36 +4189,38 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) pos = 0; m_scrollPos[dir] = adj->value = pos; - // If a "value_changed" signal emission is not already in progress - if (!m_blockValueChanged[dir]) - { - gtk_adjustment_value_changed(adj); - } + g_signal_handlers_block_by_func(m_scrollBar[dir], + (gpointer)gtk_scrollbar_value_changed, this); + + gtk_adjustment_value_changed(adj); + + g_signal_handlers_unblock_by_func(m_scrollBar[dir], + (gpointer)gtk_scrollbar_value_changed, this); } } int wxWindowGTK::GetScrollThumb(int orient) const { - wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") ); - wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") ); + GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; + wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); - return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size); + return int(sb->adjustment->page_size); } int wxWindowGTK::GetScrollPos( int orient ) const { - wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") ); - wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") ); + GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; + wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); - return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5); + return int(sb->adjustment->value + 0.5); } int wxWindowGTK::GetScrollRange( int orient ) const { - wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") ); - wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") ); + GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; + wxCHECK_MSG( sb, 0, _T("this window is not scrollable") ); - return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper); + return int(sb->adjustment->upper); } // Determine if increment is the same as +/-x, allowing for some small @@ -4192,9 +4236,6 @@ wxEventType wxWindowGTK::GetScrollEventType(GtkRange* range) { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); - wxASSERT(range == m_scrollBar[0] || range == m_scrollBar[1]); const int barIndex = range == m_scrollBar[1]; @@ -4244,7 +4285,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) // No scrolling requested. if ((dx == 0) && (dy == 0)) return; - + m_clipPaintRegion = true; if (GetLayoutDirection() == wxLayout_RightToLeft)