diff options
author | Caolán McNamara <caolanm@redhat.com> | 2017-05-18 15:05:27 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2017-05-18 16:23:30 +0200 |
commit | 8b6a29398315bf7a0b1a7d54b18d3902cb8e9dfa (patch) | |
tree | 46c6de52e9406a26633026058eff8c73176d29cb /vcl | |
parent | 70ca2d0bc42a0360055b9c54e6e5edd3ef9317b8 (diff) |
Related: rhbz#1367846 queue and merge scroll events
Change-Id: Ib45f61bbb35bd240829491ac8a79803222974778
Reviewed-on: https://gerrit.libreoffice.org/37780
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 9 | ||||
-rw-r--r-- | vcl/unx/gtk/gtksalframe.cxx | 15 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkframe.cxx | 131 |
3 files changed, 112 insertions, 43 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index 00a687422f82..37a4facabd0c 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -30,6 +30,7 @@ #include <gdk/gdkkeysyms.h> #include <salframe.hxx> +#include <vcl/idle.hxx> #include <vcl/sysdata.hxx> #include <unx/nativewindowhandleprovider.hxx> #include <unx/saltype.h> @@ -280,7 +281,7 @@ class GtkSalFrame : public SalFrame static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer ); static gboolean signalDelete( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalWindowState( GtkWidget*, GdkEvent*, gpointer ); - static gboolean signalScroll( GtkWidget*, GdkEventScroll*, gpointer ); + static gboolean signalScroll( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalCrossing( GtkWidget*, GdkEventCrossing*, gpointer ); static gboolean signalVisibility( GtkWidget*, GdkEventVisibility*, gpointer ); static void signalDestroy( GtkWidget*, gpointer ); @@ -347,6 +348,8 @@ public: cairo_surface_t* m_pSurface; basegfx::B2IVector m_aFrameSize; DamageHandler m_aDamageHandler; + std::vector<GdkEvent*> m_aPendingScrollEvents; + Idle m_aSmoothScrollIdle; int m_nGrabLevel; bool m_bSalObjectSetPosSize; #endif @@ -427,6 +430,10 @@ public: void removeGrabLevel(); void nopaint_container_resize_children(GtkContainer*); + + void LaunchAsyncScroll(GdkEvent* pEvent); + DECL_LINK(AsyncScroll, Timer *, void); + #endif virtual ~GtkSalFrame() override; diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx index 02e06ae8c053..f32e49ad4f7b 100644 --- a/vcl/unx/gtk/gtksalframe.cxx +++ b/vcl/unx/gtk/gtksalframe.cxx @@ -2782,8 +2782,9 @@ gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer return true; } -gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEventScroll* pEvent, gpointer frame ) +gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEvent* pInEvent, gpointer frame) { + GdkEventScroll& rEvent = pInEvent->scroll; GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); static sal_uLong nLines = 0; @@ -2795,16 +2796,16 @@ gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEventScroll* pEvent, gpointer nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; } - bool bNeg = (pEvent->direction == GDK_SCROLL_DOWN || pEvent->direction == GDK_SCROLL_RIGHT ); + bool bNeg = (rEvent.direction == GDK_SCROLL_DOWN || rEvent.direction == GDK_SCROLL_RIGHT ); SalWheelMouseEvent aEvent; - aEvent.mnTime = pEvent->time; - aEvent.mnX = (sal_uLong)pEvent->x; - aEvent.mnY = (sal_uLong)pEvent->y; + aEvent.mnTime = rEvent.time; + aEvent.mnX = (sal_uLong)rEvent.x; + aEvent.mnY = (sal_uLong)rEvent.y; aEvent.mnDelta = bNeg ? -120 : 120; aEvent.mnNotchDelta = bNeg ? -1 : 1; aEvent.mnScrollLines = nLines; - aEvent.mnCode = GetMouseModCode( pEvent->state ); - aEvent.mbHorz = (pEvent->direction == GDK_SCROLL_LEFT || pEvent->direction == GDK_SCROLL_RIGHT); + aEvent.mnCode = GetMouseModCode( rEvent.state ); + aEvent.mbHorz = (rEvent.direction == GDK_SCROLL_LEFT || rEvent.direction == GDK_SCROLL_RIGHT); if( AllSettings::GetLayoutRTL() ) aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX; diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index bc19821cbdf5..30a729c5cbcc 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -807,6 +807,9 @@ void GtkSalFrame::InvalidateGraphics() GtkSalFrame::~GtkSalFrame() { + m_aSmoothScrollIdle.Stop(); + m_aSmoothScrollIdle.ClearInvokeHandler(); + if (m_pDropTarget) { m_pDropTarget->deinitialize(); @@ -992,6 +995,8 @@ void GtkSalFrame::InitCommon() m_aDamageHandler.handle = this; m_aDamageHandler.damaged = ::damaged; + m_aSmoothScrollIdle.SetInvokeHandler(LINK(this, GtkSalFrame, AsyncScroll)); + m_pTopLevelGrid = GTK_GRID(gtk_grid_new()); gtk_container_add(GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pTopLevelGrid)); @@ -2653,53 +2658,107 @@ gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer return true; } -gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEventScroll* pEvent, gpointer frame) +void GtkSalFrame::LaunchAsyncScroll(GdkEvent* pEvent) { - UpdateLastInputEventTime(pEvent->time); + //if we don't match previous pending states, flush that queue now + if (!m_aPendingScrollEvents.empty() && pEvent->scroll.state != m_aPendingScrollEvents.back()->scroll.state) + { + m_aSmoothScrollIdle.Stop(); + m_aSmoothScrollIdle.Invoke(); + assert(m_aPendingScrollEvents.empty()); + } + //add scroll event to queue + m_aPendingScrollEvents.push_back(gdk_event_copy(pEvent)); + if (!m_aSmoothScrollIdle.IsActive()) + m_aSmoothScrollIdle.Start(); +} - GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); +IMPL_LINK_NOARG(GtkSalFrame, AsyncScroll, Timer *, void) +{ + assert(!m_aPendingScrollEvents.empty()); SalWheelMouseEvent aEvent; - aEvent.mnTime = pEvent->time; - aEvent.mnX = (sal_uLong)pEvent->x; + GdkEvent* pEvent = m_aPendingScrollEvents.back(); + aEvent.mnTime = pEvent->scroll.time; + aEvent.mnX = (sal_uLong)pEvent->scroll.x; + // --- RTL --- (mirror mouse pos) if (AllSettings::GetLayoutRTL()) - aEvent.mnX = pThis->maGeometry.nWidth - 1 - aEvent.mnX; - aEvent.mnY = (sal_uLong)pEvent->y; - aEvent.mnCode = GetMouseModCode( pEvent->state ); + aEvent.mnX = maGeometry.nWidth - 1 - aEvent.mnX; + aEvent.mnY = (sal_uLong)pEvent->scroll.y; + aEvent.mnCode = GetMouseModCode( pEvent->scroll.state ); - switch (pEvent->direction) + double delta_x(0.0), delta_y(0.0); + for (auto pSubEvent : m_aPendingScrollEvents) { - case GDK_SCROLL_SMOOTH: - // rhbz#1344042 "Traditionally" in gtk3 we tool a single up/down event as - // equating to 3 scroll lines and a delta of 120. So scale the delta here - // by 120 where a single mouse wheel click is an incoming delta_x of 1 - // and divide that by 40 to get the number of scroll lines - if (pEvent->delta_x != 0.0) - { - aEvent.mnDelta = -pEvent->delta_x * 120; - aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1; - if (aEvent.mnDelta == 0) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = true; - aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0; - pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent); - } + delta_x += pSubEvent->scroll.delta_x; + delta_y += pSubEvent->scroll.delta_y; + gdk_event_free(pSubEvent); + } + m_aPendingScrollEvents.clear(); - if (pEvent->delta_y != 0.0) - { - aEvent.mnDelta = -pEvent->delta_y * 120; - aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1; - if (aEvent.mnDelta == 0) - aEvent.mnDelta = aEvent.mnNotchDelta; - aEvent.mbHorz = false; - aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0; - pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent); - } + // rhbz#1344042 "Traditionally" in gtk3 we tool a single up/down event as + // equating to 3 scroll lines and a delta of 120. So scale the delta here + // by 120 where a single mouse wheel click is an incoming delta_x of 1 + // and divide that by 40 to get the number of scroll lines + if (delta_x != 0.0) + { + aEvent.mnDelta = -delta_x * 120; + aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1; + if (aEvent.mnDelta == 0) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = true; + aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0; + CallCallbackExc(SalEvent::WheelMouse, &aEvent); + } - break; + if (delta_y != 0.0) + { + aEvent.mnDelta = -delta_y * 120; + aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1; + if (aEvent.mnDelta == 0) + aEvent.mnDelta = aEvent.mnNotchDelta; + aEvent.mbHorz = false; + aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0; + CallCallbackExc(SalEvent::WheelMouse, &aEvent); + } +} +gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEvent* pInEvent, gpointer frame) +{ + GdkEventScroll& rEvent = pInEvent->scroll; + + UpdateLastInputEventTime(rEvent.time); + + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + + if (rEvent.direction == GDK_SCROLL_SMOOTH) + { + pThis->LaunchAsyncScroll(pInEvent); + return true; + } + + //if we have smooth scrolling previous pending states, flush that queue now + if (!pThis->m_aPendingScrollEvents.empty()) + { + pThis->m_aSmoothScrollIdle.Stop(); + pThis->m_aSmoothScrollIdle.Invoke(); + assert(pThis->m_aPendingScrollEvents.empty()); + } + + SalWheelMouseEvent aEvent; + + aEvent.mnTime = rEvent.time; + aEvent.mnX = (sal_uLong)rEvent.x; + // --- RTL --- (mirror mouse pos) + if (AllSettings::GetLayoutRTL()) + aEvent.mnX = pThis->maGeometry.nWidth - 1 - aEvent.mnX; + aEvent.mnY = (sal_uLong)rEvent.y; + aEvent.mnCode = GetMouseModCode(rEvent.state); + + switch (rEvent.direction) + { case GDK_SCROLL_UP: aEvent.mnDelta = 120; aEvent.mnNotchDelta = 1; @@ -2731,6 +2790,8 @@ gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEventScroll* pEvent, gpointer aEvent.mbHorz = true; pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent); break; + default: + break; } return true; |