X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/276f883f7acd637e94b7b4078af84e058667bab0..74a8f67d96591cec101def2a7d47c64072aff7fd:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 30985280bd..ed62554673 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -37,9 +37,14 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/win_gtk.h" -#include + #include +#include +#if GTK_CHECK_VERSION(3,0,0) +#include +#endif + #if !GTK_CHECK_VERSION(2,10,0) // GTK+ can reliably detect Meta key state only since 2.10 when // GDK_META_MASK was introduced -- there wasn't any way to detect it @@ -308,7 +313,8 @@ expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win) if (!win->IsShown()) return false; - const GtkAllocation& alloc = win->m_wxwindow->allocation; + GtkAllocation alloc; + gtk_widget_get_allocation(win->m_wxwindow, &alloc); const int x = alloc.x; const int y = alloc.y; const int w = alloc.width; @@ -320,7 +326,7 @@ expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win) if (win->HasFlag(wxBORDER_SIMPLE)) { gdk_draw_rectangle(gdk_event->window, - widget->style->black_gc, false, x, y, w - 1, h - 1); + gtk_widget_get_style(widget)->black_gc, false, x, y, w - 1, h - 1); } else { @@ -337,9 +343,12 @@ expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win) // for scrollable ones detail = "viewport"; + // clip rect is required to avoid painting background + // over upper left (w,h) of parent window + GdkRectangle clipRect = { x, y, w, h }; gtk_paint_shadow( - win->m_wxwindow->style, gdk_event->window, GTK_STATE_NORMAL, - shadow, NULL, wxGTKPrivate::GetEntryWidget(), detail, x, y, w, h); + gtk_widget_get_style(win->m_wxwindow), gdk_event->window, GTK_STATE_NORMAL, + shadow, &clipRect, wxGTKPrivate::GetEntryWidget(), detail, x, y, w, h); } return false; } @@ -358,9 +367,10 @@ parent_set(GtkWidget* widget, GtkObject* old_parent, wxWindow* win) g_signal_handlers_disconnect_by_func( old_parent, (void*)expose_event_border, win); } - if (widget->parent) + GtkWidget* parent = gtk_widget_get_parent(widget); + if (parent) { - g_signal_connect_after(widget->parent, "expose_event", + g_signal_connect_after(parent, "expose_event", G_CALLBACK(expose_event_border), win); } } @@ -672,34 +682,61 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event, wxWindowGTK *win, GdkEventKey *gdk_event) { - int x = 0; - int y = 0; - GdkModifierType state; - if (gdk_event->window) - gdk_window_get_pointer(gdk_event->window, &x, &y, &state); - event.SetTimestamp( gdk_event->time ); event.SetId(win->GetId()); + event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0; event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0; event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0; event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0; - event.m_rawCode = (wxUint32) gdk_event->keyval; - event.m_rawFlags = 0; -#if wxUSE_UNICODE - event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval); - if ( !event.m_uniChar && event.m_keyCode <= WXK_DELETE ) + + // Normally we take the state of modifiers directly from the low level GDK + // event but unfortunately GDK uses a different convention from MSW for the + // key events corresponding to the modifier keys themselves: in it, when + // e.g. Shift key is pressed, GDK_SHIFT_MASK is not set while it is set + // when Shift is released. Under MSW the situation is exactly reversed and + // the modifier corresponding to the key is set when it is pressed and + // unset when it is released. To ensure consistent behaviour between + // platforms (and because it seems to make slightly more sense, although + // arguably both behaviours are reasonable) we follow MSW here. + // + // Final notice: we set the flags to the desired value instead of just + // inverting them because they are not set correctly (i.e. in the same way + // as for the real events generated by the user) for wxUIActionSimulator- + // produced events and it seems better to keep that class code the same + // among all platforms and fix the discrepancy here instead of adding + // wxGTK-specific code to wxUIActionSimulator. + const bool isPress = gdk_event->type == GDK_KEY_PRESS; + switch ( gdk_event->keyval ) { - // Set Unicode key code to the ASCII equivalent for compatibility. E.g. - // let RETURN generate the key event with both key and Unicode key - // codes of 13. - event.m_uniChar = event.m_keyCode; + case GDK_Shift_L: + case GDK_Shift_R: + event.m_shiftDown = isPress; + break; + + case GDK_Control_L: + case GDK_Control_R: + event.m_controlDown = isPress; + break; + + case GDK_Alt_L: + case GDK_Alt_R: + event.m_altDown = isPress; + break; + + case GDK_Meta_L: + case GDK_Meta_R: + case GDK_Super_L: + case GDK_Super_R: + event.m_metaDown = isPress; + break; } -#endif // wxUSE_UNICODE - wxGetMousePosition( &x, &y ); - win->ScreenToClient( &x, &y ); - event.m_x = x; - event.m_y = y; + + event.m_rawCode = (wxUint32) gdk_event->keyval; + event.m_rawFlags = gdk_event->hardware_keycode; + + wxGetMousePosition(&event.m_x, &event.m_y); + win->ScreenToClient(&event.m_x, &event.m_y); event.SetEventObject( win ); } @@ -800,6 +837,17 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, event.m_keyCode = key_code; +#if wxUSE_UNICODE + event.m_uniChar = gdk_keyval_to_unicode(key_code ? key_code : keysym); + if ( !event.m_uniChar && event.m_keyCode <= WXK_DELETE ) + { + // Set Unicode key code to the ASCII equivalent for compatibility. E.g. + // let RETURN generate the key event with both key and Unicode key + // codes of 13. + event.m_uniChar = event.m_keyCode; + } +#endif // wxUSE_UNICODE + // now fill all the other fields wxFillOtherKeyEventFields(event, win, gdk_event); @@ -833,17 +881,21 @@ bool SendCharHookAndCharEvents(const wxKeyEvent& event, wxWindow *win) { // wxEVT_CHAR_HOOK must be sent to the top level parent window to allow it - // to handle key events in all of its children. - wxWindow * const parent = wxGetTopLevelParent(win); - if ( parent ) - { - // We need to make a copy of the event object because it is - // modified while it's handled, notably its WasProcessed() flag - // is set after it had been processed once. - wxKeyEvent eventCharHook(event); - eventCharHook.SetEventType(wxEVT_CHAR_HOOK); - if ( parent->HandleWindowEvent(eventCharHook) ) - return true; + // to handle key events in all of its children unless the mouse is captured + // in which case we consider that the keyboard should be "captured" too. + if ( !g_captureWindow ) + { + wxWindow * const parent = wxGetTopLevelParent(win); + if ( parent ) + { + // We need to make a copy of the event object because it is + // modified while it's handled, notably its WasProcessed() flag + // is set after it had been processed once. + wxKeyEvent eventCharHook(event); + eventCharHook.SetEventType(wxEVT_CHAR_HOOK); + if ( parent->HandleWindowEvent(eventCharHook) ) + return true; + } } // As above, make a copy of the event first. @@ -881,8 +933,10 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), return_after_IM = true; } - if ((!ret) && (win->m_imData != NULL)) + if (!ret && win->m_imData) { + win->m_imData->lastKeyEvent = gdk_event; + // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API // docs, if IM filter returns true, no further processing should be done. // we should send the key_down event anyway. @@ -1083,6 +1137,10 @@ template void InitMouseEvent(wxWindowGTK *win, event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK) != 0; event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK) != 0; event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK) != 0; + + // In gdk/win32 VK_XBUTTON1 is translated to GDK_BUTTON4_MASK + // and VK_XBUTTON2 to GDK_BUTTON5_MASK. In x11/gdk buttons 4/5 + // are wheel rotation and buttons 8/9 don't change the state. event.m_aux1Down = (gdk_event->state & GDK_BUTTON4_MASK) != 0; event.m_aux2Down = (gdk_event->state & GDK_BUTTON5_MASK) != 0; @@ -1093,7 +1151,9 @@ template void InitMouseEvent(wxWindowGTK *win, if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft)) { // origin in the upper right corner - int window_width = win->m_wxwindow->allocation.width; + GtkAllocation a; + gtk_widget_get_allocation(win->m_wxwindow, &a); + int window_width = a.width; event.m_x = window_width - event.m_x; } @@ -1132,6 +1192,20 @@ static void AdjustEventButtonState(wxMouseEvent& event) event.m_rightDown = !event.m_rightDown; return; } + + if ((event.GetEventType() == wxEVT_AUX1_DOWN) || + (event.GetEventType() == wxEVT_AUX1_DCLICK)) + { + event.m_aux1Down = true; + return; + } + + if ((event.GetEventType() == wxEVT_AUX2_DOWN) || + (event.GetEventType() == wxEVT_AUX2_DCLICK)) + { + event.m_aux2Down = true; + return; + } } // find the window to send the mouse event too @@ -1361,6 +1435,42 @@ gtk_window_button_press_callback( GtkWidget *widget, } } + else if (gdk_event->button == 8) + { + switch (gdk_event->type) + { + case GDK_3BUTTON_PRESS: + case GDK_BUTTON_PRESS: + event_type = wxEVT_AUX1_DOWN; + break; + + case GDK_2BUTTON_PRESS: + event_type = wxEVT_AUX1_DCLICK; + break; + + default: + ; + } + } + + else if (gdk_event->button == 9) + { + switch (gdk_event->type) + { + case GDK_3BUTTON_PRESS: + case GDK_BUTTON_PRESS: + event_type = wxEVT_AUX2_DOWN; + break; + + case GDK_2BUTTON_PRESS: + event_type = wxEVT_AUX2_DCLICK; + break; + + default: + ; + } + } + if ( event_type == wxEVT_NULL ) { // unknown mouse button or click type @@ -1444,6 +1554,14 @@ gtk_window_button_release_callback( GtkWidget *WXUNUSED(widget), event_type = wxEVT_RIGHT_UP; break; + case 8: + event_type = wxEVT_AUX1_UP; + break; + + case 9: + event_type = wxEVT_AUX2_UP; + break; + default: // unknown button, don't process return FALSE; @@ -1555,22 +1673,16 @@ window_scroll_event_hscrollbar(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* return false; } - wxMouseEvent event(wxEVT_MOUSEWHEEL); - InitMouseEvent(win, event, gdk_event); - GtkRange *range = win->m_scrollBar[wxWindow::ScrollDir_Horz]; - if (!range) return FALSE; - if (range && GTK_WIDGET_VISIBLE (range)) + if (range && gtk_widget_get_visible(GTK_WIDGET(range))) { - GtkAdjustment *adj = range->adjustment; - gdouble delta = adj->step_increment * 3; + GtkAdjustment* adj = gtk_range_get_adjustment(range); + double delta = gtk_adjustment_get_step_increment(adj) * 3; if (gdk_event->direction == GDK_SCROLL_LEFT) delta = -delta; - gdouble new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size); - - gtk_adjustment_set_value (adj, new_value); + gtk_range_set_value(range, gtk_adjustment_get_value(adj) + delta); return TRUE; } @@ -1602,18 +1714,15 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) return TRUE; GtkRange *range = win->m_scrollBar[wxWindow::ScrollDir_Vert]; - if (!range) return FALSE; - if (range && GTK_WIDGET_VISIBLE (range)) + if (range && gtk_widget_get_visible(GTK_WIDGET(range))) { - GtkAdjustment *adj = range->adjustment; - gdouble delta = adj->step_increment * 3; + GtkAdjustment* adj = gtk_range_get_adjustment(range); + double delta = gtk_adjustment_get_step_increment(adj) * 3; if (gdk_event->direction == GDK_SCROLL_UP) - delta = -delta; - - gdouble new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size); + delta = -delta; - gtk_adjustment_set_value (adj, new_value); + gtk_range_set_value(range, gtk_adjustment_get_value(adj) + delta); return TRUE; } @@ -1696,7 +1805,7 @@ gtk_window_enter_callback( GtkWidget *widget, int y = 0; GdkModifierType state = (GdkModifierType)0; - gdk_window_get_pointer( widget->window, &x, &y, &state ); + gdk_window_get_pointer(gtk_widget_get_window(widget), &x, &y, &state); wxMouseEvent event( wxEVT_ENTER_WINDOW ); InitMouseEvent(win, event, gdk_event); @@ -1736,7 +1845,7 @@ gtk_window_leave_callback( GtkWidget *widget, int y = 0; GdkModifierType state = (GdkModifierType)0; - gdk_window_get_pointer( widget->window, &x, &y, &state ); + gdk_window_get_pointer(gtk_widget_get_window(widget), &x, &y, &state); InitMouseEvent(win, event, gdk_event); @@ -1833,7 +1942,7 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win) if (win->m_imData) { gtk_im_context_set_client_window( win->m_imData->context, - win->m_wxwindow ? win->GTKGetDrawingWindow() : widget->window); + win->m_wxwindow ? win->GTKGetDrawingWindow() : gtk_widget_get_window(widget)); } // We cannot set colours and fonts before the widget @@ -1877,8 +1986,10 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxWindow* win) win->m_oldClientHeight = h; // this callback can be connected to m_wxwindow, // so always get size from m_widget->allocation - win->m_width = win->m_widget->allocation.width; - win->m_height = win->m_widget->allocation.height; + GtkAllocation a; + gtk_widget_get_allocation(win->m_widget, &a); + win->m_width = a.width; + win->m_height = a.height; if (!win->m_nativeSizeEvent) { wxSizeEvent event(win->GetSize(), win->GetId()); @@ -1981,6 +2092,7 @@ wxMouseState wxGetMouseState() ms.SetLeftDown((mask & GDK_BUTTON1_MASK) != 0); ms.SetMiddleDown((mask & GDK_BUTTON2_MASK) != 0); ms.SetRightDown((mask & GDK_BUTTON3_MASK) != 0); + // see the comment in InitMouseEvent() ms.SetAux1Down((mask & GDK_BUTTON4_MASK) != 0); ms.SetAux2Down((mask & GDK_BUTTON5_MASK) != 0); @@ -2000,9 +2112,7 @@ wxMouseState wxGetMouseState() // method #ifdef __WXUNIVERSAL__ IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK, wxWindowBase) -#else // __WXGTK__ - IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) -#endif // __WXUNIVERSAL__/__WXGTK__ +#endif // __WXUNIVERSAL__ void wxWindowGTK::Init() { @@ -2127,17 +2237,14 @@ bool wxWindowGTK::Create( wxWindow *parent, 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); + m_scrollBar[ScrollDir_Horz] = GTK_RANGE(gtk_scrolled_window_get_hscrollbar(scrolledWindow)); + m_scrollBar[ScrollDir_Vert] = GTK_RANGE(gtk_scrolled_window_get_vscrollbar(scrolledWindow)); if (GetLayoutDirection() == wxLayout_RightToLeft) gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE ); @@ -2408,8 +2515,6 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget ) bool wxWindowGTK::Destroy() { - wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") ); - m_hasVMT = false; return wxWindowBase::Destroy(); @@ -2484,7 +2589,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags int bottom_border = 0; /* the default button has a border around it */ - if (GTK_WIDGET_CAN_DEFAULT(m_widget)) + if (gtk_widget_get_can_default(m_widget)) { GtkBorder *default_border = NULL; gtk_widget_style_get( m_widget, "default_border", &default_border, NULL ); @@ -2528,7 +2633,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags bool wxWindowGTK::GTKShowFromOnIdle() { - if (IsShown() && m_showOnIdle && !GTK_WIDGET_VISIBLE (m_widget)) + if (IsShown() && m_showOnIdle && !gtk_widget_get_visible (m_widget)) { GtkAllocation alloc; alloc.x = m_x; @@ -2569,8 +2674,7 @@ void wxWindowGTK::OnInternalIdle() m_needsStyleChange = false; } - if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) - UpdateWindowUI(wxUPDATE_UI_FROMIDLE); + wxWindowBase::OnInternalIdle(); } void wxWindowGTK::DoGetSize( int *width, int *height ) const @@ -2628,7 +2732,7 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const case GTK_POLICY_AUTOMATIC: // may be shown or not, check GtkAdjustment *adj = gtk_range_get_adjustment(range); - if ( adj->upper <= adj->page_size ) + if (gtk_adjustment_get_upper(adj) <= gtk_adjustment_get_page_size(adj)) continue; } @@ -2686,9 +2790,9 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const { GdkWindow *source = NULL; if (m_wxwindow) - source = m_wxwindow->window; + source = gtk_widget_get_window(m_wxwindow); else - source = m_widget->window; + source = gtk_widget_get_window(m_widget); if (source) { @@ -2712,13 +2816,13 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (!m_widget->window) return; + if (gtk_widget_get_window(m_widget) == NULL) return; GdkWindow *source = NULL; if (m_wxwindow) - source = m_wxwindow->window; + source = gtk_widget_get_window(m_wxwindow); else - source = m_widget->window; + source = gtk_widget_get_window(m_widget); int org_x = 0; int org_y = 0; @@ -2726,10 +2830,12 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const if (!m_wxwindow) { - if (GTK_WIDGET_NO_WINDOW (m_widget)) + if (!gtk_widget_get_has_window(m_widget)) { - org_x += m_widget->allocation.x; - org_y += m_widget->allocation.y; + GtkAllocation a; + gtk_widget_get_allocation(m_widget, &a); + org_x += a.x; + org_y += a.y; } } @@ -2749,13 +2855,13 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (!m_widget->window) return; + if (!gtk_widget_get_realized(m_widget)) return; GdkWindow *source = NULL; if (m_wxwindow) - source = m_wxwindow->window; + source = gtk_widget_get_window(m_wxwindow); else - source = m_widget->window; + source = gtk_widget_get_window(m_widget); int org_x = 0; int org_y = 0; @@ -2763,10 +2869,12 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const if (!m_wxwindow) { - if (GTK_WIDGET_NO_WINDOW (m_widget)) + if (!gtk_widget_get_has_window(m_widget)) { - org_x += m_widget->allocation.x; - org_y += m_widget->allocation.y; + GtkAllocation a; + gtk_widget_get_allocation(m_widget, &a); + org_x += a.x; + org_y += a.y; } } @@ -2833,7 +2941,7 @@ int wxWindowGTK::GetCharHeight() const wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") ); wxFont font = GetFont(); - wxCHECK_MSG( font.Ok(), 12, wxT("invalid font") ); + wxCHECK_MSG( font.IsOk(), 12, wxT("invalid font") ); PangoContext* context = gtk_widget_get_pango_context(m_widget); @@ -2859,7 +2967,7 @@ int wxWindowGTK::GetCharWidth() const wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") ); wxFont font = GetFont(); - wxCHECK_MSG( font.Ok(), 8, wxT("invalid font") ); + wxCHECK_MSG( font.IsOk(), 8, wxT("invalid font") ); PangoContext* context = gtk_widget_get_pango_context(m_widget); @@ -2889,7 +2997,7 @@ void wxWindowGTK::DoGetTextExtent( const wxString& string, { wxFont fontToUse = theFont ? *theFont : GetFont(); - wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); + wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") ); if (string.empty()) { @@ -3108,7 +3216,7 @@ void wxWindowGTK::SetFocus() // within its toplevel", i.e. returns true for one widget per TLW, not // globally) returns true immediately after grabbing focus, // GTK_WIDGET_HAS_FOCUS (which returns true only for the one widget that - // has focus at the moment) takes affect only after the window is shown + // has focus at the moment) takes effect only after the window is shown // (if it was hidden at the moment of the call) or at the next event loop // iteration. // @@ -3120,7 +3228,7 @@ void wxWindowGTK::SetFocus() GtkWidget *widget = m_wxwindow ? m_wxwindow : m_focusWidget; if ( GTK_IS_CONTAINER(widget) && - !GTK_WIDGET_CAN_FOCUS(widget) ) + !gtk_widget_get_can_focus(widget) ) { wxLogTrace(TRACE_FOCUS, wxT("Setting focus to a child of %s(%p, %s)"), @@ -3138,17 +3246,11 @@ void wxWindowGTK::SetFocus() void wxWindowGTK::SetCanFocus(bool canFocus) { - if ( canFocus ) - GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS); - else - GTK_WIDGET_UNSET_FLAGS(m_widget, GTK_CAN_FOCUS); + gtk_widget_set_can_focus(m_widget, canFocus); 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); + gtk_widget_set_can_focus(m_wxwindow, canFocus); } } @@ -3156,8 +3258,7 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) { wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") ); - wxWindowGTK *oldParent = m_parent, - *newParent = (wxWindowGTK *)newParentBase; + wxWindowGTK * const newParent = (wxWindowGTK *)newParentBase; wxASSERT( GTK_IS_WIDGET(m_widget) ); @@ -3166,14 +3267,17 @@ bool wxWindowGTK::Reparent( wxWindowBase *newParentBase ) wxASSERT( GTK_IS_WIDGET(m_widget) ); - if (oldParent) - gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget ); + // Notice that old m_parent pointer might be non-NULL here but the widget + // still not have any parent at GTK level if it's a notebook page that had + // been removed from the notebook so test this at GTK level and not wx one. + if ( GtkWidget *parentGTK = gtk_widget_get_parent(m_widget) ) + gtk_container_remove(GTK_CONTAINER(parentGTK), m_widget); wxASSERT( GTK_IS_WIDGET(m_widget) ); if (newParent) { - if (GTK_WIDGET_VISIBLE (newParent->m_widget)) + if (gtk_widget_get_visible (newParent->m_widget)) { m_showOnIdle = true; gtk_widget_hide( m_widget ); @@ -3331,18 +3435,20 @@ void wxWindowGTK::RealizeTabOrder() { wxWindowGTK *win = *i; + bool focusableFromKeyboard = win->AcceptsFocusFromKeyboard(); + if ( mnemonicWindow ) { - if ( win->AcceptsFocusFromKeyboard() ) + if ( focusableFromKeyboard ) { // wxComboBox et al. needs to focus on on a different // widget than m_widget, so if the main widget isn't // focusable try the connect widget GtkWidget* w = win->m_widget; - if ( !GTK_WIDGET_CAN_FOCUS(w) ) + if ( !gtk_widget_get_can_focus(w) ) { w = win->GetConnectWidget(); - if ( !GTK_WIDGET_CAN_FOCUS(w) ) + if ( !gtk_widget_get_can_focus(w) ) w = NULL; } @@ -3358,7 +3464,8 @@ void wxWindowGTK::RealizeTabOrder() mnemonicWindow = win; } - chain = g_list_prepend(chain, win->m_widget); + if ( focusableFromKeyboard ) + chain = g_list_prepend(chain, win->m_widget); } chain = g_list_reverse(chain); @@ -3377,13 +3484,13 @@ void wxWindowGTK::Raise() { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (m_wxwindow && m_wxwindow->window) + if (m_wxwindow && gtk_widget_get_window(m_wxwindow)) { - gdk_window_raise( m_wxwindow->window ); + gdk_window_raise(gtk_widget_get_window(m_wxwindow)); } - else if (m_widget->window) + else if (gtk_widget_get_window(m_widget)) { - gdk_window_raise( m_widget->window ); + gdk_window_raise(gtk_widget_get_window(m_widget)); } } @@ -3391,19 +3498,19 @@ void wxWindowGTK::Lower() { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (m_wxwindow && m_wxwindow->window) + if (m_wxwindow && gtk_widget_get_window(m_wxwindow)) { - gdk_window_lower( m_wxwindow->window ); + gdk_window_lower(gtk_widget_get_window(m_wxwindow)); } - else if (m_widget->window) + else if (gtk_widget_get_window(m_widget)) { - gdk_window_lower( m_widget->window ); + gdk_window_lower(gtk_widget_get_window(m_widget)); } } bool wxWindowGTK::SetCursor( const wxCursor &cursor ) { - if ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) ) + if ( !wxWindowBase::SetCursor(cursor.IsOk() ? cursor : *wxSTANDARD_CURSOR) ) return false; GTKUpdateCursor(); @@ -3415,8 +3522,8 @@ void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=tr { if (update_self) { - wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor()); - if ( cursor.Ok() ) + wxCursor cursor(g_globalCursor.IsOk() ? g_globalCursor : GetCursor()); + if ( cursor.IsOk() ) { wxArrayGdkWindows windowsThis; GdkWindow* window = GTKGetWindow(windowsThis); @@ -3456,9 +3563,9 @@ void wxWindowGTK::WarpPointer( int x, int y ) GdkWindow *window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = gtk_widget_get_window(m_wxwindow); else - window = GetConnectWidget()->window; + window = gtk_widget_get_window(GetConnectWidget()); if (window) gdk_window_warp_pointer( window, x, y ); @@ -3484,14 +3591,14 @@ bool wxWindowGTK::DoScrollByUnits(ScrollDir dir, ScrollUnit unit, int units) GtkRange* range = m_scrollBar[dir]; if ( range && units ) { - GtkAdjustment* adj = range->adjustment; - gdouble inc = unit == ScrollUnit_Line ? adj->step_increment - : adj->page_increment; + GtkAdjustment* adj = gtk_range_get_adjustment(range); + double inc = unit == ScrollUnit_Line ? gtk_adjustment_get_step_increment(adj) + : gtk_adjustment_get_page_increment(adj); - const int posOld = int(adj->value + 0.5); + const int posOld = wxRound(gtk_adjustment_get_value(adj)); gtk_range_set_value(range, posOld + units*inc); - changed = int(adj->value + 0.5) != posOld; + changed = wxRound(gtk_adjustment_get_value(adj)) != posOld; } return changed; @@ -3528,8 +3635,8 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), { // Just return if the widget or one of its ancestors isn't mapped GtkWidget *w; - for (w = m_wxwindow; w != NULL; w = w->parent) - if (!GTK_WIDGET_MAPPED (w)) + for (w = m_wxwindow; w != NULL; w = gtk_widget_get_parent(w)) + if (!gtk_widget_get_mapped (w)) return; GdkWindow* window = GTKGetDrawingWindow(); @@ -3552,7 +3659,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), void wxWindowGTK::Update() { - if (m_widget && GTK_WIDGET_MAPPED(m_widget)) + if (m_widget && gtk_widget_get_mapped(m_widget)) { GdkDisplay* display = gtk_widget_get_display(m_widget); // Flush everything out to the server, and wait for it to finish. @@ -3561,7 +3668,7 @@ void wxWindowGTK::Update() GdkWindow* window = GTKGetDrawingWindow(); if (window == NULL) - window = m_widget->window; + window = gtk_widget_get_window(m_widget); gdk_window_process_updates(window, true); // Flush again, but no need to wait for it to finish @@ -3601,7 +3708,7 @@ void wxWindowGTK::GtkSendPaintEvents() m_updateRegion.Clear(); gint width; - gdk_drawable_get_size(m_wxwindow->window, &width, NULL); + gdk_drawable_get_size(gtk_widget_get_window(m_wxwindow), &width, NULL); wxRegionIterator upd( m_nativeUpdateRegion ); while (upd) @@ -3655,7 +3762,7 @@ void wxWindowGTK::GtkSendPaintEvents() if (!parent) parent = (wxWindow*)this; - if (GTK_WIDGET_MAPPED(parent->m_widget)) + if (gtk_widget_get_mapped(parent->m_widget)) { wxRegionIterator upd( m_nativeUpdateRegion ); while (upd) @@ -3666,9 +3773,9 @@ void wxWindowGTK::GtkSendPaintEvents() rect.width = upd.GetWidth(); rect.height = upd.GetHeight(); - gtk_paint_flat_box( parent->m_widget->style, + gtk_paint_flat_box(gtk_widget_get_style(parent->m_widget), GTKGetDrawingWindow(), - (GtkStateType)GTK_WIDGET_STATE(m_wxwindow), + gtk_widget_get_state(m_wxwindow), GTK_SHADOW_NONE, &rect, parent->m_widget, @@ -3713,7 +3820,7 @@ void wxWindowGTK::SetDoubleBuffered( bool on ) bool wxWindowGTK::IsDoubleBuffered() const { - return GTK_WIDGET_DOUBLE_BUFFERED( m_wxwindow ); + return gtk_widget_get_double_buffered( m_wxwindow ); } void wxWindowGTK::ClearBackground() @@ -3724,29 +3831,20 @@ void wxWindowGTK::ClearBackground() #if wxUSE_TOOLTIPS void wxWindowGTK::DoSetToolTip( wxToolTip *tip ) { - wxWindowBase::DoSetToolTip(tip); - - if (m_tooltip) + if (m_tooltip != tip) { - m_tooltip->GTKApply( (wxWindow *)this ); - } - else - { - GtkWidget *w = GetConnectWidget(); - wxToolTip::GTKApply(w, NULL); -#if GTK_CHECK_VERSION(2, 12, 0) - // Just applying NULL doesn't work on 2.12.0, so also use - // gtk_widget_set_has_tooltip. It is part of the new GtkTooltip API - // but seems also to work with the old GtkTooltips. - if (gtk_check_version(2, 12, 0) == NULL) - gtk_widget_set_has_tooltip(w, FALSE); -#endif + wxWindowBase::DoSetToolTip(tip); + + if (m_tooltip) + m_tooltip->GTKSetWindow(static_cast(this)); + else + GTKApplyToolTip(NULL); } } -void wxWindowGTK::GTKApplyToolTip( GtkTooltips *tips, const gchar *tip ) +void wxWindowGTK::GTKApplyToolTip(const char* tip) { - gtk_tooltips_set_tip(tips, GetConnectWidget(), tip, NULL); + wxToolTip::GTKApply(GetConnectWidget(), tip); } #endif // wxUSE_TOOLTIPS @@ -3757,7 +3855,7 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour ) if (!wxWindowBase::SetBackgroundColour(colour)) return false; - if (colour.Ok()) + if (colour.IsOk()) { // We need the pixel value e.g. for background clearing. m_backgroundColour.CalcPixel(gtk_widget_get_colormap(m_widget)); @@ -3779,7 +3877,7 @@ bool wxWindowGTK::SetForegroundColour( const wxColour &colour ) return false; } - if (colour.Ok()) + if (colour.IsOk()) { // We need the pixel value e.g. for background clearing. m_foregroundColour.CalcPixel(gtk_widget_get_colormap(m_widget)); @@ -3801,15 +3899,15 @@ GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) { // do we need to apply any changes at all? if ( !forceStyle && - !m_font.Ok() && - !m_foregroundColour.Ok() && !m_backgroundColour.Ok() ) + !m_font.IsOk() && + !m_foregroundColour.IsOk() && !m_backgroundColour.IsOk() ) { return NULL; } GtkRcStyle *style = gtk_rc_style_new(); - if ( m_font.Ok() ) + if ( m_font.IsOk() ) { style->font_desc = pango_font_description_copy( m_font.GetNativeFontInfo()->description ); @@ -3820,7 +3918,7 @@ GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) flagsActive = 0, flagsInsensitive = 0; - if ( m_foregroundColour.Ok() ) + if ( m_foregroundColour.IsOk() ) { const GdkColor *fg = m_foregroundColour.GetColor(); @@ -3837,7 +3935,7 @@ GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) flagsActive |= GTK_RC_FG | GTK_RC_TEXT; } - if ( m_backgroundColour.Ok() ) + if ( m_backgroundColour.IsOk() ) { const GdkColor *bg = m_backgroundColour.GetColor(); @@ -3872,7 +3970,7 @@ void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle) if ( style ) { DoApplyWidgetStyle(style); - gtk_rc_style_unref(style); + g_object_unref(style); } // Style change may affect GTK+'s size calculation: @@ -3921,7 +4019,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) else { GtkWidget * const w = GetConnectWidget(); - window = w ? w->window : NULL; + window = w ? gtk_widget_get_window(w) : NULL; } if (window) @@ -4061,7 +4159,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const { - return m_wxwindow ? GTKGetDrawingWindow() : m_widget->window; + return m_wxwindow ? GTKGetDrawingWindow() : gtk_widget_get_window(m_widget); } bool wxWindowGTK::SetFont( const wxFont &font ) @@ -4086,12 +4184,12 @@ void wxWindowGTK::DoCaptureMouse() if (m_wxwindow) window = GTKGetDrawingWindow(); else - window = GetConnectWidget()->window; + window = gtk_widget_get_window(GetConnectWidget()); wxCHECK_RET( window, wxT("CaptureMouse() failed") ); const wxCursor* cursor = &m_cursor; - if (!cursor->Ok()) + if (!cursor->IsOk()) cursor = wxSTANDARD_CURSOR; gdk_pointer_grab( window, FALSE, @@ -4119,7 +4217,7 @@ void wxWindowGTK::DoReleaseMouse() if (m_wxwindow) window = GTKGetDrawingWindow(); else - window = GetConnectWidget()->window; + window = gtk_widget_get_window(GetConnectWidget()); if (!window) return; @@ -4163,17 +4261,14 @@ void wxWindowGTK::SetScrollbar(int orient, thumbVisible = 1; } - GtkAdjustment * const adj = sb->adjustment; - adj->step_increment = 1; - adj->page_increment = - adj->page_size = thumbVisible; - adj->value = pos; - g_signal_handlers_block_by_func( sb, (void*)gtk_scrollbar_value_changed, this); + gtk_range_set_increments(sb, 1, thumbVisible); + gtk_adjustment_set_page_size(gtk_range_get_adjustment(sb), thumbVisible); gtk_range_set_range(sb, 0, range); - m_scrollPos[dir] = sb->adjustment->value; + gtk_range_set_value(sb, pos); + m_scrollPos[dir] = gtk_range_get_value(sb); g_signal_handlers_unblock_by_func( sb, (void*)gtk_scrollbar_value_changed, this); @@ -4193,7 +4288,7 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) sb, (void*)gtk_scrollbar_value_changed, this); gtk_range_set_value(sb, pos); - m_scrollPos[dir] = sb->adjustment->value; + m_scrollPos[dir] = gtk_range_get_value(sb); g_signal_handlers_unblock_by_func( sb, (void*)gtk_scrollbar_value_changed, this); @@ -4205,7 +4300,7 @@ int wxWindowGTK::GetScrollThumb(int orient) const GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); - return wxRound(sb->adjustment->page_size); + return wxRound(gtk_adjustment_get_page_size(gtk_range_get_adjustment(sb))); } int wxWindowGTK::GetScrollPos( int orient ) const @@ -4213,7 +4308,7 @@ int wxWindowGTK::GetScrollPos( int orient ) const GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); - return wxRound(sb->adjustment->value); + return wxRound(gtk_range_get_value(sb)); } int wxWindowGTK::GetScrollRange( int orient ) const @@ -4221,7 +4316,7 @@ int wxWindowGTK::GetScrollRange( int orient ) const GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; wxCHECK_MSG( sb, 0, wxT("this window is not scrollable") ); - return wxRound(sb->adjustment->upper); + return wxRound(gtk_adjustment_get_upper(gtk_range_get_adjustment(sb))); } // Determine if increment is the same as +/-x, allowing for some small @@ -4238,16 +4333,15 @@ wxEventType wxWindowGTK::GTKGetScrollEventType(GtkRange* range) wxASSERT(range == m_scrollBar[0] || range == m_scrollBar[1]); const int barIndex = range == m_scrollBar[1]; - GtkAdjustment* adj = range->adjustment; - const int value = wxRound(adj->value); + const double value = gtk_range_get_value(range); // save previous position const double oldPos = m_scrollPos[barIndex]; // update current position - m_scrollPos[barIndex] = adj->value; + m_scrollPos[barIndex] = value; // If event should be ignored, or integral position has not changed - if (!m_hasVMT || g_blockEventsOnDrag || value == wxRound(oldPos)) + if (!m_hasVMT || g_blockEventsOnDrag || wxRound(value) == wxRound(oldPos)) { return wxEVT_NULL; } @@ -4256,14 +4350,15 @@ wxEventType wxWindowGTK::GTKGetScrollEventType(GtkRange* range) if (!m_isScrolling) { // Difference from last change event - const double diff = adj->value - oldPos; + const double diff = value - oldPos; const bool isDown = diff > 0; - if (IsScrollIncrement(adj->step_increment, diff)) + GtkAdjustment* adj = gtk_range_get_adjustment(range); + if (IsScrollIncrement(gtk_adjustment_get_step_increment(adj), diff)) { eventType = isDown ? wxEVT_SCROLL_LINEDOWN : wxEVT_SCROLL_LINEUP; } - else if (IsScrollIncrement(adj->page_increment, diff)) + else if (IsScrollIncrement(gtk_adjustment_get_page_increment(adj), diff)) { eventType = isDown ? wxEVT_SCROLL_PAGEDOWN : wxEVT_SCROLL_PAGEUP; } @@ -4389,7 +4484,7 @@ GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const { GdkWindow* window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = gtk_widget_get_window(m_wxwindow); return window; } @@ -4404,8 +4499,8 @@ extern "C" // is realized (and so can be frozen): static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) { - wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) ); - wxASSERT( GTK_WIDGET_REALIZED(w) ); + wxASSERT( w && gtk_widget_get_has_window(w) ); + wxASSERT( gtk_widget_get_realized(w) ); g_signal_handlers_disconnect_by_func ( @@ -4414,9 +4509,11 @@ static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) win ); - GdkWindow* window = w->window; + GdkWindow* window; if (w == win->m_wxwindow) window = win->GTKGetDrawingWindow(); + else + window = gtk_widget_get_window(w); gdk_window_freeze_updates(window); } @@ -4424,10 +4521,11 @@ static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) { - if ( !w || GTK_WIDGET_NO_WINDOW(w) ) + if ( !w || !gtk_widget_get_has_window(w) ) return; // window-less widget, cannot be frozen - if ( !GTK_WIDGET_REALIZED(w) ) + GdkWindow* window = gtk_widget_get_window(w); + if (window == NULL) { // we can't thaw unrealized widgets because they don't have GdkWindow, // so set it up to be done immediately after realization: @@ -4441,7 +4539,6 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) return; } - GdkWindow* window = w->window; if (w == m_wxwindow) window = GTKGetDrawingWindow(); gdk_window_freeze_updates(window); @@ -4449,10 +4546,11 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) void wxWindowGTK::GTKThawWidget(GtkWidget *w) { - if ( !w || GTK_WIDGET_NO_WINDOW(w) ) + if ( !w || !gtk_widget_get_has_window(w) ) return; // window-less widget, cannot be frozen - if ( !GTK_WIDGET_REALIZED(w) ) + GdkWindow* window = gtk_widget_get_window(w); + if (window == NULL) { // the widget wasn't realized yet, no need to thaw g_signal_handlers_disconnect_by_func @@ -4464,7 +4562,6 @@ void wxWindowGTK::GTKThawWidget(GtkWidget *w) return; } - GdkWindow* window = w->window; if (w == m_wxwindow) window = GTKGetDrawingWindow(); gdk_window_thaw_updates(window);