+
+#ifndef WX_PRECOMP
+ #include "wx/utils.h"
+#endif
+
+#include "wx/gtk/private.h"
+
+//-----------------------------------------------------------------------------
+// "value_changed" from scrollbar
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_value_changed(GtkRange* range, wxScrollBar* win)
+{
+ wxEventType eventType = win->GTKGetScrollEventType(range);
+ if (eventType != wxEVT_NULL)
+ {
+ const int orient = win->HasFlag(wxSB_VERTICAL) ? wxVERTICAL : wxHORIZONTAL;
+ const int value = win->GetThumbPosition();
+ const int id = win->GetId();
+
+ // first send the specific event for the user action
+ wxScrollEvent evtSpec(eventType, id, value, orient);
+ evtSpec.SetEventObject(win);
+ win->HandleWindowEvent(evtSpec);
+
+ if (!win->m_isScrolling)
+ {
+ // and if it's over also send a general "changed" event
+ wxScrollEvent evtChanged(wxEVT_SCROLL_CHANGED, id, value, orient);
+ evtChanged.SetEventObject(win);
+ win->HandleWindowEvent(evtChanged);
+ }
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// "button_press_event" from scrollbar
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gboolean
+gtk_button_press_event(GtkRange*, GdkEventButton*, wxScrollBar* win)
+{
+ win->m_mouseButtonDown = true;
+ return false;
+}
+}
+
+//-----------------------------------------------------------------------------
+// "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;
+ const int id = win->GetId();
+
+ wxScrollEvent evtRel(wxEVT_SCROLL_THUMBRELEASE, id, value, orient);
+ evtRel.SetEventObject(win);
+ win->HandleWindowEvent(evtRel);
+
+ wxScrollEvent evtChanged(wxEVT_SCROLL_CHANGED, id, value, orient);
+ evtChanged.SetEventObject(win);
+ win->HandleWindowEvent(evtChanged);
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// "button_release_event" from scrollbar
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gboolean
+gtk_button_release_event(GtkRange* range, GdkEventButton*, wxScrollBar* win)
+{
+ win->m_mouseButtonDown = false;
+ // If thumb tracking
+ if (win->m_isScrolling)
+ {
+ win->m_isScrolling = false;
+ // 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
+ g_signal_handlers_unblock_by_func(range, (void*)gtk_event_after, win);
+ }
+
+ return false;
+}
+}