|
|
6f4496d |
From fa929caca17523110eea3b0bab315d400d447652 Mon Sep 17 00:00:00 2001
|
|
|
1835cbd |
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
|
|
1835cbd |
Date: Thu, 18 May 2017 15:05:27 +0100
|
|
|
1835cbd |
Subject: [PATCH] Related: rhbz#1367846 queue and merge scroll events
|
|
|
1835cbd |
MIME-Version: 1.0
|
|
|
1835cbd |
Content-Type: text/plain; charset=UTF-8
|
|
|
1835cbd |
Content-Transfer-Encoding: 8bit
|
|
|
1835cbd |
|
|
|
1835cbd |
Reviewed-on: https://gerrit.libreoffice.org/37779
|
|
|
1835cbd |
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
|
|
|
1835cbd |
Tested-by: Caolán McNamara <caolanm@redhat.com>
|
|
|
1835cbd |
(cherry picked from commit 7f60978b2ccd0e17816b78bde60c6e0e60a9d52e)
|
|
|
1835cbd |
|
|
|
1835cbd |
Change-Id: Ib45f61bbb35bd240829491ac8a79803222974778
|
|
|
1835cbd |
---
|
|
|
1835cbd |
vcl/inc/unx/gtk/gtkframe.hxx | 8 ++-
|
|
|
1835cbd |
vcl/unx/gtk/gtksalframe.cxx | 15 ++---
|
|
|
6f4496d |
vcl/unx/gtk3/gtk3gtkframe.cxx | 133 ++++++++++++++++++++++++++++++------------
|
|
|
6f4496d |
3 files changed, 112 insertions(+), 44 deletions(-)
|
|
|
1835cbd |
|
|
|
1835cbd |
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
|
|
|
1835cbd |
index 874566d..907757b 100644
|
|
|
1835cbd |
--- a/vcl/inc/unx/gtk/gtkframe.hxx
|
|
|
1835cbd |
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
|
|
|
1835cbd |
@@ -32,6 +32,7 @@
|
|
|
1835cbd |
#include <gdk/gdkkeysyms.h>
|
|
|
1835cbd |
|
|
|
1835cbd |
#include <salframe.hxx>
|
|
|
1835cbd |
+#include <vcl/idle.hxx>
|
|
|
1835cbd |
#include <vcl/sysdata.hxx>
|
|
|
1835cbd |
#include <unx/nativewindowhandleprovider.hxx>
|
|
|
1835cbd |
#include <unx/saltype.h>
|
|
|
1835cbd |
@@ -284,7 +285,7 @@ class GtkSalFrame : public SalFrame
|
|
|
1835cbd |
static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer );
|
|
|
1835cbd |
static gboolean signalDelete( GtkWidget*, GdkEvent*, gpointer );
|
|
|
1835cbd |
static gboolean signalWindowState( GtkWidget*, GdkEvent*, gpointer );
|
|
|
1835cbd |
- static gboolean signalScroll( GtkWidget*, GdkEventScroll*, gpointer );
|
|
|
1835cbd |
+ static gboolean signalScroll( GtkWidget*, GdkEvent*, gpointer );
|
|
|
1835cbd |
static gboolean signalCrossing( GtkWidget*, GdkEventCrossing*, gpointer );
|
|
|
1835cbd |
static gboolean signalVisibility( GtkWidget*, GdkEventVisibility*, gpointer );
|
|
|
1835cbd |
static void signalDestroy( GtkWidget*, gpointer );
|
|
|
1835cbd |
@@ -354,6 +355,8 @@ public:
|
|
|
1835cbd |
#if GTK_CHECK_VERSION(3,0,0)
|
|
|
1835cbd |
cairo_surface_t* m_pSurface;
|
|
|
1835cbd |
DamageHandler m_aDamageHandler;
|
|
|
1835cbd |
+ std::vector<GdkEvent*> m_aPendingScrollEvents;
|
|
|
1835cbd |
+ Idle m_aSmoothScrollIdle;
|
|
|
1835cbd |
bool m_bSalObjectSetPosSize;
|
|
|
1835cbd |
#endif
|
|
|
1835cbd |
GtkSalFrame( SalFrame* pParent, SalFrameStyleFlags nStyle );
|
|
|
1835cbd |
@@ -433,6 +436,9 @@ public:
|
|
|
1835cbd |
static void closePopup();
|
|
|
1835cbd |
|
|
|
1835cbd |
void nopaint_container_resize_children(GtkContainer*);
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ void LaunchAsyncScroll(GdkEvent* pEvent);
|
|
|
1835cbd |
+ DECL_LINK_TYPED(AsyncScroll, Idle *, void);
|
|
|
1835cbd |
#endif
|
|
|
1835cbd |
virtual ~GtkSalFrame();
|
|
|
1835cbd |
|
|
|
1835cbd |
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
|
|
|
1835cbd |
index b56c899..81c3cba 100644
|
|
|
1835cbd |
--- a/vcl/unx/gtk/gtksalframe.cxx
|
|
|
1835cbd |
+++ b/vcl/unx/gtk/gtksalframe.cxx
|
|
|
1835cbd |
@@ -2827,8 +2827,9 @@ gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer
|
|
|
1835cbd |
return true;
|
|
|
1835cbd |
}
|
|
|
1835cbd |
|
|
|
1835cbd |
-gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEventScroll* pEvent, gpointer frame )
|
|
|
1835cbd |
+gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEvent* pInEvent, gpointer frame)
|
|
|
1835cbd |
{
|
|
|
1835cbd |
+ GdkEventScroll& rEvent = pInEvent->scroll;
|
|
|
1835cbd |
GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
|
|
|
1835cbd |
|
|
|
1835cbd |
static sal_uLong nLines = 0;
|
|
|
1835cbd |
@@ -2840,16 +2841,16 @@ gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEventScroll* pEvent, gpointer
|
|
|
1835cbd |
nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
|
|
|
1835cbd |
}
|
|
|
1835cbd |
|
|
|
1835cbd |
- bool bNeg = (pEvent->direction == GDK_SCROLL_DOWN || pEvent->direction == GDK_SCROLL_RIGHT );
|
|
|
1835cbd |
+ bool bNeg = (rEvent.direction == GDK_SCROLL_DOWN || rEvent.direction == GDK_SCROLL_RIGHT );
|
|
|
1835cbd |
SalWheelMouseEvent aEvent;
|
|
|
1835cbd |
- aEvent.mnTime = pEvent->time;
|
|
|
1835cbd |
- aEvent.mnX = (sal_uLong)pEvent->x;
|
|
|
1835cbd |
- aEvent.mnY = (sal_uLong)pEvent->y;
|
|
|
1835cbd |
+ aEvent.mnTime = rEvent.time;
|
|
|
1835cbd |
+ aEvent.mnX = (sal_uLong)rEvent.x;
|
|
|
1835cbd |
+ aEvent.mnY = (sal_uLong)rEvent.y;
|
|
|
1835cbd |
aEvent.mnDelta = bNeg ? -120 : 120;
|
|
|
1835cbd |
aEvent.mnNotchDelta = bNeg ? -1 : 1;
|
|
|
1835cbd |
aEvent.mnScrollLines = nLines;
|
|
|
1835cbd |
- aEvent.mnCode = GetMouseModCode( pEvent->state );
|
|
|
1835cbd |
- aEvent.mbHorz = (pEvent->direction == GDK_SCROLL_LEFT || pEvent->direction == GDK_SCROLL_RIGHT);
|
|
|
1835cbd |
+ aEvent.mnCode = GetMouseModCode( rEvent.state );
|
|
|
1835cbd |
+ aEvent.mbHorz = (rEvent.direction == GDK_SCROLL_LEFT || rEvent.direction == GDK_SCROLL_RIGHT);
|
|
|
1835cbd |
|
|
|
1835cbd |
// --- RTL --- (mirror mouse pos)
|
|
|
1835cbd |
if( AllSettings::GetLayoutRTL() )
|
|
|
1835cbd |
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
|
|
|
6f4496d |
index 5bed078..b47dd88 100644
|
|
|
1835cbd |
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
|
|
|
1835cbd |
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
|
|
|
1835cbd |
@@ -781,6 +781,9 @@ void GtkSalFrame::InvalidateGraphics()
|
|
|
1835cbd |
|
|
|
1835cbd |
GtkSalFrame::~GtkSalFrame()
|
|
|
1835cbd |
{
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.Stop();
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.SetIdleHdl(Link<Idle *, void>());
|
|
|
1835cbd |
+
|
|
|
1835cbd |
if (m_pDropTarget)
|
|
|
1835cbd |
{
|
|
|
1835cbd |
m_pDropTarget->deinitialize();
|
|
|
1835cbd |
@@ -965,6 +968,8 @@ void GtkSalFrame::InitCommon()
|
|
|
1835cbd |
m_aDamageHandler.handle = this;
|
|
|
1835cbd |
m_aDamageHandler.damaged = ::damaged;
|
|
|
1835cbd |
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.SetIdleHdl(LINK(this, GtkSalFrame, AsyncScroll));
|
|
|
1835cbd |
+
|
|
|
1835cbd |
m_pTopLevelGrid = GTK_GRID(gtk_grid_new());
|
|
|
1835cbd |
gtk_container_add(GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pTopLevelGrid));
|
|
|
1835cbd |
|
|
|
6f4496d |
@@ -2665,53 +2670,107 @@ gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer
|
|
|
1835cbd |
return true;
|
|
|
1835cbd |
}
|
|
|
1835cbd |
|
|
|
1835cbd |
-gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEventScroll* pEvent, gpointer frame)
|
|
|
1835cbd |
+void GtkSalFrame::LaunchAsyncScroll(GdkEvent* pEvent)
|
|
|
1835cbd |
{
|
|
|
1835cbd |
- UpdateLastInputEventTime(pEvent->time);
|
|
|
1835cbd |
-
|
|
|
1835cbd |
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
|
|
|
1835cbd |
+ //if we don't match previous pending states, flush that queue now
|
|
|
1835cbd |
+ if (!m_aPendingScrollEvents.empty() && pEvent->scroll.state != m_aPendingScrollEvents.back()->scroll.state)
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.Stop();
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.Invoke();
|
|
|
1835cbd |
+ assert(m_aPendingScrollEvents.empty());
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
+ //add scroll event to queue
|
|
|
1835cbd |
+ m_aPendingScrollEvents.push_back(gdk_event_copy(pEvent));
|
|
|
1835cbd |
+ if (!m_aSmoothScrollIdle.IsActive())
|
|
|
1835cbd |
+ m_aSmoothScrollIdle.Start();
|
|
|
1835cbd |
+}
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+IMPL_LINK_NOARG_TYPED(GtkSalFrame, AsyncScroll, Idle *, void)
|
|
|
1835cbd |
+{
|
|
|
1835cbd |
+ assert(!m_aPendingScrollEvents.empty());
|
|
|
1835cbd |
|
|
|
1835cbd |
SalWheelMouseEvent aEvent;
|
|
|
1835cbd |
|
|
|
1835cbd |
- aEvent.mnTime = pEvent->time;
|
|
|
1835cbd |
- aEvent.mnX = (sal_uLong)pEvent->x;
|
|
|
1835cbd |
+ GdkEvent* pEvent = m_aPendingScrollEvents.back();
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ aEvent.mnTime = pEvent->scroll.time;
|
|
|
1835cbd |
+ aEvent.mnX = (sal_uLong)pEvent->scroll.x;
|
|
|
1835cbd |
// --- RTL --- (mirror mouse pos)
|
|
|
1835cbd |
if (AllSettings::GetLayoutRTL())
|
|
|
1835cbd |
- aEvent.mnX = pThis->maGeometry.nWidth - 1 - aEvent.mnX;
|
|
|
1835cbd |
- aEvent.mnY = (sal_uLong)pEvent->y;
|
|
|
1835cbd |
- aEvent.mnCode = GetMouseModCode( pEvent->state );
|
|
|
1835cbd |
+ aEvent.mnX = maGeometry.nWidth - 1 - aEvent.mnX;
|
|
|
1835cbd |
+ aEvent.mnY = (sal_uLong)pEvent->scroll.y;
|
|
|
1835cbd |
+ aEvent.mnCode = GetMouseModCode( pEvent->scroll.state );
|
|
|
1835cbd |
|
|
|
6f4496d |
- switch (pEvent->direction)
|
|
|
1835cbd |
+ double delta_x(0.0), delta_y(0.0);
|
|
|
1835cbd |
+ for (auto pSubEvent : m_aPendingScrollEvents)
|
|
|
1835cbd |
{
|
|
|
1835cbd |
- case GDK_SCROLL_SMOOTH:
|
|
|
1835cbd |
- // rhbz#1344042 "Traditionally" in gtk3 we tool a single up/down event as
|
|
|
1835cbd |
- // equating to 3 scroll lines and a delta of 120. So scale the delta here
|
|
|
1835cbd |
- // by 120 where a single mouse wheel click is an incoming delta_x of 1
|
|
|
1835cbd |
- // and divide that by 40 to get the number of scrollines
|
|
|
1835cbd |
- if (pEvent->delta_x != 0.0)
|
|
|
1835cbd |
- {
|
|
|
1835cbd |
- aEvent.mnDelta = -pEvent->delta_x * 120;
|
|
|
1835cbd |
- aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1;
|
|
|
1835cbd |
- if (aEvent.mnDelta == 0)
|
|
|
1835cbd |
- aEvent.mnDelta = aEvent.mnNotchDelta;
|
|
|
1835cbd |
- aEvent.mbHorz = true;
|
|
|
1835cbd |
- aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0;
|
|
|
1835cbd |
- pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent);
|
|
|
1835cbd |
- }
|
|
|
1835cbd |
+ delta_x += pSubEvent->scroll.delta_x;
|
|
|
1835cbd |
+ delta_y += pSubEvent->scroll.delta_y;
|
|
|
1835cbd |
+ gdk_event_free(pSubEvent);
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
+ m_aPendingScrollEvents.clear();
|
|
|
1835cbd |
|
|
|
1835cbd |
- if (pEvent->delta_y != 0.0)
|
|
|
1835cbd |
- {
|
|
|
1835cbd |
- aEvent.mnDelta = -pEvent->delta_y * 120;
|
|
|
1835cbd |
- aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1;
|
|
|
1835cbd |
- if (aEvent.mnDelta == 0)
|
|
|
1835cbd |
- aEvent.mnDelta = aEvent.mnNotchDelta;
|
|
|
1835cbd |
- aEvent.mbHorz = false;
|
|
|
1835cbd |
- aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0;
|
|
|
1835cbd |
- pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent);
|
|
|
1835cbd |
- }
|
|
|
1835cbd |
+ // rhbz#1344042 "Traditionally" in gtk3 we tool a single up/down event as
|
|
|
1835cbd |
+ // equating to 3 scroll lines and a delta of 120. So scale the delta here
|
|
|
1835cbd |
+ // by 120 where a single mouse wheel click is an incoming delta_x of 1
|
|
|
1835cbd |
+ // and divide that by 40 to get the number of scroll lines
|
|
|
1835cbd |
+ if (delta_x != 0.0)
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
+ aEvent.mnDelta = -delta_x * 120;
|
|
|
1835cbd |
+ aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1;
|
|
|
1835cbd |
+ if (aEvent.mnDelta == 0)
|
|
|
1835cbd |
+ aEvent.mnDelta = aEvent.mnNotchDelta;
|
|
|
1835cbd |
+ aEvent.mbHorz = true;
|
|
|
1835cbd |
+ aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0;
|
|
|
1835cbd |
+ CallCallback(SalEvent::WheelMouse, &aEvent);
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
|
|
|
1835cbd |
- break;
|
|
|
1835cbd |
+ if (delta_y != 0.0)
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
+ aEvent.mnDelta = -delta_y * 120;
|
|
|
1835cbd |
+ aEvent.mnNotchDelta = aEvent.mnDelta < 0 ? -1 : +1;
|
|
|
1835cbd |
+ if (aEvent.mnDelta == 0)
|
|
|
1835cbd |
+ aEvent.mnDelta = aEvent.mnNotchDelta;
|
|
|
1835cbd |
+ aEvent.mbHorz = false;
|
|
|
1835cbd |
+ aEvent.mnScrollLines = std::abs(aEvent.mnDelta) / 40.0;
|
|
|
1835cbd |
+ CallCallback(SalEvent::WheelMouse, &aEvent);
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
+}
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEvent* pInEvent, gpointer frame)
|
|
|
1835cbd |
+{
|
|
|
1835cbd |
+ GdkEventScroll& rEvent = pInEvent->scroll;
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ UpdateLastInputEventTime(rEvent.time);
|
|
|
1835cbd |
|
|
|
1835cbd |
+ GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ if (rEvent.direction == GDK_SCROLL_SMOOTH)
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
+ pThis->LaunchAsyncScroll(pInEvent);
|
|
|
1835cbd |
+ return true;
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ //if we have smooth scrolling previous pending states, flush that queue now
|
|
|
1835cbd |
+ if (!pThis->m_aPendingScrollEvents.empty())
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
+ pThis->m_aSmoothScrollIdle.Stop();
|
|
|
1835cbd |
+ pThis->m_aSmoothScrollIdle.Invoke();
|
|
|
1835cbd |
+ assert(pThis->m_aPendingScrollEvents.empty());
|
|
|
1835cbd |
+ }
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ SalWheelMouseEvent aEvent;
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ aEvent.mnTime = rEvent.time;
|
|
|
1835cbd |
+ aEvent.mnX = (sal_uLong)rEvent.x;
|
|
|
1835cbd |
+ // --- RTL --- (mirror mouse pos)
|
|
|
1835cbd |
+ if (AllSettings::GetLayoutRTL())
|
|
|
1835cbd |
+ aEvent.mnX = pThis->maGeometry.nWidth - 1 - aEvent.mnX;
|
|
|
1835cbd |
+ aEvent.mnY = (sal_uLong)rEvent.y;
|
|
|
1835cbd |
+ aEvent.mnCode = GetMouseModCode(rEvent.state);
|
|
|
1835cbd |
+
|
|
|
1835cbd |
+ switch (rEvent.direction)
|
|
|
1835cbd |
+ {
|
|
|
1835cbd |
case GDK_SCROLL_UP:
|
|
|
1835cbd |
aEvent.mnDelta = 120;
|
|
|
1835cbd |
aEvent.mnNotchDelta = 1;
|
|
|
6f4496d |
@@ -2743,6 +2802,8 @@ gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEventScroll* pEvent, gpointer
|
|
|
1835cbd |
aEvent.mbHorz = true;
|
|
|
1835cbd |
pThis->CallCallbackExc(SalEvent::WheelMouse, &aEvent);
|
|
|
1835cbd |
break;
|
|
|
1835cbd |
+ default:
|
|
|
1835cbd |
+ break;
|
|
|
1835cbd |
}
|
|
|
1835cbd |
|
|
|
1835cbd |
return true;
|
|
|
1835cbd |
--
|
|
|
1835cbd |
2.9.3
|
|
|
1835cbd |
|