From c918b2cda24daa062cc5fe4f5dd1dbd4fb6edaa3 Mon Sep 17 00:00:00 2001 From: Paul Cornett Date: Thu, 8 Jun 2006 05:16:25 +0000 Subject: [PATCH] use "event-after" signal to send thumb release event git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39626 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/gtk/scrolbar.cpp | 45 +++++++++++++++++++++++++++++++++----------- src/gtk/slider.cpp | 44 ++++++++++++++++++++++++------------------- src/gtk/window.cpp | 33 ++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/gtk/scrolbar.cpp b/src/gtk/scrolbar.cpp index cf66761a5d..d0a691baea 100644 --- a/src/gtk/scrolbar.cpp +++ b/src/gtk/scrolbar.cpp @@ -64,13 +64,39 @@ gtk_button_press_event(GtkRange*, GdkEventButton*, wxScrollBar* win) } } +//----------------------------------------------------------------------------- +// "event_after" from scrollbar +//----------------------------------------------------------------------------- + +extern "C" { +static void +gtk_event_after(GtkRange* range, GdkEvent* event, wxScrollBar* win) +{ + if (event->type == GDK_BUTTON_RELEASE) + { + g_signal_handlers_block_by_func(range, (void*)gtk_event_after, win); + + const int value = win->GetThumbPosition(); + const int orient = win->HasFlag(wxSB_VERTICAL) ? wxVERTICAL : wxHORIZONTAL; + + wxScrollEvent event(wxEVT_SCROLL_THUMBRELEASE, win->GetId(), value, orient); + event.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(event); + + wxScrollEvent event2(wxEVT_SCROLL_CHANGED, win->GetId(), value, orient); + event2.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(event2); + } +} +} + //----------------------------------------------------------------------------- // "button_release_event" from scrollbar //----------------------------------------------------------------------------- extern "C" { static gboolean -gtk_button_release_event(GtkRange*, GdkEventButton*, wxScrollBar* win) +gtk_button_release_event(GtkRange* range, GdkEventButton*, wxScrollBar* win) { if (g_isIdle) wxapp_install_idle_handler(); @@ -80,18 +106,10 @@ gtk_button_release_event(GtkRange*, GdkEventButton*, wxScrollBar* win) if (win->m_isScrolling) { win->m_isScrolling = false; - const int value = win->GetThumbPosition(); - const int orient = win->HasFlag(wxSB_VERTICAL) ? wxVERTICAL : wxHORIZONTAL; - - wxScrollEvent event(wxEVT_SCROLL_THUMBRELEASE, win->GetId(), value, orient); - event.SetEventObject(win); + // Hook up handler to send thumb release event after this emission is finished. // To allow setting scroll position from event handler, sending event must // be deferred until after the GtkRange handler for this signal has run - win->GetEventHandler()->AddPendingEvent(event); - - wxScrollEvent event2(wxEVT_SCROLL_CHANGED, win->GetId(), value, orient); - event2.SetEventObject(win); - win->GetEventHandler()->AddPendingEvent(event2); + g_signal_handlers_unblock_by_func(range, (void*)gtk_event_after, win); } return false; @@ -141,6 +159,11 @@ bool wxScrollBar::Create(wxWindow *parent, wxWindowID id, g_signal_connect(m_widget, "button_release_event", G_CALLBACK(gtk_button_release_event), this); + gulong handler_id; + handler_id = g_signal_connect( + m_widget, "event_after", G_CALLBACK(gtk_event_after), this); + g_signal_handler_block(m_widget, handler_id); + m_parent->DoAddChild( this ); PostCreation(size); diff --git a/src/gtk/slider.cpp b/src/gtk/slider.cpp index 1d6870feca..3eaaba17d7 100644 --- a/src/gtk/slider.cpp +++ b/src/gtk/slider.cpp @@ -219,27 +219,28 @@ gtk_button_press_event(GtkWidget*, GdkEventButton*, wxSlider* win) } } -// Single shot idle callback, to generate thumb release event, and -// truncate position to integral value. Idle callback is used -// because position cannot be changed from button release event. +//----------------------------------------------------------------------------- +// "event_after" +//----------------------------------------------------------------------------- + extern "C" { -static gboolean -idle_thumbrelease(void* data) +static void +gtk_event_after(GtkRange* range, GdkEvent* event, wxSlider* win) { - gdk_threads_enter(); - wxSlider* win = (wxSlider*)data; - win->m_isScrolling = false; - if (win->m_needThumbRelease) + if (event->type == GDK_BUTTON_RELEASE) { - win->m_needThumbRelease = false; - ProcessScrollEvent(win, wxEVT_SCROLL_THUMBRELEASE); + g_signal_handlers_block_by_func(range, (void*)gtk_event_after, win); + + if (win->m_needThumbRelease) + { + win->m_needThumbRelease = false; + ProcessScrollEvent(win, wxEVT_SCROLL_THUMBRELEASE); + } + // Keep slider at an integral position + win->BlockScrollEvent(); + gtk_range_set_value((GtkRange*)win->m_widget, win->GetValue()); + win->UnblockScrollEvent(); } - // Keep slider at an integral position - win->BlockScrollEvent(); - gtk_range_set_value((GtkRange*)win->m_widget, win->GetValue()); - win->UnblockScrollEvent(); - gdk_threads_leave(); - return false; } } @@ -249,12 +250,13 @@ idle_thumbrelease(void* data) extern "C" { static gboolean -gtk_button_release_event(GtkWidget*, GdkEventButton*, wxSlider* win) +gtk_button_release_event(GtkRange* range, GdkEventButton*, wxSlider* win) { win->m_mouseButtonDown = false; if (win->m_isScrolling) { - g_idle_add(idle_thumbrelease, win); + win->m_isScrolling = false; + g_signal_handlers_unblock_by_func(range, (void*)gtk_event_after, win); } return false; } @@ -321,6 +323,10 @@ bool wxSlider::Create(wxWindow *parent, wxWindowID id, g_signal_connect(m_widget, "move_slider", G_CALLBACK(gtk_move_slider), this); g_signal_connect(m_widget, "format_value", G_CALLBACK(gtk_format_value), NULL); g_signal_connect(m_widget, "value_changed", G_CALLBACK(gtk_value_changed), this); + gulong handler_id; + handler_id = g_signal_connect( + m_widget, "event_after", G_CALLBACK(gtk_event_after), this); + g_signal_handler_block(m_widget, handler_id); SetRange( minValue, maxValue ); SetValue( value ); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 27f4b8f458..ab839de36c 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -2131,6 +2131,26 @@ gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win) } } +//----------------------------------------------------------------------------- +// "event_after" from scrollbar +//----------------------------------------------------------------------------- + +extern "C" { +static void +gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win) +{ + if (event->type == GDK_BUTTON_RELEASE) + { + g_signal_handlers_block_by_func(range, (void*)gtk_scrollbar_event_after, win); + + const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL; + wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient); + event.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(event); + } +} +} + //----------------------------------------------------------------------------- // "button_release_event" from scrollbar //----------------------------------------------------------------------------- @@ -2147,12 +2167,10 @@ gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* w if (win->m_isScrolling) { win->m_isScrolling = false; - const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL; - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient); - event.SetEventObject(win); + // Hook up handler to send thumb release event after this emission is finished. // To allow setting scroll position from event handler, sending event must // be deferred until after the GtkRange handler for this signal has run - win->GetEventHandler()->AddPendingEvent(event); + g_signal_handlers_unblock_by_func(range, (void*)gtk_scrollbar_event_after, win); } return false; @@ -2569,6 +2587,13 @@ bool wxWindowGTK::Create( wxWindow *parent, 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 -- 2.45.2