X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6a17b868de5fd4b78988b355b9e1efbb766cd6f2..9b0b3151e03b347f8f153c1da73799fb575ac26c:/src/gtk/window.cpp?ds=sidebyside diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a73310396d..abd0171fe1 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -33,10 +33,9 @@ #include "wx/layout.h" #include "wx/statusbr.h" #include "wx/math.h" + #include "wx/module.h" #endif -#include "wx/module.h" - #if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" #endif @@ -79,8 +78,6 @@ #undef HAVE_XIM #endif -extern GtkContainerClass *pizza_parent_class; - //----------------------------------------------------------------------------- // documentation on internals //----------------------------------------------------------------------------- @@ -219,8 +216,6 @@ extern bool g_blockEventsOnDrag; extern bool g_blockEventsOnScroll; extern wxCursor g_globalCursor; -static GdkGC *g_eraseGC = NULL; - // mouse capture state: the window which has it and if the mouse is currently // inside it static wxWindowGTK *g_captureWindow = (wxWindowGTK*) NULL; @@ -407,13 +402,9 @@ gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win ) { - if (gdk_event->count > 0) return FALSE; - - draw_frame( widget, win ); - - (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); - - return TRUE; + if (gdk_event->count == 0) + draw_frame(widget, win); + return false; } } @@ -480,8 +471,7 @@ gtk_window_expose_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // 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 @@ -490,6 +480,7 @@ gtk_window_expose_callback( GtkWidget *widget, GtkPizza *pizza = GTK_PIZZA( widget ); if (gdk_event->window != pizza->bin_window) return FALSE; + #if 0 if (win->GetName()) { @@ -519,10 +510,7 @@ gtk_window_expose_callback( GtkWidget *widget, win->GtkSendPaintEvents(); - // Let parent window draw window-less widgets - (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); - return FALSE; } } @@ -991,8 +979,7 @@ gtk_window_key_press_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // don't need to install idle handler, its done from "event" signal if (!win->m_hasVMT) return FALSE; @@ -1124,10 +1111,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)) && @@ -1152,50 +1135,7 @@ gtk_window_key_press_callback( GtkWidget *widget, ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); } - // generate wxID_CANCEL if has been pressed (typically in dialogs) - if ( !ret && - (gdk_event->keyval == GDK_Escape) ) - { - // however only do it if we have a Cancel button in the dialog, - // otherwise the user code may get confused by the events from a - // nonexistent button and, worse, a wxButton might get button event - // from another button which is not really expected - wxWindow *winForCancel = win, - *btnCancel = NULL; - while ( winForCancel ) - { - btnCancel = winForCancel->FindWindow(wxID_CANCEL); - if ( btnCancel ) - { - // found a cancel button - break; - } - - if ( winForCancel->IsTopLevel() ) - { - // no need to look further - break; - } - - // maybe our parent has a cancel button? - winForCancel = winForCancel->GetParent(); - } - - if ( btnCancel ) - { - wxCommandEvent eventClick(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - eventClick.SetEventObject(btnCancel); - ret = btnCancel->GetEventHandler()->ProcessEvent(eventClick); - } - } - - if (ret) - { - g_signal_stop_emission_by_name (widget, "key_press_event"); - return TRUE; - } - - return FALSE; + return ret; } } @@ -1281,8 +1221,7 @@ gtk_window_key_release_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // don't need to install idle handler, its done from "event" signal if (!win->m_hasVMT) return FALSE; @@ -1297,11 +1236,7 @@ gtk_window_key_release_callback( GtkWidget *widget, return FALSE; } - if ( !win->GetEventHandler()->ProcessEvent( event ) ) - return FALSE; - - g_signal_stop_emission_by_name (widget, "key_release_event"); - return TRUE; + return win->GTKProcessEvent(event); } } @@ -1339,6 +1274,13 @@ template void InitMouseEvent(wxWindowGTK *win, wxPoint pt = win->GetClientAreaOrigin(); event.m_x = (wxCoord)gdk_event->x - pt.x; event.m_y = (wxCoord)gdk_event->y - pt.y; + + if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft)) + { + // origin in the upper right corner + int window_width = gtk_pizza_get_rtl_offset( GTK_PIZZA(win->m_wxwindow) ); + event.m_x = window_width - event.m_x; + } event.SetEventObject( win ); event.SetId( win->GetId() ); @@ -1387,8 +1329,8 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y) if (win->m_wxwindow) { GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow); - xx += pizza->xoffset; - yy += pizza->yoffset; + xx += gtk_pizza_get_xoffset( pizza ); + yy += gtk_pizza_get_yoffset( pizza ); } wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); @@ -1443,42 +1385,88 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y) return win; } +// ---------------------------------------------------------------------------- +// common event handlers helpers +// ---------------------------------------------------------------------------- + +bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const +{ + // nothing special at this level + return GetEventHandler()->ProcessEvent(event); +} + +int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const +{ + DEBUG_MAIN_THREAD + + // don't need to install idle handler, its done from "event" signal + + if (!m_hasVMT) + return FALSE; + if (g_blockEventsOnDrag) + return TRUE; + if (g_blockEventsOnScroll) + return TRUE; + + if (!GTKIsOwnWindow(event->window)) + return FALSE; + + return -1; +} + +// overloads for all GDK event types we use here: we need to have this as +// GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact, +// derives from it in the sense that the structs have the same layout +#define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T) \ + static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win) \ + { \ + return win->GTKCallbackCommonPrologue((GdkEventAny *)event); \ + } + +wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton) +wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion) +wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing) + +#undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD + +#define wxCOMMON_CALLBACK_PROLOGUE(event, win) \ + const int rc = wxGtkCallbackCommonPrologue(event, win); \ + if ( rc != -1 ) \ + return rc + +// send the wxChildFocusEvent and wxFocusEvent, common code of +// gtk_window_focus_in_callback() and SetFocus() +static bool DoSendFocusEvents(wxWindow *win) +{ + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. + wxChildFocusEvent eventChildFocus(win); + (void)win->GetEventHandler()->ProcessEvent(eventChildFocus); + + wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId()); + eventFocus.SetEventObject(win); + + return win->GetEventHandler()->ProcessEvent(eventFocus); +} + +// all event handlers must have C linkage as they're called from GTK+ C code +extern "C" +{ + //----------------------------------------------------------------------------- // "button_press_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win ) { - DEBUG_MAIN_THREAD - - if (g_isIdle) - wxapp_install_idle_handler(); - -/* - wxPrintf( wxT("1) OnButtonPress from ") ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - wxPrintf( win->GetClassInfo()->GetClassName() ); - wxPrintf( wxT(".\n") ); -*/ - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return TRUE; - if (g_blockEventsOnScroll) return TRUE; - - if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; + wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus()) { gtk_widget_grab_focus( win->m_wxwindow ); -/* - wxPrintf( wxT("GrabFocus from ") ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - wxPrintf( win->GetClassInfo()->GetClassName() ); - wxPrintf( wxT(".\n") ); -*/ } // GDK sends surplus button down events @@ -1611,9 +1599,8 @@ gtk_window_button_press_callback( GtkWidget *widget, event.SetEventObject( win ); event.SetId( win->GetId() ); - if (win->GetEventHandler()->ProcessEvent( event )) + if (win->GTKProcessEvent( event )) { - g_signal_stop_emission_by_name (widget, "button_press_event"); return TRUE; } @@ -1631,33 +1618,22 @@ gtk_window_button_press_callback( GtkWidget *widget, win->GetId(), win->ClientToScreen(event.GetPosition())); evtCtx.SetEventObject(win); - return win->GetEventHandler()->ProcessEvent(evtCtx); + return win->GTKProcessEvent(evtCtx); } return FALSE; } -} //----------------------------------------------------------------------------- // "button_release_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win ) { - DEBUG_MAIN_THREAD - - if (g_isIdle) - wxapp_install_idle_handler(); - - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; - if (g_blockEventsOnScroll) return FALSE; - - if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; + wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); wxEventType event_type = wxEVT_NULL; @@ -1695,36 +1671,19 @@ gtk_window_button_release_callback( GtkWidget *widget, event.SetEventObject( win ); event.SetId( win->GetId() ); - if (win->GetEventHandler()->ProcessEvent( event )) - { - g_signal_stop_emission_by_name (widget, "button_release_event"); - return TRUE; - } - - return FALSE; -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "motion_notify_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindowGTK *win ) { - DEBUG_MAIN_THREAD - - if (g_isIdle) - wxapp_install_idle_handler(); - - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; - if (g_blockEventsOnScroll) return FALSE; - - if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; + wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); if (gdk_event->is_hint) { @@ -1736,13 +1695,6 @@ gtk_window_motion_notify_callback( GtkWidget *widget, gdk_event->y = y; } -/* - printf( "OnMotion from " ); - if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) - printf( win->GetClassInfo()->GetClassName() ); - printf( ".\n" ); -*/ - wxMouseEvent event( wxEVT_MOTION ); InitMouseEvent(win, event, gdk_event); @@ -1764,7 +1716,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget, : wxEVT_LEAVE_WINDOW); InitMouseEvent(win, eventM, gdk_event); eventM.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(eventM); + win->GTKProcessEvent(eventM); } } else // no capture @@ -1779,34 +1731,25 @@ gtk_window_motion_notify_callback( GtkWidget *widget, if ( !g_captureWindow ) { wxSetCursorEvent cevent( event.m_x, event.m_y ); - if (win->GetEventHandler()->ProcessEvent( cevent )) + if (win->GTKProcessEvent( cevent )) { - // Rewrite cursor handling here (away from idle). + win->SetCursor( cevent.GetCursor() ); } } - if (win->GetEventHandler()->ProcessEvent( event )) - { - g_signal_stop_emission_by_name (widget, "motion_notify_event"); - return TRUE; - } - - return FALSE; -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "scroll_event", (mouse wheel event) //----------------------------------------------------------------------------- -extern "C" { static gboolean window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // 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) @@ -1839,45 +1782,24 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) event.SetId( win->GetId() ); event.SetTimestamp( gdk_event->time ); - return win->GetEventHandler()->ProcessEvent(event); -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "popup-menu" //----------------------------------------------------------------------------- -extern "C" { + static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win) { - wxContextMenuEvent event( - wxEVT_CONTEXT_MENU, - win->GetId(), - wxPoint(-1, -1)); + wxContextMenuEvent event(wxEVT_CONTEXT_MENU, win->GetId(), wxPoint(-1, -1)); event.SetEventObject(win); - return win->GetEventHandler()->ProcessEvent(event); -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "focus_in_event" //----------------------------------------------------------------------------- -// send the wxChildFocusEvent and wxFocusEvent, common code of -// gtk_window_focus_in_callback() and SetFocus() -static bool DoSendFocusEvents(wxWindow *win) -{ - // Notify the parent keeping track of focus for the kbd navigation - // purposes that we got it. - wxChildFocusEvent eventChildFocus(win); - (void)win->GetEventHandler()->ProcessEvent(eventChildFocus); - - wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId()); - eventFocus.SetEventObject(win); - - return win->GetEventHandler()->ProcessEvent(eventFocus); -} - -extern "C" { static gboolean gtk_window_focus_in_callback( GtkWidget *widget, GdkEventFocus *WXUNUSED(event), @@ -1885,8 +1807,7 @@ gtk_window_focus_in_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // 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); @@ -1931,13 +1852,11 @@ gtk_window_focus_in_callback( GtkWidget *widget, return FALSE; } -} //----------------------------------------------------------------------------- // "focus_out_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk_event, @@ -1945,8 +1864,7 @@ gtk_window_focus_out_callback( GtkWidget *widget, { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // 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); @@ -1986,7 +1904,7 @@ gtk_window_focus_out_callback( GtkWidget *widget, wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); event.SetEventObject( win ); - (void)win->GetEventHandler()->ProcessEvent( event ); + (void)win->GTKProcessEvent( event ); ret = TRUE; } @@ -1998,31 +1916,21 @@ gtk_window_focus_out_callback( GtkWidget *widget, return FALSE; } -} //----------------------------------------------------------------------------- // "enter_notify_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win ) { - DEBUG_MAIN_THREAD - - if (g_isIdle) - wxapp_install_idle_handler(); - - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; + wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); // Event was emitted after a grab if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE; - if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; - int x = 0; int y = 0; GdkModifierType state = (GdkModifierType)0; @@ -2038,45 +1946,29 @@ gtk_window_enter_callback( GtkWidget *widget, if ( !g_captureWindow ) { wxSetCursorEvent cevent( event.m_x, event.m_y ); - if (win->GetEventHandler()->ProcessEvent( cevent )) + if (win->GTKProcessEvent( cevent )) { - // Rewrite cursor handling here (away from idle). + win->SetCursor( cevent.GetCursor() ); } } - if (win->GetEventHandler()->ProcessEvent( event )) - { - g_signal_stop_emission_by_name (widget, "enter_notify_event"); - return TRUE; - } - - return FALSE; -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "leave_notify_event" //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win ) { - DEBUG_MAIN_THREAD - - if (g_isIdle) - wxapp_install_idle_handler(); - - if (!win->m_hasVMT) return FALSE; - if (g_blockEventsOnDrag) return FALSE; + wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win); // Event was emitted after an ungrab if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE; - if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; - wxMouseEvent event( wxEVT_LEAVE_WINDOW ); event.SetTimestamp( gdk_event->time ); event.SetEventObject( win ); @@ -2099,21 +1991,13 @@ gtk_window_leave_callback( GtkWidget *widget, event.m_x = x + pt.x; event.m_y = y + pt.y; - if (win->GetEventHandler()->ProcessEvent( event )) - { - g_signal_stop_emission_by_name (widget, "leave_notify_event"); - return TRUE; - } - - return FALSE; -} + return win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- // "value_changed" from scrollbar //----------------------------------------------------------------------------- -extern "C" { static void gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win) { @@ -2122,42 +2006,42 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win) { // Convert scroll event type to scrollwin event type eventType += wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP; - const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL; - const int i = orient == wxVERTICAL; + + // find the scrollbar which generated the event + wxWindowGTK::ScrollDir dir = win->ScrollDirFromRange(range); + + // generate the corresponding wx event + const int orient = win->OrientFromScrollDir(dir); wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient); event.SetEventObject(win); - win->m_blockValueChanged[i] = true; - win->GetEventHandler()->ProcessEvent(event); - win->m_blockValueChanged[i] = false; + + win->m_blockValueChanged[dir] = true; + win->GTKProcessEvent(event); + win->m_blockValueChanged[dir] = false; } } -} //----------------------------------------------------------------------------- // "button_press_event" from scrollbar //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win) { DEBUG_MAIN_THREAD - if (g_isIdle) - wxapp_install_idle_handler(); + // don't need to install idle handler, its done from "event" signal g_blockEventsOnScroll = true; win->m_mouseButtonDown = true; return false; } -} //----------------------------------------------------------------------------- // "event_after" from scrollbar //----------------------------------------------------------------------------- -extern "C" { static void gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win) { @@ -2165,19 +2049,18 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win) { g_signal_handlers_block_by_func(range, (void*)gtk_scrollbar_event_after, win); - const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL; + const int orient = win->OrientFromScrollDir( + win->ScrollDirFromRange(range)); wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient); event.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(event); + win->GTKProcessEvent(event); } } -} //----------------------------------------------------------------------------- // "button_release_event" from scrollbar //----------------------------------------------------------------------------- -extern "C" { static gboolean gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* win) { @@ -2197,18 +2080,6 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w return false; } -} - -// ---------------------------------------------------------------------------- -// this wxWindowBase function is implemented here (in platform-specific file) -// because it is static and so couldn't be made virtual -// ---------------------------------------------------------------------------- - -wxWindow *wxWindowBase::DoFindFocus() -{ - // the cast is necessary when we compile in wxUniversal mode - return (wxWindow *)g_focusWindow; -} //----------------------------------------------------------------------------- // "realize" from m_widget @@ -2217,7 +2088,6 @@ wxWindow *wxWindowBase::DoFindFocus() /* We cannot set colours and fonts before the widget has been realized, so we do this directly after realization. */ -extern "C" { static void gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win ) { @@ -2235,18 +2105,16 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win ) wxWindowCreateEvent event( win ); event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); -} + win->GTKProcessEvent( event ); } //----------------------------------------------------------------------------- // "size_allocate" //----------------------------------------------------------------------------- -extern "C" { static void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), - GtkAllocation *WXUNUSED(alloc), + GtkAllocation *alloc, wxWindow *win ) { if (g_isIdle) @@ -2258,6 +2126,19 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight)) return; +#if 0 + wxPrintf( wxT("size_allocate ") ); + if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) + wxPrintf( win->GetClassInfo()->GetClassName() ); + wxPrintf( wxT(" %d %d %d %d\n"), + alloc->x, + alloc->y, + alloc->width, + alloc->height ); +#endif + + GTK_PIZZA(win->m_wxwindow)->m_width = win->GetClientSize().x; + win->m_oldClientWidth = client_width; win->m_oldClientHeight = client_height; @@ -2265,10 +2146,9 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), { wxSizeEvent event( win->GetSize(), win->GetId() ); event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); + win->GTKProcessEvent( event ); } } -} #ifdef HAVE_XIM @@ -2278,8 +2158,6 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), #endif /* Resize XIM window */ - -extern "C" { static void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget), GtkAllocation* WXUNUSED_UNLESS_XIM(alloc), @@ -2303,7 +2181,6 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget), } #endif // HAVE_XIM } -} //----------------------------------------------------------------------------- // "realize" from m_wxwindow @@ -2311,7 +2188,6 @@ void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget), /* Initialize XIM support */ -extern "C" { static void gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget), wxWindowGTK * WXUNUSED_UNLESS_XIM(win) ) @@ -2396,6 +2272,18 @@ gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget), } #endif // HAVE_XIM } + +} // extern "C" + +// ---------------------------------------------------------------------------- +// this wxWindowBase function is implemented here (in platform-specific file) +// because it is static and so couldn't be made virtual +// ---------------------------------------------------------------------------- + +wxWindow *wxWindowBase::DoFindFocus() +{ + // the cast is necessary when we compile in wxUniversal mode + return (wxWindow *)g_focusWindow; } //----------------------------------------------------------------------------- @@ -2414,8 +2302,8 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child ) /* the window might have been scrolled already, do we have to adapt the position */ GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow); - child->m_x += pizza->xoffset; - child->m_y += pizza->yoffset; + child->m_x += gtk_pizza_get_xoffset( pizza ); + child->m_y += gtk_pizza_get_yoffset( pizza ); gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow), GTK_WIDGET(child->m_widget), @@ -2489,6 +2377,8 @@ void wxWindowGTK::Init() m_needParent = true; m_isBeingDeleted = false; + m_showOnIdle= false; + m_noExpose = false; m_nativeSizeEvent = false; @@ -2497,12 +2387,13 @@ void wxWindowGTK::Init() m_mouseButtonDown = false; m_blockScrollEvent = false; - m_scrollBar[0] = - m_scrollBar[1] = NULL; - m_scrollPos[0] = - m_scrollPos[1] = 0; - m_blockValueChanged[0] = - m_blockValueChanged[1] = false; + // initialize scrolling stuff + for ( int dir = 0; dir < ScrollDir_Max; dir++ ) + { + m_scrollBar[dir] = NULL; + m_scrollPos[dir] = 0; + m_blockValueChanged[dir] = false; + } m_oldClientWidth = m_oldClientHeight = 0; @@ -2567,14 +2458,14 @@ bool wxWindowGTK::Create( wxWindow *parent, gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - m_scrollBar[0] = GTK_RANGE(scrolledWindow->hscrollbar); - m_scrollBar[1] = GTK_RANGE(scrolledWindow->vscrollbar); + m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar); + m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar); m_wxwindow = gtk_pizza_new(); #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - + if (HasFlag(wxRAISED_BORDER)) { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT ); @@ -2598,31 +2489,25 @@ bool wxWindowGTK::Create( wxWindow *parent, GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); m_acceptsFocus = true; - // 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[0], "button_press_event", - G_CALLBACK(gtk_scrollbar_button_press_event), this); - g_signal_connect(m_scrollBar[1], "button_press_event", - G_CALLBACK(gtk_scrollbar_button_press_event), this); - g_signal_connect(m_scrollBar[0], "button_release_event", - G_CALLBACK(gtk_scrollbar_button_release_event), this); - g_signal_connect(m_scrollBar[1], "button_release_event", - G_CALLBACK(gtk_scrollbar_button_release_event), this); - gulong handler_id; - handler_id = g_signal_connect( - m_scrollBar[0], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this); - g_signal_handler_block(m_scrollBar[0], handler_id); - handler_id = g_signal_connect( - m_scrollBar[1], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this); - g_signal_handler_block(m_scrollBar[1], handler_id); - - // these handlers get notified when scrollbar slider moves - - g_signal_connect(m_scrollBar[0], "value_changed", - G_CALLBACK(gtk_scrollbar_value_changed), this); - g_signal_connect(m_scrollBar[1], "value_changed", - G_CALLBACK(gtk_scrollbar_value_changed), this); + // 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_CALLBACK(gtk_scrollbar_button_release_event), this); + + 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); + + // these handlers get notified when scrollbar slider moves + g_signal_connect(m_scrollBar[dir], "value_changed", + G_CALLBACK(gtk_scrollbar_value_changed), this); + } gtk_widget_show( m_wxwindow ); @@ -2715,12 +2600,11 @@ void wxWindowGTK::PostCreation() { // these get reported to wxWidgets -> wxPaintEvent - gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE ); - g_signal_connect (m_wxwindow, "expose_event", G_CALLBACK (gtk_window_expose_callback), this); - gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); + if (GetLayoutDirection() == wxLayout_LeftToRight) + gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); } // Create input method handler @@ -2795,7 +2679,7 @@ void wxWindowGTK::PostCreation() this); } #ifdef GTK_IS_FILE_CHOOSER_BUTTON - else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) + else if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) { // If we connect to the "size_request" signal of a GtkFileChooserButton // then that control won't be sized properly when placed inside sizers @@ -2818,6 +2702,8 @@ void wxWindowGTK::PostCreation() m_hasVMT = true; + SetLayoutDirection(wxLayout_Default); + // unless the window was created initially hidden (i.e. Hide() had been // called before Create()), we should show it at GTK+ level as well if ( IsShown() ) @@ -2857,7 +2743,9 @@ bool wxWindowGTK::Destroy() void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) { + // inform the parent to perform the move gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height ); + } void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags ) @@ -2865,10 +2753,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") ); wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") ); -/* - printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); -*/ - if (m_resizing) return; /* I don't like recursions */ m_resizing = true; @@ -2912,8 +2796,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags // don't take the x,y values, they're wrong because toolbar sets them GtkWidget *widget = GTK_WIDGET(m_widget); gtk_widget_set_size_request (widget, m_width, m_height); - if (GTK_WIDGET_VISIBLE (widget)) - gtk_widget_queue_resize (widget); } else #endif @@ -2930,13 +2812,13 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow); if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0) { - if (x != -1) m_x = x + pizza->xoffset; - if (y != -1) m_y = y + pizza->yoffset; + if (x != -1) m_x = x + gtk_pizza_get_xoffset( pizza ); + if (y != -1) m_y = y + gtk_pizza_get_yoffset( pizza ); } else { - m_x = x + pizza->xoffset; - m_y = y + pizza->yoffset; + m_x = x + gtk_pizza_get_xoffset( pizza ); + m_y = y + gtk_pizza_get_yoffset( pizza ); } int left_border = 0; @@ -2993,8 +2875,32 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags m_resizing = false; } +bool wxWindowGTK::GtkShowFromOnIdle() +{ + if (IsShown() && m_showOnIdle && !GTK_WIDGET_VISIBLE (m_widget)) + { + GtkAllocation alloc; + alloc.x = m_x; + alloc.y = m_y; + alloc.width = m_width; + alloc.height = m_height; + gtk_widget_size_allocate( m_widget, &alloc ); + gtk_widget_show( m_widget ); + wxShowEvent eventShow(GetId(), true); + eventShow.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventShow); + m_showOnIdle = false; + return true; + } + + return false; +} + void wxWindowGTK::OnInternalIdle() { + // Check if we have to show window now + if (GtkShowFromOnIdle()) return; + if ( m_dirtyTabOrder ) { m_dirtyTabOrder = false; @@ -3009,9 +2915,6 @@ void wxWindowGTK::OnInternalIdle() m_needsStyleChange = false; } - // Update invalidated regions. - GtkUpdate(); - wxCursor cursor = m_cursor; if (g_globalCursor.Ok()) cursor = g_globalCursor; @@ -3036,13 +2939,11 @@ void wxWindowGTK::OnInternalIdle() gdk_window_set_cursor( window, cursor.GetCursor() ); } - else + else if ( m_widget ) { - GdkWindow *window = m_widget->window; - if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget))) + if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) ) gdk_window_set_cursor( window, cursor.GetCursor() ); - } } @@ -3128,6 +3029,10 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const w -= dw; h -= dh; + if (w < 0) + w = 0; + if (h < 0) + h = 0; } if (width) *width = w; @@ -3143,8 +3048,30 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const if (m_parent && m_parent->m_wxwindow) { GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow); - dx = pizza->xoffset; - dy = pizza->yoffset; + dx = gtk_pizza_get_xoffset( pizza ); + dy = gtk_pizza_get_yoffset( pizza ); + } + + if (m_x == -1 && m_y == -1) + { + GdkWindow *source = (GdkWindow *) NULL; + if (m_wxwindow) + source = GTK_PIZZA(m_wxwindow)->bin_window; + else + source = m_widget->window; + + if (source) + { + int org_x = 0; + int org_y = 0; + gdk_window_get_origin( source, &org_x, &org_y ); + + if (GetParent()) + GetParent()->ScreenToClient(&org_x, &org_y); + + ((wxWindowGTK*) this)->m_x = org_x; + ((wxWindowGTK*) this)->m_y = org_y; + } } if (x) (*x) = m_x - dx; @@ -3176,7 +3103,15 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const } } - if (x) *x += org_x; + + if (x) + { + if (GetLayoutDirection() == wxLayout_RightToLeft) + *x = (GetClientSize().x - *x) + org_x; + else + *x += org_x; + } + if (y) *y += org_y; } @@ -3205,7 +3140,13 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const } } - if (x) *x -= org_x; + if (x) + { + if (GetLayoutDirection() == wxLayout_RightToLeft) + *x = (GetClientSize().x - *x) - org_x; + else + *x -= org_x; + } if (y) *y -= org_y; } @@ -3220,14 +3161,22 @@ bool wxWindowGTK::Show( bool show ) } if (show) - gtk_widget_show( m_widget ); + { + if (!m_showOnIdle) + { + gtk_widget_show( m_widget ); + wxShowEvent eventShow(GetId(), show); + eventShow.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventShow); + } + } else + { gtk_widget_hide( m_widget ); - - wxShowEvent eventShow(GetId(), show); - eventShow.SetEventObject(this); - - GetEventHandler()->ProcessEvent(eventShow); + wxShowEvent eventShow(GetId(), show); + eventShow.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventShow); + } return true; } @@ -3379,6 +3328,22 @@ void wxWindowGTK::GetTextExtent( const wxString& string, g_object_unref (layout); } +bool wxWindowGTK::GTKSetDelayedFocusIfNeeded() +{ + if ( g_delayedFocus == this ) + { + if ( GTK_WIDGET_REALIZED(m_widget) ) + { + gtk_widget_grab_focus(m_widget); + g_delayedFocus = NULL; + + return true; + } + } + + return false; +} + void wxWindowGTK::SetFocus() { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); @@ -3465,6 +3430,12 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) if (newParent) { + if (GTK_WIDGET_VISIBLE (newParent->m_widget)) + { + m_showOnIdle = true; + gtk_widget_hide( m_widget ); + } + /* insert GTK representation */ (*(newParent->m_insertCallback))(newParent, this); } @@ -3472,6 +3443,8 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) /* reverse: prevent GTK from deleting the widget arbitrarily */ gtk_widget_unref( m_widget ); + SetLayoutDirection(wxLayout_Default); + return true; } @@ -3506,6 +3479,63 @@ void wxWindowGTK::RemoveChild(wxWindowBase *child) wxapp_install_idle_handler(); } +/* static */ +wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget) +{ + return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL + ? wxLayout_RightToLeft + : wxLayout_LeftToRight; +} + +/* static */ +void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir) +{ + wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") ); + + gtk_widget_set_direction(GTK_WIDGET(widget), + dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL + : GTK_TEXT_DIR_LTR); +} + +wxLayoutDirection wxWindowGTK::GetLayoutDirection() const +{ + return GTKGetLayout(m_widget); +} + +void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir) +{ + if ( dir == wxLayout_Default ) + { + const wxWindow *const parent = GetParent(); + if ( parent ) + { + // inherit layout from parent. + dir = parent->GetLayoutDirection(); + } + else // no parent, use global default layout + { + dir = wxTheApp->GetLayoutDirection(); + } + } + + if ( dir == wxLayout_Default ) + return; + + GTKSetLayout(m_widget, dir); + + if (m_wxwindow) + GTKSetLayout(m_wxwindow, dir); +} + +wxCoord +wxWindowGTK::AdjustForLayoutDirection(wxCoord x, + wxCoord WXUNUSED(width), + wxCoord WXUNUSED(widthTotal)) const +{ + // We now mirrors the coordinates of RTL windows in GtkPizza + return x; +} + void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move) { wxWindowBase::DoMoveInTabOrder(win, move); @@ -3616,18 +3646,41 @@ void wxWindowGTK::Lower() bool wxWindowGTK::SetCursor( const wxCursor &cursor ) { - wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") ); + if ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) ) + return false; - if (cursor == m_cursor) - return false; + GTKUpdateCursor(); - if (g_isIdle) - wxapp_install_idle_handler(); + return true; +} - if (cursor == wxNullCursor) - return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ); - else - return wxWindowBase::SetCursor( cursor ); +void wxWindowGTK::GTKUpdateCursor() +{ + wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor()); + if ( cursor.Ok() ) + { + wxArrayGdkWindows windowsThis; + GdkWindow * const winThis = GTKGetWindow(windowsThis); + if ( winThis ) + { + gdk_window_set_cursor(winThis, cursor.GetCursor()); + } + else + { + const size_t count = windowsThis.size(); + for ( size_t n = 0; n < count; n++ ) + { + GdkWindow *win = windowsThis[n]; + if ( !win ) + { + wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?")); + continue; + } + + gdk_window_set_cursor(win, cursor.GetCursor()); + } + } + } } void wxWindowGTK::WarpPointer( int x, int y ) @@ -3647,34 +3700,49 @@ void wxWindowGTK::WarpPointer( int x, int y ) gdk_window_warp_pointer( window, x, y ); } -bool wxWindowGTK::ScrollLines(int lines) +wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const { - bool changed = false; - GtkRange* range = m_scrollBar[1]; - if (range != NULL) + // find the scrollbar which generated the event + for ( int dir = 0; dir < ScrollDir_Max; dir++ ) { - GtkAdjustment* adj = range->adjustment; - const int pos = int(adj->value + 0.5); - gtk_range_set_value(range, pos + lines); - changed = pos != int(adj->value + 0.5); + if ( range == m_scrollBar[dir] ) + return (ScrollDir)dir; } - return changed; + + wxFAIL_MSG( _T("event from unknown scrollbar received") ); + + return ScrollDir_Max; } -bool wxWindowGTK::ScrollPages(int pages) +bool wxWindowGTK::DoScrollByUnits(ScrollDir dir, ScrollUnit unit, int units) { bool changed = false; - GtkRange* range = m_scrollBar[1]; - if (range != NULL) + GtkRange* range = m_scrollBar[dir]; + if ( range && units ) { GtkAdjustment* adj = range->adjustment; - const int pos = int(adj->value + 0.5); - gtk_range_set_value(range, pos + pages * adj->page_size); - changed = pos != int(adj->value + 0.5); + gdouble inc = unit == ScrollUnit_Line ? adj->step_increment + : adj->page_increment; + + const int posOld = int(adj->value + 0.5); + gtk_range_set_value(range, posOld + units*inc); + + changed = int(adj->value + 0.5) != posOld; } + return changed; } +bool wxWindowGTK::ScrollLines(int lines) +{ + return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Line, lines); +} + +bool wxWindowGTK::ScrollPages(int pages) +{ + return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Page, pages); +} + void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) { if (!m_widget) @@ -3684,6 +3752,8 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) if (m_wxwindow) { + if (!GTK_PIZZA(m_wxwindow)->bin_window) return; + GdkRectangle gdk_rect, *p; if (rect) @@ -3692,13 +3762,15 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) gdk_rect.y = rect->y; gdk_rect.width = rect->width; gdk_rect.height = rect->height; + if (GetLayoutDirection() == wxLayout_RightToLeft) + gdk_rect.x = GetClientSize().x - gdk_rect.x - gdk_rect.width; p = &gdk_rect; } else // invalidate everything { p = NULL; } - + gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE ); } } @@ -3718,6 +3790,8 @@ 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) + gdk_window_process_updates( m_widget->window, FALSE ); // for consistency with other platforms (and also because it's convenient // to be able to update an entire TLW by calling Update() only once), we @@ -3730,6 +3804,20 @@ void wxWindowGTK::GtkUpdate() } } +bool wxWindowGTK::DoIsExposed( int x, int y ) const +{ + return m_updateRegion.Contains(x, y) != wxOutRegion; +} + + +bool wxWindowGTK::DoIsExposed( int x, int y, int w, int h ) const +{ + if (GetLayoutDirection() == wxLayout_RightToLeft) + return m_updateRegion.Contains(x-w, y, w, h) != wxOutRegion; + else + return m_updateRegion.Contains(x, y, w, h) != wxOutRegion; +} + void wxWindowGTK::GtkSendPaintEvents() { if (!m_wxwindow) @@ -3741,6 +3829,34 @@ void wxWindowGTK::GtkSendPaintEvents() // Clip to paint region in wxClientDC m_clipPaintRegion = true; + wxRegion maybe_rtl_region = m_updateRegion; + +#if 0 + if (GetLayoutDirection() == wxLayout_RightToLeft) + { + maybe_rtl_region.Clear(); + + gint width; + gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window, + NULL, NULL, &width, NULL, NULL ); + + wxRegionIterator upd( m_updateRegion ); + while (upd) + { + wxRect rect; + rect.x = upd.GetX(); + rect.y = upd.GetY(); + rect.width = upd.GetWidth(); + rect.height = upd.GetHeight(); + + rect.x = width - rect.x - rect.width; + maybe_rtl_region.Union( rect ); + + ++upd; + } + } +#endif + // widget to draw on GtkPizza *pizza = GTK_PIZZA (m_wxwindow); @@ -3776,8 +3892,9 @@ void wxWindowGTK::GtkSendPaintEvents() } } else - { + m_updateRegion = maybe_rtl_region; + wxWindowDC dc( (wxWindow*)this ); dc.SetClippingRegion( m_updateRegion ); @@ -3787,6 +3904,8 @@ void wxWindowGTK::GtkSendPaintEvents() GetEventHandler()->ProcessEvent(erase_event); } + m_updateRegion = maybe_rtl_region; + wxNcPaintEvent nc_paint_event( GetId() ); nc_paint_event.SetEventObject( this ); GetEventHandler()->ProcessEvent( nc_paint_event ); @@ -4022,12 +4141,18 @@ GtkWidget* wxWindowGTK::GetConnectWidget() return connect_widget; } -bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window ) +bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const { - if (m_wxwindow) - return (window == GTK_PIZZA(m_wxwindow)->bin_window); + wxArrayGdkWindows windowsThis; + GdkWindow * const winThis = GTKGetWindow(windowsThis); + + return winThis ? window == winThis + : windowsThis.Index(window) != wxNOT_FOUND; +} - return (window == m_widget->window); +GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const +{ + return m_wxwindow ? GTK_PIZZA(m_wxwindow)->bin_window : m_widget->window; } bool wxWindowGTK::SetFont( const wxFont &font ) @@ -4116,8 +4241,11 @@ void wxWindowGTK::UnblockScrollEvent() m_blockScrollEvent = false; } -void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible, - int range, bool ) +void wxWindowGTK::SetScrollbar(int orient, + int pos, + int thumbVisible, + 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") ); @@ -4137,8 +4265,7 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible, pos = range - thumbVisible; if (pos < 0) pos = 0; - const int i = orient == wxVERTICAL; - GtkAdjustment* adj = m_scrollBar[i]->adjustment; + GtkAdjustment* adj = m_scrollBar[ScrollDirFromOrient(orient)]->adjustment; adj->step_increment = 1; adj->page_increment = adj->page_size = thumbVisible; @@ -4147,7 +4274,7 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible, gtk_adjustment_changed(adj); } -void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) +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") ); @@ -4156,30 +4283,29 @@ void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) // will not move smoothly while tracking when using wxScrollHelper. if (GetScrollPos(orient) != pos) { - const int i = orient == wxVERTICAL; - GtkAdjustment* adj = m_scrollBar[i]->adjustment; + const int dir = ScrollDirFromOrient(orient); + GtkAdjustment* adj = m_scrollBar[dir]->adjustment; const int max = int(adj->upper - adj->page_size); if (pos > max) pos = max; if (pos < 0) pos = 0; - m_scrollPos[i] = + m_scrollPos[dir] = adj->value = pos; // If a "value_changed" signal emission is not already in progress - if (!m_blockValueChanged[i]) + if (!m_blockValueChanged[dir]) { gtk_adjustment_value_changed(adj); } } } -int wxWindowGTK::GetScrollThumb( int orient ) const +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") ); - const int i = orient == wxVERTICAL; - return int(m_scrollBar[i]->adjustment->page_size); + return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size); } int wxWindowGTK::GetScrollPos( int orient ) const @@ -4187,8 +4313,7 @@ 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") ); - const int i = orient == wxVERTICAL; - return int(m_scrollBar[i]->adjustment->value + 0.5); + return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5); } int wxWindowGTK::GetScrollRange( int orient ) const @@ -4196,8 +4321,7 @@ 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") ); - const int i = orient == wxVERTICAL; - return int(m_scrollBar[i]->adjustment->upper); + return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper); } // Determine if increment is the same as +/-x, allowing for some small @@ -4349,33 +4473,3 @@ void wxRemoveGrab(wxWindow* window) { gtk_grab_remove( (GtkWidget*) window->GetHandle() ); } - -// ---------------------------------------------------------------------------- -// wxWinModule -// ---------------------------------------------------------------------------- - -class wxWinModule : public wxModule -{ -public: - bool OnInit(); - void OnExit(); - -private: - DECLARE_DYNAMIC_CLASS(wxWinModule) -}; - -IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule) - -bool wxWinModule::OnInit() -{ - // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() ); - // gdk_gc_set_fill( g_eraseGC, GDK_SOLID ); - - return true; -} - -void wxWinModule::OnExit() -{ - if (g_eraseGC) - g_object_unref (g_eraseGC); -}