X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/830ed6d97d913f9d3cf53999a82d3507d5aebde4..ee3510132b8b4160f848bd4f502a6f5315f90dbc:/src/gtk1/scrolwin.cpp diff --git a/src/gtk1/scrolwin.cpp b/src/gtk1/scrolwin.cpp index 7e38b4c7b2..143c07f78d 100644 --- a/src/gtk1/scrolwin.cpp +++ b/src/gtk1/scrolwin.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: generic/scrolwin.cpp +// Name: gtk/scrolwin.cpp // Purpose: wxScrolledWindow implementation // Author: Julian Smart // Modified by: @@ -59,6 +59,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) //----------------------------------------------------------------------------- extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnScroll; //----------------------------------------------------------------------------- // idle system @@ -98,6 +99,66 @@ static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, wxScrol win->GtkHScroll( adjust->value ); } +//----------------------------------------------------------------------------- +// "button_press_event" from scrollbar +//----------------------------------------------------------------------------- + +static gint gtk_scrollbar_button_press_callback( GtkRange *widget, + GdkEventButton *gdk_event, + wxWindowGTK *win) +{ + if (g_isIdle) + wxapp_install_idle_handler(); + + g_blockEventsOnScroll = TRUE; + win->m_isScrolling = (gdk_event->window == widget->slider); + + return FALSE; +} + +//----------------------------------------------------------------------------- +// "button_release_event" from scrollbar +//----------------------------------------------------------------------------- + +static gint gtk_scrollbar_button_release_callback( GtkRange *widget, + GdkEventButton *WXUNUSED(gdk_event), + wxWindowGTK *win) +{ +// don't test here as we can release the mouse while being over +// a different window than the slider +// +// if (gdk_event->window != widget->slider) return FALSE; + + g_blockEventsOnScroll = FALSE; + + if (win->m_isScrolling) + { + wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE; + int value = -1; + int dir = -1; + + GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); + if (widget == GTK_RANGE(scrolledWindow->hscrollbar)) + { + value = (int)(win->m_hAdjust->value+0.5); + dir = wxHORIZONTAL; + } + if (widget == GTK_RANGE(scrolledWindow->vscrollbar)) + { + value = (int)(win->m_vAdjust->value+0.5); + dir = wxVERTICAL; + } + + wxScrollWinEvent event( command, value, dir ); + event.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( event ); + } + + win->m_isScrolling = FALSE; + + return FALSE; +} + //----------------------------------------------------------------------------- // InsertChild for wxScrolledWindow //----------------------------------------------------------------------------- @@ -137,6 +198,7 @@ void wxScrolledWindow::Init() m_targetWindow = (wxWindow*) NULL; m_scaleX = 1.0; m_scaleY = 1.0; + m_hasScrolling = TRUE; } bool wxScrolledWindow::Create(wxWindow *parent, @@ -156,7 +218,7 @@ bool wxScrolledWindow::Create(wxWindow *parent, } m_insertCallback = wxInsertChildInScrolledWindow; - + m_targetWindow = this; m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); @@ -216,10 +278,28 @@ bool wxScrolledWindow::Create(wxWindow *parent, GtkVConnectEvent(); GtkHConnectEvent(); + // these handlers block mouse events to any window during scrolling such as + // motion events and prevent GTK and wxWindows from fighting over where the + // slider should be + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", + (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event", + (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event", + (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event", + (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); + gtk_widget_show( m_wxwindow ); if (m_parent) m_parent->DoAddChild( this ); + + m_focusWidget = m_wxwindow; PostCreation(); @@ -240,13 +320,16 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX, int noUnitsY, int xPos, int yPos, bool noRefresh ) { + int old_x = m_xScrollPixelsPerLine * m_xScrollPosition; + int old_y = m_yScrollPixelsPerLine * m_yScrollPosition; + m_xScrollPixelsPerLine = pixelsPerUnitX; m_yScrollPixelsPerLine = pixelsPerUnitY; - m_xScrollPosition = xPos; - m_yScrollPosition = yPos; m_xScrollLines = noUnitsX; m_yScrollLines = noUnitsY; - + m_xScrollPosition = xPos; + m_yScrollPosition = yPos; + m_hAdjust->lower = 0.0; m_hAdjust->upper = noUnitsX; m_hAdjust->value = xPos; @@ -260,26 +343,34 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, m_vAdjust->page_increment = 2.0; AdjustScrollbars(); + + if (!noRefresh) + { + int new_x = m_xScrollPixelsPerLine * m_xScrollPosition; + int new_y = m_yScrollPixelsPerLine * m_yScrollPosition; + + m_targetWindow->ScrollWindow( old_x-new_x, old_y-new_y ); + } } void wxScrolledWindow::AdjustScrollbars() { int w, h; m_targetWindow->GetClientSize( &w, &h ); - + if (m_xScrollPixelsPerLine == 0) m_hAdjust->page_size = 1.0; else m_hAdjust->page_size = (w / m_xScrollPixelsPerLine); - + if (m_yScrollPixelsPerLine == 0) m_vAdjust->page_size = 1.0; else m_vAdjust->page_size = (h / m_yScrollPixelsPerLine); - + m_xScrollLinesPerPage = (int)(m_hAdjust->page_size + 0.5); m_yScrollLinesPerPage = (int)(m_vAdjust->page_size + 0.5); - + gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); } @@ -288,7 +379,7 @@ void wxScrolledWindow::AdjustScrollbars() // target window handling // ---------------------------------------------------------------------------- -void wxScrolledWindow::SetTargetWindow( wxWindow *target ) +void wxScrolledWindow::SetTargetWindow( wxWindow *target, bool WXUNUSED(pushEventHandler) ) { wxASSERT_MSG( target, wxT("target window must not be NULL") ); m_targetWindow = target; @@ -388,32 +479,32 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) if (max < 0) max = 0; if (x_pos > max) x_pos = max; if (x_pos < 0) x_pos = 0; - + int old_x = m_xScrollPosition; m_xScrollPosition = x_pos; m_hAdjust->value = x_pos; - + m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); - + // Just update the scrollbar, don't send any wxWindows event GtkHDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); GtkHConnectEvent(); } - + if ((y_pos != -1) && (m_yScrollPixelsPerLine)) { int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); if (max < 0) max = 0; if (y_pos > max) y_pos = max; if (y_pos < 0) y_pos = 0; - + int old_y = m_yScrollPosition; m_yScrollPosition = y_pos; m_vAdjust->value = y_pos; - + m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); - + // Just update the scrollbar, don't send any wxWindows event GtkVDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); @@ -428,15 +519,15 @@ void wxScrolledWindow::GtkVScroll( float value ) if (m_yScrollPixelsPerLine == 0) return; - + int y_pos = (int)(value+0.5); - + if (y_pos == m_yScrollPosition) return; - + GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); GtkRange *range = GTK_RANGE(scrolledWindow->vscrollbar); - + wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; @@ -452,10 +543,10 @@ void wxScrolledWindow::GtkHScroll( float value ) { if (!m_targetWindow) return; - + if (m_xScrollPixelsPerLine == 0) return; - + int x_pos = (int)(value+0.5); if (x_pos == m_xScrollPosition) @@ -463,7 +554,7 @@ void wxScrolledWindow::GtkHScroll( float value ) GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); GtkRange *range = GTK_RANGE(scrolledWindow->hscrollbar); - + wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; @@ -599,7 +690,7 @@ int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) return nScrollInc; } -void wxScrolledWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) +void wxScrolledWindow::SetScrollPos( int orient, int pos, bool refresh ) { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); @@ -609,10 +700,10 @@ void wxScrolledWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) { int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); if (max < 0) max = 0; - + if (pos > max) pos = 0; if (pos < 0) pos = 0; - + if (pos == (int)(m_hAdjust->value+0.5)) return; m_hAdjust->value = pos; } @@ -620,10 +711,10 @@ void wxScrolledWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) { int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); if (max < 0) max = 0; - + if (pos > max) pos = 0; if (pos < 0) pos = 0; - + if (pos == (int)(m_vAdjust->value+0.5)) return; m_vAdjust->value = pos; } @@ -731,6 +822,9 @@ void wxScrolledWindow::OnChar(wxKeyEvent& event) szy = -1; } + int xScrollOld = GetScrollPos(wxHORIZONTAL), + yScrollOld = GetScrollPos(wxVERTICAL); + int dsty; switch ( event.KeyCode() ) { @@ -772,5 +866,25 @@ void wxScrolledWindow::OnChar(wxKeyEvent& event) default: // not for us event.Skip(); + return; + } + + int xScroll = GetScrollPos(wxHORIZONTAL); + if ( xScroll != xScrollOld ) + { + wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, xScroll, + wxHORIZONTAL); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + } + + int yScroll = GetScrollPos(wxVERTICAL); + if ( yScroll != yScrollOld ) + { + wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, yScroll, + wxVERTICAL); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); } } +