X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/00ce89e74a2c42e3057f4c34429ebbf4de2efe96..883ea3bf80503de1f2aa797ce91acda654d88d74:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a0d88ec670..eb36d67c61 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -25,7 +25,6 @@ #include "wx/settings.h" #include "wx/msgdlg.h" #include "wx/textctrl.h" - #include "wx/radiobut.h" #include "wx/toolbar.h" #include "wx/combobox.h" #include "wx/layout.h" @@ -991,6 +990,11 @@ gtk_window_key_press_callback( GtkWidget *widget, if (g_blockEventsOnDrag) return FALSE; + // GTK+ sends keypress events to the focus widget and then + // to all its parent and grandparent widget. We only want + // the key events from the focus widget. + if (!GTK_WIDGET_HAS_FOCUS(widget)) + return FALSE; wxKeyEvent event( wxEVT_KEY_DOWN ); bool ret = false; @@ -1008,18 +1012,7 @@ gtk_window_key_press_callback( GtkWidget *widget, return_after_IM = true; } - // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw): - // When we get a key_press event here, it could be originate - // from the current widget or its child widgets. However, only the widget - // with the INPUT FOCUS can generate the INITIAL key_press event. That is, - // if the CURRENT widget doesn't have the FOCUS at all, this event definitely - // originated from its child widgets and shouldn't be passed to IM context. - // In fact, what a GTK+ IM should do is filtering keyEvents and convert them - // into text input ONLY WHEN THE WIDGET HAS INPUT FOCUS. Besides, when current - // widgets has both IM context and input focus, the event should be filtered - // by gtk_im_context_filter_keypress(). - // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns. - if ((!ret) && (win->m_imData != NULL) && ( wxWindow::FindFocus() == win )) + if ((!ret) && (win->m_imData != NULL)) { // 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. @@ -1237,13 +1230,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); + 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; @@ -1438,11 +1433,6 @@ gtk_window_button_press_callback( GtkWidget *widget, g_lastButtonNumber = gdk_event->button; - if (win->m_wxwindow && (g_focusWindow != win) && win->IsFocusable()) - { - gtk_widget_grab_focus( win->m_wxwindow ); - } - // GDK sends surplus button down events // before a double click event. We // need to filter these out. @@ -1573,10 +1563,10 @@ gtk_window_button_press_callback( GtkWidget *widget, if ( ret ) return TRUE; - if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && - (g_focusWindow != win) && win->IsFocusable()) + if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && + (g_focusWindow != win) /* && win->IsFocusable() */) { - gtk_widget_grab_focus( win->m_wxwindow ); + win->SetFocus(); } if (event_type == wxEVT_RIGHT_DOWN) @@ -1745,15 +1735,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) @@ -1761,14 +1743,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); } @@ -1963,8 +1937,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; @@ -1972,17 +1944,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); } @@ -2040,9 +2002,10 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win) const int orient = wxWindow::OrientFromScrollDir( win->ScrollDirFromRange(range)); - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient); - event.SetEventObject(win); - win->GTKProcessEvent(event); + wxScrollWinEvent evt(wxEVT_SCROLLWIN_THUMBRELEASE, + win->GetScrollPos(orient), orient); + evt.SetEventObject(win); + win->GTKProcessEvent(evt); } } @@ -2133,6 +2096,27 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), } } +//----------------------------------------------------------------------------- +// "grab_broken" +//----------------------------------------------------------------------------- + +#if GTK_CHECK_VERSION(2, 8, 0) +static gboolean +gtk_window_grab_broken( GtkWidget*, + GdkEventGrabBroken *event, + wxWindow *win ) +{ + // Mouse capture has been lost involuntarily, notify the application + if(!event->keyboard && wxWindow::GetCapture() == win) + { + wxMouseCaptureLostEvent evt( win->GetId() ); + evt.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( evt ); + } + return false; +} +#endif + } // extern "C" // ---------------------------------------------------------------------------- @@ -2198,6 +2182,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); @@ -2243,7 +2229,6 @@ void wxWindowGTK::Init() m_hasScrolling = false; m_isScrolling = false; m_mouseButtonDown = false; - m_blockScrollEvent = false; // initialize scrolling stuff for ( int dir = 0; dir < ScrollDir_Max; dir++ ) @@ -2545,6 +2530,26 @@ void wxWindowGTK::PostCreation() // Catch native resize events g_signal_connect (m_wxwindow, "size_allocate", G_CALLBACK (gtk_window_size_callback), this); +#if GTK_CHECK_VERSION(2, 8, 0) + 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 ) + { +#if GTK_CHECK_VERSION(2, 8, 0) + 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 @@ -2555,8 +2560,7 @@ void wxWindowGTK::PostCreation() g_signal_connect (gcombo->entry, "size_request", G_CALLBACK (wxgtk_combo_size_request_callback), this); - } - else + } else #endif // wxUSE_COMBOBOX #ifdef GTK_IS_FILE_CHOOSER_BUTTON if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) @@ -2565,9 +2569,9 @@ void wxWindowGTK::PostCreation() // 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 @@ -2836,7 +2840,7 @@ void wxWindowGTK::OnInternalIdle() } } - if (wxUpdateUIEvent::CanUpdate(this)) + if (wxUpdateUIEvent::CanUpdate(this) && IsShown()) UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } @@ -2894,7 +2898,7 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const int dx = 0; int dy = 0; - if (m_parent && m_parent->m_wxwindow) + if (!IsTopLevel() && m_parent && m_parent->m_wxwindow) { GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow); dx = gtk_pizza_get_xoffset( pizza ); @@ -3046,9 +3050,7 @@ int wxWindowGTK::GetCharHeight() const wxFont font = GetFont(); wxCHECK_MSG( font.Ok(), 12, wxT("invalid font") ); - PangoContext *context = NULL; - if (m_widget) - context = gtk_widget_get_pango_context( m_widget ); + PangoContext* context = gtk_widget_get_pango_context(m_widget); if (!context) return 0; @@ -3074,9 +3076,7 @@ int wxWindowGTK::GetCharWidth() const wxFont font = GetFont(); wxCHECK_MSG( font.Ok(), 8, wxT("invalid font") ); - PangoContext *context = NULL; - if (m_widget) - context = gtk_widget_get_pango_context( m_widget ); + PangoContext* context = gtk_widget_get_pango_context(m_widget); if (!context) return 0; @@ -3177,22 +3177,30 @@ void wxWindowGTK::SetFocus() if (m_wxwindow) { + // wxWindow::SetFocus() should really set the focus to + // this control, whatever the flags are + if (!GTK_WIDGET_CAN_FOCUS(m_wxwindow)) + GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS); + if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) { gtk_widget_grab_focus (m_wxwindow); } } - else if (m_widget) + else { + // wxWindow::SetFocus() should really set the focus to + // this control, whatever the flags are + if (!GTK_WIDGET_CAN_FOCUS(m_widget)) + GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS); + if (GTK_IS_CONTAINER(m_widget)) { -#if wxUSE_RADIOBTN - if (IsKindOf(CLASSINFO(wxRadioButton))) + if (GTK_IS_RADIO_BUTTON(m_widget)) { gtk_widget_grab_focus (m_widget); return; } -#endif // wxUSE_RADIOBTN gtk_widget_child_focus( m_widget, GTK_DIR_TAB_FORWARD ); } @@ -3389,7 +3397,7 @@ bool wxWindowGTK::DoNavigateIn(int flags) } else // navigate inside the container { - wxWindow *parent = wxGetTopLevelParent(this); + wxWindow *parent = wxGetTopLevelParent((wxWindow *)this); wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") ); GtkDirectionType dir; @@ -4094,6 +4102,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() { @@ -4105,25 +4121,14 @@ bool wxWindowGTK::IsRetained() const return false; } -void wxWindowGTK::BlockScrollEvent() -{ - wxASSERT(!m_blockScrollEvent); - m_blockScrollEvent = true; -} - -void wxWindowGTK::UnblockScrollEvent() -{ - wxASSERT(m_blockScrollEvent); - m_blockScrollEvent = false; -} - void wxWindowGTK::SetScrollbar(int orient, int pos, int thumbVisible, int range, bool WXUNUSED(update)) { - GtkRange * const sb = m_scrollBar[ScrollDirFromOrient(orient)]; + const int dir = ScrollDirFromOrient(orient); + GtkRange* const sb = m_scrollBar[dir]; wxCHECK_RET( sb, _T("this window is not scrollable") ); if (range > 0) @@ -4137,17 +4142,20 @@ void wxWindowGTK::SetScrollbar(int orient, thumbVisible = 1; } - if (pos > range - thumbVisible) - pos = range - thumbVisible; - if (pos < 0) - pos = 0; GtkAdjustment * const adj = sb->adjustment; adj->step_increment = 1; adj->page_increment = adj->page_size = thumbVisible; - adj->upper = range; - SetScrollPos(orient, pos); - gtk_adjustment_changed(adj); + adj->value = pos; + + g_signal_handlers_block_by_func( + sb, (void*)gtk_scrollbar_value_changed, this); + + gtk_range_set_range(sb, 0, range); + m_scrollPos[dir] = sb->adjustment->value; + + g_signal_handlers_unblock_by_func( + sb, (void*)gtk_scrollbar_value_changed, this); } void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) @@ -4160,21 +4168,14 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) // will not move smoothly while tracking when using wxScrollHelper. if (GetScrollPos(orient) != pos) { - GtkAdjustment* adj = sb->adjustment; - const int max = int(adj->upper - adj->page_size); - if (pos > max) - pos = max; - if (pos < 0) - pos = 0; - m_scrollPos[dir] = adj->value = pos; + g_signal_handlers_block_by_func( + sb, (void*)gtk_scrollbar_value_changed, this); - g_signal_handlers_block_by_func(m_scrollBar[dir], - (gpointer)gtk_scrollbar_value_changed, this); + gtk_range_set_value(sb, pos); + m_scrollPos[dir] = sb->adjustment->value; - gtk_adjustment_value_changed(adj); - - g_signal_handlers_unblock_by_func(m_scrollBar[dir], - (gpointer)gtk_scrollbar_value_changed, this); + g_signal_handlers_unblock_by_func( + sb, (void*)gtk_scrollbar_value_changed, this); } } @@ -4264,7 +4265,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) @@ -4310,8 +4311,11 @@ void wxWindowGTK::GtkScrolledWindowSetBorder(GtkWidget* w, int wxstyle) gtkstyle = GTK_SHADOW_OUT; else if (wxstyle & wxBORDER_SUNKEN) gtkstyle = GTK_SHADOW_IN; +#if 0 + // Now obsolete else if (wxstyle & wxBORDER_DOUBLE) gtkstyle = GTK_SHADOW_ETCHED_IN; +#endif else //default gtkstyle = GTK_SHADOW_IN;